Updated jquery(+ui) to latest stable versions
[mailer.git] / js / jquery-ui.uncompressed.js
1 /*! jQuery UI - v1.9.2 - 2012-11-23
2 * http://jqueryui.com
3 * Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.progressbar.js, jquery.ui.tabs.js
4 * Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT */
5
6 (function( $, undefined ) {
7
8 var uuid = 0,
9         runiqueId = /^ui-id-\d+$/;
10
11 // prevent duplicate loading
12 // this is only a problem because we proxy existing functions
13 // and we don't want to double proxy them
14 $.ui = $.ui || {};
15 if ( $.ui.version ) {
16         return;
17 }
18
19 $.extend( $.ui, {
20         version: "1.9.2",
21
22         keyCode: {
23                 BACKSPACE: 8,
24                 COMMA: 188,
25                 DELETE: 46,
26                 DOWN: 40,
27                 END: 35,
28                 ENTER: 13,
29                 ESCAPE: 27,
30                 HOME: 36,
31                 LEFT: 37,
32                 NUMPAD_ADD: 107,
33                 NUMPAD_DECIMAL: 110,
34                 NUMPAD_DIVIDE: 111,
35                 NUMPAD_ENTER: 108,
36                 NUMPAD_MULTIPLY: 106,
37                 NUMPAD_SUBTRACT: 109,
38                 PAGE_DOWN: 34,
39                 PAGE_UP: 33,
40                 PERIOD: 190,
41                 RIGHT: 39,
42                 SPACE: 32,
43                 TAB: 9,
44                 UP: 38
45         }
46 });
47
48 // plugins
49 $.fn.extend({
50         _focus: $.fn.focus,
51         focus: function( delay, fn ) {
52                 return typeof delay === "number" ?
53                         this.each(function() {
54                                 var elem = this;
55                                 setTimeout(function() {
56                                         $( elem ).focus();
57                                         if ( fn ) {
58                                                 fn.call( elem );
59                                         }
60                                 }, delay );
61                         }) :
62                         this._focus.apply( this, arguments );
63         },
64
65         scrollParent: function() {
66                 var scrollParent;
67                 if (($.ui.ie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
68                         scrollParent = this.parents().filter(function() {
69                                 return (/(relative|absolute|fixed)/).test($.css(this,'position')) && (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x'));
70                         }).eq(0);
71                 } else {
72                         scrollParent = this.parents().filter(function() {
73                                 return (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x'));
74                         }).eq(0);
75                 }
76
77                 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
78         },
79
80         zIndex: function( zIndex ) {
81                 if ( zIndex !== undefined ) {
82                         return this.css( "zIndex", zIndex );
83                 }
84
85                 if ( this.length ) {
86                         var elem = $( this[ 0 ] ), position, value;
87                         while ( elem.length && elem[ 0 ] !== document ) {
88                                 // Ignore z-index if position is set to a value where z-index is ignored by the browser
89                                 // This makes behavior of this function consistent across browsers
90                                 // WebKit always returns auto if the element is positioned
91                                 position = elem.css( "position" );
92                                 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
93                                         // IE returns 0 when zIndex is not specified
94                                         // other browsers return a string
95                                         // we ignore the case of nested elements with an explicit value of 0
96                                         // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
97                                         value = parseInt( elem.css( "zIndex" ), 10 );
98                                         if ( !isNaN( value ) && value !== 0 ) {
99                                                 return value;
100                                         }
101                                 }
102                                 elem = elem.parent();
103                         }
104                 }
105
106                 return 0;
107         },
108
109         uniqueId: function() {
110                 return this.each(function() {
111                         if ( !this.id ) {
112                                 this.id = "ui-id-" + (++uuid);
113                         }
114                 });
115         },
116
117         removeUniqueId: function() {
118                 return this.each(function() {
119                         if ( runiqueId.test( this.id ) ) {
120                                 $( this ).removeAttr( "id" );
121                         }
122                 });
123         }
124 });
125
126 // selectors
127 function focusable( element, isTabIndexNotNaN ) {
128         var map, mapName, img,
129                 nodeName = element.nodeName.toLowerCase();
130         if ( "area" === nodeName ) {
131                 map = element.parentNode;
132                 mapName = map.name;
133                 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
134                         return false;
135                 }
136                 img = $( "img[usemap=#" + mapName + "]" )[0];
137                 return !!img && visible( img );
138         }
139         return ( /input|select|textarea|button|object/.test( nodeName ) ?
140                 !element.disabled :
141                 "a" === nodeName ?
142                         element.href || isTabIndexNotNaN :
143                         isTabIndexNotNaN) &&
144                 // the element and all of its ancestors must be visible
145                 visible( element );
146 }
147
148 function visible( element ) {
149         return $.expr.filters.visible( element ) &&
150                 !$( element ).parents().andSelf().filter(function() {
151                         return $.css( this, "visibility" ) === "hidden";
152                 }).length;
153 }
154
155 $.extend( $.expr[ ":" ], {
156         data: $.expr.createPseudo ?
157                 $.expr.createPseudo(function( dataName ) {
158                         return function( elem ) {
159                                 return !!$.data( elem, dataName );
160                         };
161                 }) :
162                 // support: jQuery <1.8
163                 function( elem, i, match ) {
164                         return !!$.data( elem, match[ 3 ] );
165                 },
166
167         focusable: function( element ) {
168                 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
169         },
170
171         tabbable: function( element ) {
172                 var tabIndex = $.attr( element, "tabindex" ),
173                         isTabIndexNaN = isNaN( tabIndex );
174                 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
175         }
176 });
177
178 // support
179 $(function() {
180         var body = document.body,
181                 div = body.appendChild( div = document.createElement( "div" ) );
182
183         // access offsetHeight before setting the style to prevent a layout bug
184         // in IE 9 which causes the element to continue to take up space even
185         // after it is removed from the DOM (#8026)
186         div.offsetHeight;
187
188         $.extend( div.style, {
189                 minHeight: "100px",
190                 height: "auto",
191                 padding: 0,
192                 borderWidth: 0
193         });
194
195         $.support.minHeight = div.offsetHeight === 100;
196         $.support.selectstart = "onselectstart" in div;
197
198         // set display to none to avoid a layout bug in IE
199         // http://dev.jquery.com/ticket/4014
200         body.removeChild( div ).style.display = "none";
201 });
202
203 // support: jQuery <1.8
204 if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
205         $.each( [ "Width", "Height" ], function( i, name ) {
206                 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
207                         type = name.toLowerCase(),
208                         orig = {
209                                 innerWidth: $.fn.innerWidth,
210                                 innerHeight: $.fn.innerHeight,
211                                 outerWidth: $.fn.outerWidth,
212                                 outerHeight: $.fn.outerHeight
213                         };
214
215                 function reduce( elem, size, border, margin ) {
216                         $.each( side, function() {
217                                 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
218                                 if ( border ) {
219                                         size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
220                                 }
221                                 if ( margin ) {
222                                         size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
223                                 }
224                         });
225                         return size;
226                 }
227
228                 $.fn[ "inner" + name ] = function( size ) {
229                         if ( size === undefined ) {
230                                 return orig[ "inner" + name ].call( this );
231                         }
232
233                         return this.each(function() {
234                                 $( this ).css( type, reduce( this, size ) + "px" );
235                         });
236                 };
237
238                 $.fn[ "outer" + name] = function( size, margin ) {
239                         if ( typeof size !== "number" ) {
240                                 return orig[ "outer" + name ].call( this, size );
241                         }
242
243                         return this.each(function() {
244                                 $( this).css( type, reduce( this, size, true, margin ) + "px" );
245                         });
246                 };
247         });
248 }
249
250 // support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
251 if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
252         $.fn.removeData = (function( removeData ) {
253                 return function( key ) {
254                         if ( arguments.length ) {
255                                 return removeData.call( this, $.camelCase( key ) );
256                         } else {
257                                 return removeData.call( this );
258                         }
259                 };
260         })( $.fn.removeData );
261 }
262
263
264
265
266
267 // deprecated
268
269 (function() {
270         var uaMatch = /msie ([\w.]+)/.exec( navigator.userAgent.toLowerCase() ) || [];
271         $.ui.ie = uaMatch.length ? true : false;
272         $.ui.ie6 = parseFloat( uaMatch[ 1 ], 10 ) === 6;
273 })();
274
275 $.fn.extend({
276         disableSelection: function() {
277                 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
278                         ".ui-disableSelection", function( event ) {
279                                 event.preventDefault();
280                         });
281         },
282
283         enableSelection: function() {
284                 return this.unbind( ".ui-disableSelection" );
285         }
286 });
287
288 $.extend( $.ui, {
289         // $.ui.plugin is deprecated.  Use the proxy pattern instead.
290         plugin: {
291                 add: function( module, option, set ) {
292                         var i,
293                                 proto = $.ui[ module ].prototype;
294                         for ( i in set ) {
295                                 proto.plugins[ i ] = proto.plugins[ i ] || [];
296                                 proto.plugins[ i ].push( [ option, set[ i ] ] );
297                         }
298                 },
299                 call: function( instance, name, args ) {
300                         var i,
301                                 set = instance.plugins[ name ];
302                         if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
303                                 return;
304                         }
305
306                         for ( i = 0; i < set.length; i++ ) {
307                                 if ( instance.options[ set[ i ][ 0 ] ] ) {
308                                         set[ i ][ 1 ].apply( instance.element, args );
309                                 }
310                         }
311                 }
312         },
313
314         contains: $.contains,
315
316         // only used by resizable
317         hasScroll: function( el, a ) {
318
319                 //If overflow is hidden, the element might have extra content, but the user wants to hide it
320                 if ( $( el ).css( "overflow" ) === "hidden") {
321                         return false;
322                 }
323
324                 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
325                         has = false;
326
327                 if ( el[ scroll ] > 0 ) {
328                         return true;
329                 }
330
331                 // TODO: determine which cases actually cause this to happen
332                 // if the element doesn't have the scroll set, see if it's possible to
333                 // set the scroll
334                 el[ scroll ] = 1;
335                 has = ( el[ scroll ] > 0 );
336                 el[ scroll ] = 0;
337                 return has;
338         },
339
340         // these are odd functions, fix the API or move into individual plugins
341         isOverAxis: function( x, reference, size ) {
342                 //Determines when x coordinate is over "b" element axis
343                 return ( x > reference ) && ( x < ( reference + size ) );
344         },
345         isOver: function( y, x, top, left, height, width ) {
346                 //Determines when x, y coordinates is over "b" element
347                 return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
348         }
349 });
350
351 })( jQuery );
352 (function( $, undefined ) {
353
354 var uuid = 0,
355         slice = Array.prototype.slice,
356         _cleanData = $.cleanData;
357 $.cleanData = function( elems ) {
358         for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
359                 try {
360                         $( elem ).triggerHandler( "remove" );
361                 // http://bugs.jquery.com/ticket/8235
362                 } catch( e ) {}
363         }
364         _cleanData( elems );
365 };
366
367 $.widget = function( name, base, prototype ) {
368         var fullName, existingConstructor, constructor, basePrototype,
369                 namespace = name.split( "." )[ 0 ];
370
371         name = name.split( "." )[ 1 ];
372         fullName = namespace + "-" + name;
373
374         if ( !prototype ) {
375                 prototype = base;
376                 base = $.Widget;
377         }
378
379         // create selector for plugin
380         $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
381                 return !!$.data( elem, fullName );
382         };
383
384         $[ namespace ] = $[ namespace ] || {};
385         existingConstructor = $[ namespace ][ name ];
386         constructor = $[ namespace ][ name ] = function( options, element ) {
387                 // allow instantiation without "new" keyword
388                 if ( !this._createWidget ) {
389                         return new constructor( options, element );
390                 }
391
392                 // allow instantiation without initializing for simple inheritance
393                 // must use "new" keyword (the code above always passes args)
394                 if ( arguments.length ) {
395                         this._createWidget( options, element );
396                 }
397         };
398         // extend with the existing constructor to carry over any static properties
399         $.extend( constructor, existingConstructor, {
400                 version: prototype.version,
401                 // copy the object used to create the prototype in case we need to
402                 // redefine the widget later
403                 _proto: $.extend( {}, prototype ),
404                 // track widgets that inherit from this widget in case this widget is
405                 // redefined after a widget inherits from it
406                 _childConstructors: []
407         });
408
409         basePrototype = new base();
410         // we need to make the options hash a property directly on the new instance
411         // otherwise we'll modify the options hash on the prototype that we're
412         // inheriting from
413         basePrototype.options = $.widget.extend( {}, basePrototype.options );
414         $.each( prototype, function( prop, value ) {
415                 if ( $.isFunction( value ) ) {
416                         prototype[ prop ] = (function() {
417                                 var _super = function() {
418                                                 return base.prototype[ prop ].apply( this, arguments );
419                                         },
420                                         _superApply = function( args ) {
421                                                 return base.prototype[ prop ].apply( this, args );
422                                         };
423                                 return function() {
424                                         var __super = this._super,
425                                                 __superApply = this._superApply,
426                                                 returnValue;
427
428                                         this._super = _super;
429                                         this._superApply = _superApply;
430
431                                         returnValue = value.apply( this, arguments );
432
433                                         this._super = __super;
434                                         this._superApply = __superApply;
435
436                                         return returnValue;
437                                 };
438                         })();
439                 }
440         });
441         constructor.prototype = $.widget.extend( basePrototype, {
442                 // TODO: remove support for widgetEventPrefix
443                 // always use the name + a colon as the prefix, e.g., draggable:start
444                 // don't prefix for widgets that aren't DOM-based
445                 widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
446         }, prototype, {
447                 constructor: constructor,
448                 namespace: namespace,
449                 widgetName: name,
450                 // TODO remove widgetBaseClass, see #8155
451                 widgetBaseClass: fullName,
452                 widgetFullName: fullName
453         });
454
455         // If this widget is being redefined then we need to find all widgets that
456         // are inheriting from it and redefine all of them so that they inherit from
457         // the new version of this widget. We're essentially trying to replace one
458         // level in the prototype chain.
459         if ( existingConstructor ) {
460                 $.each( existingConstructor._childConstructors, function( i, child ) {
461                         var childPrototype = child.prototype;
462
463                         // redefine the child widget using the same prototype that was
464                         // originally used, but inherit from the new version of the base
465                         $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
466                 });
467                 // remove the list of existing child constructors from the old constructor
468                 // so the old child constructors can be garbage collected
469                 delete existingConstructor._childConstructors;
470         } else {
471                 base._childConstructors.push( constructor );
472         }
473
474         $.widget.bridge( name, constructor );
475 };
476
477 $.widget.extend = function( target ) {
478         var input = slice.call( arguments, 1 ),
479                 inputIndex = 0,
480                 inputLength = input.length,
481                 key,
482                 value;
483         for ( ; inputIndex < inputLength; inputIndex++ ) {
484                 for ( key in input[ inputIndex ] ) {
485                         value = input[ inputIndex ][ key ];
486                         if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
487                                 // Clone objects
488                                 if ( $.isPlainObject( value ) ) {
489                                         target[ key ] = $.isPlainObject( target[ key ] ) ?
490                                                 $.widget.extend( {}, target[ key ], value ) :
491                                                 // Don't extend strings, arrays, etc. with objects
492                                                 $.widget.extend( {}, value );
493                                 // Copy everything else by reference
494                                 } else {
495                                         target[ key ] = value;
496                                 }
497                         }
498                 }
499         }
500         return target;
501 };
502
503 $.widget.bridge = function( name, object ) {
504         var fullName = object.prototype.widgetFullName || name;
505         $.fn[ name ] = function( options ) {
506                 var isMethodCall = typeof options === "string",
507                         args = slice.call( arguments, 1 ),
508                         returnValue = this;
509
510                 // allow multiple hashes to be passed on init
511                 options = !isMethodCall && args.length ?
512                         $.widget.extend.apply( null, [ options ].concat(args) ) :
513                         options;
514
515                 if ( isMethodCall ) {
516                         this.each(function() {
517                                 var methodValue,
518                                         instance = $.data( this, fullName );
519                                 if ( !instance ) {
520                                         return $.error( "cannot call methods on " + name + " prior to initialization; " +
521                                                 "attempted to call method '" + options + "'" );
522                                 }
523                                 if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
524                                         return $.error( "no such method '" + options + "' for " + name + " widget instance" );
525                                 }
526                                 methodValue = instance[ options ].apply( instance, args );
527                                 if ( methodValue !== instance && methodValue !== undefined ) {
528                                         returnValue = methodValue && methodValue.jquery ?
529                                                 returnValue.pushStack( methodValue.get() ) :
530                                                 methodValue;
531                                         return false;
532                                 }
533                         });
534                 } else {
535                         this.each(function() {
536                                 var instance = $.data( this, fullName );
537                                 if ( instance ) {
538                                         instance.option( options || {} )._init();
539                                 } else {
540                                         $.data( this, fullName, new object( options, this ) );
541                                 }
542                         });
543                 }
544
545                 return returnValue;
546         };
547 };
548
549 $.Widget = function( /* options, element */ ) {};
550 $.Widget._childConstructors = [];
551
552 $.Widget.prototype = {
553         widgetName: "widget",
554         widgetEventPrefix: "",
555         defaultElement: "<div>",
556         options: {
557                 disabled: false,
558
559                 // callbacks
560                 create: null
561         },
562         _createWidget: function( options, element ) {
563                 element = $( element || this.defaultElement || this )[ 0 ];
564                 this.element = $( element );
565                 this.uuid = uuid++;
566                 this.eventNamespace = "." + this.widgetName + this.uuid;
567                 this.options = $.widget.extend( {},
568                         this.options,
569                         this._getCreateOptions(),
570                         options );
571
572                 this.bindings = $();
573                 this.hoverable = $();
574                 this.focusable = $();
575
576                 if ( element !== this ) {
577                         // 1.9 BC for #7810
578                         // TODO remove dual storage
579                         $.data( element, this.widgetName, this );
580                         $.data( element, this.widgetFullName, this );
581                         this._on( true, this.element, {
582                                 remove: function( event ) {
583                                         if ( event.target === element ) {
584                                                 this.destroy();
585                                         }
586                                 }
587                         });
588                         this.document = $( element.style ?
589                                 // element within the document
590                                 element.ownerDocument :
591                                 // element is window or document
592                                 element.document || element );
593                         this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
594                 }
595
596                 this._create();
597                 this._trigger( "create", null, this._getCreateEventData() );
598                 this._init();
599         },
600         _getCreateOptions: $.noop,
601         _getCreateEventData: $.noop,
602         _create: $.noop,
603         _init: $.noop,
604
605         destroy: function() {
606                 this._destroy();
607                 // we can probably remove the unbind calls in 2.0
608                 // all event bindings should go through this._on()
609                 this.element
610                         .unbind( this.eventNamespace )
611                         // 1.9 BC for #7810
612                         // TODO remove dual storage
613                         .removeData( this.widgetName )
614                         .removeData( this.widgetFullName )
615                         // support: jquery <1.6.3
616                         // http://bugs.jquery.com/ticket/9413
617                         .removeData( $.camelCase( this.widgetFullName ) );
618                 this.widget()
619                         .unbind( this.eventNamespace )
620                         .removeAttr( "aria-disabled" )
621                         .removeClass(
622                                 this.widgetFullName + "-disabled " +
623                                 "ui-state-disabled" );
624
625                 // clean up events and states
626                 this.bindings.unbind( this.eventNamespace );
627                 this.hoverable.removeClass( "ui-state-hover" );
628                 this.focusable.removeClass( "ui-state-focus" );
629         },
630         _destroy: $.noop,
631
632         widget: function() {
633                 return this.element;
634         },
635
636         option: function( key, value ) {
637                 var options = key,
638                         parts,
639                         curOption,
640                         i;
641
642                 if ( arguments.length === 0 ) {
643                         // don't return a reference to the internal hash
644                         return $.widget.extend( {}, this.options );
645                 }
646
647                 if ( typeof key === "string" ) {
648                         // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
649                         options = {};
650                         parts = key.split( "." );
651                         key = parts.shift();
652                         if ( parts.length ) {
653                                 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
654                                 for ( i = 0; i < parts.length - 1; i++ ) {
655                                         curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
656                                         curOption = curOption[ parts[ i ] ];
657                                 }
658                                 key = parts.pop();
659                                 if ( value === undefined ) {
660                                         return curOption[ key ] === undefined ? null : curOption[ key ];
661                                 }
662                                 curOption[ key ] = value;
663                         } else {
664                                 if ( value === undefined ) {
665                                         return this.options[ key ] === undefined ? null : this.options[ key ];
666                                 }
667                                 options[ key ] = value;
668                         }
669                 }
670
671                 this._setOptions( options );
672
673                 return this;
674         },
675         _setOptions: function( options ) {
676                 var key;
677
678                 for ( key in options ) {
679                         this._setOption( key, options[ key ] );
680                 }
681
682                 return this;
683         },
684         _setOption: function( key, value ) {
685                 this.options[ key ] = value;
686
687                 if ( key === "disabled" ) {
688                         this.widget()
689                                 .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
690                                 .attr( "aria-disabled", value );
691                         this.hoverable.removeClass( "ui-state-hover" );
692                         this.focusable.removeClass( "ui-state-focus" );
693                 }
694
695                 return this;
696         },
697
698         enable: function() {
699                 return this._setOption( "disabled", false );
700         },
701         disable: function() {
702                 return this._setOption( "disabled", true );
703         },
704
705         _on: function( suppressDisabledCheck, element, handlers ) {
706                 var delegateElement,
707                         instance = this;
708
709                 // no suppressDisabledCheck flag, shuffle arguments
710                 if ( typeof suppressDisabledCheck !== "boolean" ) {
711                         handlers = element;
712                         element = suppressDisabledCheck;
713                         suppressDisabledCheck = false;
714                 }
715
716                 // no element argument, shuffle and use this.element
717                 if ( !handlers ) {
718                         handlers = element;
719                         element = this.element;
720                         delegateElement = this.widget();
721                 } else {
722                         // accept selectors, DOM elements
723                         element = delegateElement = $( element );
724                         this.bindings = this.bindings.add( element );
725                 }
726
727                 $.each( handlers, function( event, handler ) {
728                         function handlerProxy() {
729                                 // allow widgets to customize the disabled handling
730                                 // - disabled as an array instead of boolean
731                                 // - disabled class as method for disabling individual parts
732                                 if ( !suppressDisabledCheck &&
733                                                 ( instance.options.disabled === true ||
734                                                         $( this ).hasClass( "ui-state-disabled" ) ) ) {
735                                         return;
736                                 }
737                                 return ( typeof handler === "string" ? instance[ handler ] : handler )
738                                         .apply( instance, arguments );
739                         }
740
741                         // copy the guid so direct unbinding works
742                         if ( typeof handler !== "string" ) {
743                                 handlerProxy.guid = handler.guid =
744                                         handler.guid || handlerProxy.guid || $.guid++;
745                         }
746
747                         var match = event.match( /^(\w+)\s*(.*)$/ ),
748                                 eventName = match[1] + instance.eventNamespace,
749                                 selector = match[2];
750                         if ( selector ) {
751                                 delegateElement.delegate( selector, eventName, handlerProxy );
752                         } else {
753                                 element.bind( eventName, handlerProxy );
754                         }
755                 });
756         },
757
758         _off: function( element, eventName ) {
759                 eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
760                 element.unbind( eventName ).undelegate( eventName );
761         },
762
763         _delay: function( handler, delay ) {
764                 function handlerProxy() {
765                         return ( typeof handler === "string" ? instance[ handler ] : handler )
766                                 .apply( instance, arguments );
767                 }
768                 var instance = this;
769                 return setTimeout( handlerProxy, delay || 0 );
770         },
771
772         _hoverable: function( element ) {
773                 this.hoverable = this.hoverable.add( element );
774                 this._on( element, {
775                         mouseenter: function( event ) {
776                                 $( event.currentTarget ).addClass( "ui-state-hover" );
777                         },
778                         mouseleave: function( event ) {
779                                 $( event.currentTarget ).removeClass( "ui-state-hover" );
780                         }
781                 });
782         },
783
784         _focusable: function( element ) {
785                 this.focusable = this.focusable.add( element );
786                 this._on( element, {
787                         focusin: function( event ) {
788                                 $( event.currentTarget ).addClass( "ui-state-focus" );
789                         },
790                         focusout: function( event ) {
791                                 $( event.currentTarget ).removeClass( "ui-state-focus" );
792                         }
793                 });
794         },
795
796         _trigger: function( type, event, data ) {
797                 var prop, orig,
798                         callback = this.options[ type ];
799
800                 data = data || {};
801                 event = $.Event( event );
802                 event.type = ( type === this.widgetEventPrefix ?
803                         type :
804                         this.widgetEventPrefix + type ).toLowerCase();
805                 // the original event may come from any element
806                 // so we need to reset the target on the new event
807                 event.target = this.element[ 0 ];
808
809                 // copy original event properties over to the new event
810                 orig = event.originalEvent;
811                 if ( orig ) {
812                         for ( prop in orig ) {
813                                 if ( !( prop in event ) ) {
814                                         event[ prop ] = orig[ prop ];
815                                 }
816                         }
817                 }
818
819                 this.element.trigger( event, data );
820                 return !( $.isFunction( callback ) &&
821                         callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
822                         event.isDefaultPrevented() );
823         }
824 };
825
826 $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
827         $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
828                 if ( typeof options === "string" ) {
829                         options = { effect: options };
830                 }
831                 var hasOptions,
832                         effectName = !options ?
833                                 method :
834                                 options === true || typeof options === "number" ?
835                                         defaultEffect :
836                                         options.effect || defaultEffect;
837                 options = options || {};
838                 if ( typeof options === "number" ) {
839                         options = { duration: options };
840                 }
841                 hasOptions = !$.isEmptyObject( options );
842                 options.complete = callback;
843                 if ( options.delay ) {
844                         element.delay( options.delay );
845                 }
846                 if ( hasOptions && $.effects && ( $.effects.effect[ effectName ] || $.uiBackCompat !== false && $.effects[ effectName ] ) ) {
847                         element[ method ]( options );
848                 } else if ( effectName !== method && element[ effectName ] ) {
849                         element[ effectName ]( options.duration, options.easing, callback );
850                 } else {
851                         element.queue(function( next ) {
852                                 $( this )[ method ]();
853                                 if ( callback ) {
854                                         callback.call( element[ 0 ] );
855                                 }
856                                 next();
857                         });
858                 }
859         };
860 });
861
862 // DEPRECATED
863 if ( $.uiBackCompat !== false ) {
864         $.Widget.prototype._getCreateOptions = function() {
865                 return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
866         };
867 }
868
869 })( jQuery );
870 (function( $, undefined ) {
871
872 var mouseHandled = false;
873 $( document ).mouseup( function( e ) {
874         mouseHandled = false;
875 });
876
877 $.widget("ui.mouse", {
878         version: "1.9.2",
879         options: {
880                 cancel: 'input,textarea,button,select,option',
881                 distance: 1,
882                 delay: 0
883         },
884         _mouseInit: function() {
885                 var that = this;
886
887                 this.element
888                         .bind('mousedown.'+this.widgetName, function(event) {
889                                 return that._mouseDown(event);
890                         })
891                         .bind('click.'+this.widgetName, function(event) {
892                                 if (true === $.data(event.target, that.widgetName + '.preventClickEvent')) {
893                                         $.removeData(event.target, that.widgetName + '.preventClickEvent');
894                                         event.stopImmediatePropagation();
895                                         return false;
896                                 }
897                         });
898
899                 this.started = false;
900         },
901
902         // TODO: make sure destroying one instance of mouse doesn't mess with
903         // other instances of mouse
904         _mouseDestroy: function() {
905                 this.element.unbind('.'+this.widgetName);
906                 if ( this._mouseMoveDelegate ) {
907                         $(document)
908                                 .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
909                                 .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
910                 }
911         },
912
913         _mouseDown: function(event) {
914                 // don't let more than one widget handle mouseStart
915                 if( mouseHandled ) { return; }
916
917                 // we may have missed mouseup (out of window)
918                 (this._mouseStarted && this._mouseUp(event));
919
920                 this._mouseDownEvent = event;
921
922                 var that = this,
923                         btnIsLeft = (event.which === 1),
924                         // event.target.nodeName works around a bug in IE 8 with
925                         // disabled inputs (#7620)
926                         elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
927                 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
928                         return true;
929                 }
930
931                 this.mouseDelayMet = !this.options.delay;
932                 if (!this.mouseDelayMet) {
933                         this._mouseDelayTimer = setTimeout(function() {
934                                 that.mouseDelayMet = true;
935                         }, this.options.delay);
936                 }
937
938                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
939                         this._mouseStarted = (this._mouseStart(event) !== false);
940                         if (!this._mouseStarted) {
941                                 event.preventDefault();
942                                 return true;
943                         }
944                 }
945
946                 // Click event may never have fired (Gecko & Opera)
947                 if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {
948                         $.removeData(event.target, this.widgetName + '.preventClickEvent');
949                 }
950
951                 // these delegates are required to keep context
952                 this._mouseMoveDelegate = function(event) {
953                         return that._mouseMove(event);
954                 };
955                 this._mouseUpDelegate = function(event) {
956                         return that._mouseUp(event);
957                 };
958                 $(document)
959                         .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
960                         .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
961
962                 event.preventDefault();
963
964                 mouseHandled = true;
965                 return true;
966         },
967
968         _mouseMove: function(event) {
969                 // IE mouseup check - mouseup happened when mouse was out of window
970                 if ($.ui.ie && !(document.documentMode >= 9) && !event.button) {
971                         return this._mouseUp(event);
972                 }
973
974                 if (this._mouseStarted) {
975                         this._mouseDrag(event);
976                         return event.preventDefault();
977                 }
978
979                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
980                         this._mouseStarted =
981                                 (this._mouseStart(this._mouseDownEvent, event) !== false);
982                         (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
983                 }
984
985                 return !this._mouseStarted;
986         },
987
988         _mouseUp: function(event) {
989                 $(document)
990                         .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
991                         .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
992
993                 if (this._mouseStarted) {
994                         this._mouseStarted = false;
995
996                         if (event.target === this._mouseDownEvent.target) {
997                                 $.data(event.target, this.widgetName + '.preventClickEvent', true);
998                         }
999
1000                         this._mouseStop(event);
1001                 }
1002
1003                 return false;
1004         },
1005
1006         _mouseDistanceMet: function(event) {
1007                 return (Math.max(
1008                                 Math.abs(this._mouseDownEvent.pageX - event.pageX),
1009                                 Math.abs(this._mouseDownEvent.pageY - event.pageY)
1010                         ) >= this.options.distance
1011                 );
1012         },
1013
1014         _mouseDelayMet: function(event) {
1015                 return this.mouseDelayMet;
1016         },
1017
1018         // These are placeholder methods, to be overriden by extending plugin
1019         _mouseStart: function(event) {},
1020         _mouseDrag: function(event) {},
1021         _mouseStop: function(event) {},
1022         _mouseCapture: function(event) { return true; }
1023 });
1024
1025 })(jQuery);
1026 (function( $, undefined ) {
1027
1028 $.widget("ui.draggable", $.ui.mouse, {
1029         version: "1.9.2",
1030         widgetEventPrefix: "drag",
1031         options: {
1032                 addClasses: true,
1033                 appendTo: "parent",
1034                 axis: false,
1035                 connectToSortable: false,
1036                 containment: false,
1037                 cursor: "auto",
1038                 cursorAt: false,
1039                 grid: false,
1040                 handle: false,
1041                 helper: "original",
1042                 iframeFix: false,
1043                 opacity: false,
1044                 refreshPositions: false,
1045                 revert: false,
1046                 revertDuration: 500,
1047                 scope: "default",
1048                 scroll: true,
1049                 scrollSensitivity: 20,
1050                 scrollSpeed: 20,
1051                 snap: false,
1052                 snapMode: "both",
1053                 snapTolerance: 20,
1054                 stack: false,
1055                 zIndex: false
1056         },
1057         _create: function() {
1058
1059                 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
1060                         this.element[0].style.position = 'relative';
1061
1062                 (this.options.addClasses && this.element.addClass("ui-draggable"));
1063                 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
1064
1065                 this._mouseInit();
1066
1067         },
1068
1069         _destroy: function() {
1070                 this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
1071                 this._mouseDestroy();
1072         },
1073
1074         _mouseCapture: function(event) {
1075
1076                 var o = this.options;
1077
1078                 // among others, prevent a drag on a resizable-handle
1079                 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
1080                         return false;
1081
1082                 //Quit if we're not on a valid handle
1083                 this.handle = this._getHandle(event);
1084                 if (!this.handle)
1085                         return false;
1086
1087                 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
1088                         $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
1089                         .css({
1090                                 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
1091                                 position: "absolute", opacity: "0.001", zIndex: 1000
1092                         })
1093                         .css($(this).offset())
1094                         .appendTo("body");
1095                 });
1096
1097                 return true;
1098
1099         },
1100
1101         _mouseStart: function(event) {
1102
1103                 var o = this.options;
1104
1105                 //Create and append the visible helper
1106                 this.helper = this._createHelper(event);
1107
1108                 this.helper.addClass("ui-draggable-dragging");
1109
1110                 //Cache the helper size
1111                 this._cacheHelperProportions();
1112
1113                 //If ddmanager is used for droppables, set the global draggable
1114                 if($.ui.ddmanager)
1115                         $.ui.ddmanager.current = this;
1116
1117                 /*
1118                  * - Position generation -
1119                  * This block generates everything position related - it's the core of draggables.
1120                  */
1121
1122                 //Cache the margins of the original element
1123                 this._cacheMargins();
1124
1125                 //Store the helper's css position
1126                 this.cssPosition = this.helper.css("position");
1127                 this.scrollParent = this.helper.scrollParent();
1128
1129                 //The element's absolute position on the page minus margins
1130                 this.offset = this.positionAbs = this.element.offset();
1131                 this.offset = {
1132                         top: this.offset.top - this.margins.top,
1133                         left: this.offset.left - this.margins.left
1134                 };
1135
1136                 $.extend(this.offset, {
1137                         click: { //Where the click happened, relative to the element
1138                                 left: event.pageX - this.offset.left,
1139                                 top: event.pageY - this.offset.top
1140                         },
1141                         parent: this._getParentOffset(),
1142                         relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
1143                 });
1144
1145                 //Generate the original position
1146                 this.originalPosition = this.position = this._generatePosition(event);
1147                 this.originalPageX = event.pageX;
1148                 this.originalPageY = event.pageY;
1149
1150                 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
1151                 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
1152
1153                 //Set a containment if given in the options
1154                 if(o.containment)
1155                         this._setContainment();
1156
1157                 //Trigger event + callbacks
1158                 if(this._trigger("start", event) === false) {
1159                         this._clear();
1160                         return false;
1161                 }
1162
1163                 //Recache the helper size
1164                 this._cacheHelperProportions();
1165
1166                 //Prepare the droppable offsets
1167                 if ($.ui.ddmanager && !o.dropBehaviour)
1168                         $.ui.ddmanager.prepareOffsets(this, event);
1169
1170
1171                 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
1172
1173                 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
1174                 if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event);
1175
1176                 return true;
1177         },
1178
1179         _mouseDrag: function(event, noPropagation) {
1180
1181                 //Compute the helpers position
1182                 this.position = this._generatePosition(event);
1183                 this.positionAbs = this._convertPositionTo("absolute");
1184
1185                 //Call plugins and callbacks and use the resulting position if something is returned
1186                 if (!noPropagation) {
1187                         var ui = this._uiHash();
1188                         if(this._trigger('drag', event, ui) === false) {
1189                                 this._mouseUp({});
1190                                 return false;
1191                         }
1192                         this.position = ui.position;
1193                 }
1194
1195                 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
1196                 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
1197                 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
1198
1199                 return false;
1200         },
1201
1202         _mouseStop: function(event) {
1203
1204                 //If we are using droppables, inform the manager about the drop
1205                 var dropped = false;
1206                 if ($.ui.ddmanager && !this.options.dropBehaviour)
1207                         dropped = $.ui.ddmanager.drop(this, event);
1208
1209                 //if a drop comes from outside (a sortable)
1210                 if(this.dropped) {
1211                         dropped = this.dropped;
1212                         this.dropped = false;
1213                 }
1214
1215                 //if the original element is no longer in the DOM don't bother to continue (see #8269)
1216                 var element = this.element[0], elementInDom = false;
1217                 while ( element && (element = element.parentNode) ) {
1218                         if (element == document ) {
1219                                 elementInDom = true;
1220                         }
1221                 }
1222                 if ( !elementInDom && this.options.helper === "original" )
1223                         return false;
1224
1225                 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))) {
1226                         var that = this;
1227                         $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
1228                                 if(that._trigger("stop", event) !== false) {
1229                                         that._clear();
1230                                 }
1231                         });
1232                 } else {
1233                         if(this._trigger("stop", event) !== false) {
1234                                 this._clear();
1235                         }
1236                 }
1237
1238                 return false;
1239         },
1240
1241         _mouseUp: function(event) {
1242                 //Remove frame helpers
1243                 $("div.ui-draggable-iframeFix").each(function() {
1244                         this.parentNode.removeChild(this);
1245                 });
1246
1247                 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
1248                 if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event);
1249
1250                 return $.ui.mouse.prototype._mouseUp.call(this, event);
1251         },
1252
1253         cancel: function() {
1254
1255                 if(this.helper.is(".ui-draggable-dragging")) {
1256                         this._mouseUp({});
1257                 } else {
1258                         this._clear();
1259                 }
1260
1261                 return this;
1262
1263         },
1264
1265         _getHandle: function(event) {
1266
1267                 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
1268                 $(this.options.handle, this.element)
1269                         .find("*")
1270                         .andSelf()
1271                         .each(function() {
1272                                 if(this == event.target) handle = true;
1273                         });
1274
1275                 return handle;
1276
1277         },
1278
1279         _createHelper: function(event) {
1280
1281                 var o = this.options;
1282                 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element);
1283
1284                 if(!helper.parents('body').length)
1285                         helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
1286
1287                 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
1288                         helper.css("position", "absolute");
1289
1290                 return helper;
1291
1292         },
1293
1294         _adjustOffsetFromHelper: function(obj) {
1295                 if (typeof obj == 'string') {
1296                         obj = obj.split(' ');
1297                 }
1298                 if ($.isArray(obj)) {
1299                         obj = {left: +obj[0], top: +obj[1] || 0};
1300                 }
1301                 if ('left' in obj) {
1302                         this.offset.click.left = obj.left + this.margins.left;
1303                 }
1304                 if ('right' in obj) {
1305                         this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1306                 }
1307                 if ('top' in obj) {
1308                         this.offset.click.top = obj.top + this.margins.top;
1309                 }
1310                 if ('bottom' in obj) {
1311                         this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1312                 }
1313         },
1314
1315         _getParentOffset: function() {
1316
1317                 //Get the offsetParent and cache its position
1318                 this.offsetParent = this.helper.offsetParent();
1319                 var po = this.offsetParent.offset();
1320
1321                 // This is a special case where we need to modify a offset calculated on start, since the following happened:
1322                 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1323                 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1324                 //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1325                 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
1326                         po.left += this.scrollParent.scrollLeft();
1327                         po.top += this.scrollParent.scrollTop();
1328                 }
1329
1330                 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
1331                 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.ui.ie)) //Ugly IE fix
1332                         po = { top: 0, left: 0 };
1333
1334                 return {
1335                         top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1336                         left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1337                 };
1338
1339         },
1340
1341         _getRelativeOffset: function() {
1342
1343                 if(this.cssPosition == "relative") {
1344                         var p = this.element.position();
1345                         return {
1346                                 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1347                                 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1348                         };
1349                 } else {
1350                         return { top: 0, left: 0 };
1351                 }
1352
1353         },
1354
1355         _cacheMargins: function() {
1356                 this.margins = {
1357                         left: (parseInt(this.element.css("marginLeft"),10) || 0),
1358                         top: (parseInt(this.element.css("marginTop"),10) || 0),
1359                         right: (parseInt(this.element.css("marginRight"),10) || 0),
1360                         bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
1361                 };
1362         },
1363
1364         _cacheHelperProportions: function() {
1365                 this.helperProportions = {
1366                         width: this.helper.outerWidth(),
1367                         height: this.helper.outerHeight()
1368                 };
1369         },
1370
1371         _setContainment: function() {
1372
1373                 var o = this.options;
1374                 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
1375                 if(o.containment == 'document' || o.containment == 'window') this.containment = [
1376                         o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
1377                         o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
1378                         (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
1379                         (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
1380                 ];
1381
1382                 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
1383                         var c = $(o.containment);
1384                         var ce = c[0]; if(!ce) return;
1385                         var co = c.offset();
1386                         var over = ($(ce).css("overflow") != 'hidden');
1387
1388                         this.containment = [
1389                                 (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
1390                                 (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
1391                                 (over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right,
1392                                 (over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top  - this.margins.bottom
1393                         ];
1394                         this.relative_container = c;
1395
1396                 } else if(o.containment.constructor == Array) {
1397                         this.containment = o.containment;
1398                 }
1399
1400         },
1401
1402         _convertPositionTo: function(d, pos) {
1403
1404                 if(!pos) pos = this.position;
1405                 var mod = d == "absolute" ? 1 : -1;
1406                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
1407
1408                 return {
1409                         top: (
1410                                 pos.top                                                                                                                                 // The absolute mouse position
1411                                 + this.offset.relative.top * mod                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
1412                                 + this.offset.parent.top * mod                                                                                  // The offsetParent's offset without borders (offset + border)
1413                                 - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
1414                         ),
1415                         left: (
1416                                 pos.left                                                                                                                                // The absolute mouse position
1417                                 + this.offset.relative.left * mod                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
1418                                 + this.offset.parent.left * mod                                                                                 // The offsetParent's offset without borders (offset + border)
1419                                 - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
1420                         )
1421                 };
1422
1423         },
1424
1425         _generatePosition: function(event) {
1426
1427                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
1428                 var pageX = event.pageX;
1429                 var pageY = event.pageY;
1430
1431                 /*
1432                  * - Position constraining -
1433                  * Constrain the position to a mix of grid, containment.
1434                  */
1435
1436                 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
1437                         var containment;
1438                         if(this.containment) {
1439                         if (this.relative_container){
1440                                 var co = this.relative_container.offset();
1441                                 containment = [ this.containment[0] + co.left,
1442                                         this.containment[1] + co.top,
1443                                         this.containment[2] + co.left,
1444                                         this.containment[3] + co.top ];
1445                         }
1446                         else {
1447                                 containment = this.containment;
1448                         }
1449
1450                                 if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left;
1451                                 if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top;
1452                                 if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left;
1453                                 if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top;
1454                         }
1455
1456                         if(o.grid) {
1457                                 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
1458                                 var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
1459                                 pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
1460
1461                                 var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
1462                                 pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
1463                         }
1464
1465                 }
1466
1467                 return {
1468                         top: (
1469                                 pageY                                                                                                                           // The absolute mouse position
1470                                 - this.offset.click.top                                                                                                 // Click offset (relative to the element)
1471                                 - this.offset.relative.top                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
1472                                 - this.offset.parent.top                                                                                                // The offsetParent's offset without borders (offset + border)
1473                                 + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
1474                         ),
1475                         left: (
1476                                 pageX                                                                                                                           // The absolute mouse position
1477                                 - this.offset.click.left                                                                                                // Click offset (relative to the element)
1478                                 - this.offset.relative.left                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
1479                                 - this.offset.parent.left                                                                                               // The offsetParent's offset without borders (offset + border)
1480                                 + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
1481                         )
1482                 };
1483
1484         },
1485
1486         _clear: function() {
1487                 this.helper.removeClass("ui-draggable-dragging");
1488                 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
1489                 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
1490                 this.helper = null;
1491                 this.cancelHelperRemoval = false;
1492         },
1493
1494         // From now on bulk stuff - mainly helpers
1495
1496         _trigger: function(type, event, ui) {
1497                 ui = ui || this._uiHash();
1498                 $.ui.plugin.call(this, type, [event, ui]);
1499                 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
1500                 return $.Widget.prototype._trigger.call(this, type, event, ui);
1501         },
1502
1503         plugins: {},
1504
1505         _uiHash: function(event) {
1506                 return {
1507                         helper: this.helper,
1508                         position: this.position,
1509                         originalPosition: this.originalPosition,
1510                         offset: this.positionAbs
1511                 };
1512         }
1513
1514 });
1515
1516 $.ui.plugin.add("draggable", "connectToSortable", {
1517         start: function(event, ui) {
1518
1519                 var inst = $(this).data("draggable"), o = inst.options,
1520                         uiSortable = $.extend({}, ui, { item: inst.element });
1521                 inst.sortables = [];
1522                 $(o.connectToSortable).each(function() {
1523                         var sortable = $.data(this, 'sortable');
1524                         if (sortable && !sortable.options.disabled) {
1525                                 inst.sortables.push({
1526                                         instance: sortable,
1527                                         shouldRevert: sortable.options.revert
1528                                 });
1529                                 sortable.refreshPositions();    // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
1530                                 sortable._trigger("activate", event, uiSortable);
1531                         }
1532                 });
1533
1534         },
1535         stop: function(event, ui) {
1536
1537                 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
1538                 var inst = $(this).data("draggable"),
1539                         uiSortable = $.extend({}, ui, { item: inst.element });
1540
1541                 $.each(inst.sortables, function() {
1542                         if(this.instance.isOver) {
1543
1544                                 this.instance.isOver = 0;
1545
1546                                 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
1547                                 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
1548
1549                                 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
1550                                 if(this.shouldRevert) this.instance.options.revert = true;
1551
1552                                 //Trigger the stop of the sortable
1553                                 this.instance._mouseStop(event);
1554
1555                                 this.instance.options.helper = this.instance.options._helper;
1556
1557                                 //If the helper has been the original item, restore properties in the sortable
1558                                 if(inst.options.helper == 'original')
1559                                         this.instance.currentItem.css({ top: 'auto', left: 'auto' });
1560
1561                         } else {
1562                                 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
1563                                 this.instance._trigger("deactivate", event, uiSortable);
1564                         }
1565
1566                 });
1567
1568         },
1569         drag: function(event, ui) {
1570
1571                 var inst = $(this).data("draggable"), that = this;
1572
1573                 var checkPos = function(o) {
1574                         var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
1575                         var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
1576                         var itemHeight = o.height, itemWidth = o.width;
1577                         var itemTop = o.top, itemLeft = o.left;
1578
1579                         return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
1580                 };
1581
1582                 $.each(inst.sortables, function(i) {
1583
1584                         var innermostIntersecting = false;
1585                         var thisSortable = this;
1586                         //Copy over some variables to allow calling the sortable's native _intersectsWith
1587                         this.instance.positionAbs = inst.positionAbs;
1588                         this.instance.helperProportions = inst.helperProportions;
1589                         this.instance.offset.click = inst.offset.click;
1590
1591                         if(this.instance._intersectsWith(this.instance.containerCache)) {
1592                                 innermostIntersecting = true;
1593                                 $.each(inst.sortables, function () {
1594                                         this.instance.positionAbs = inst.positionAbs;
1595                                         this.instance.helperProportions = inst.helperProportions;
1596                                         this.instance.offset.click = inst.offset.click;
1597                                         if  (this != thisSortable
1598                                                 && this.instance._intersectsWith(this.instance.containerCache)
1599                                                 && $.ui.contains(thisSortable.instance.element[0], this.instance.element[0]))
1600                                                 innermostIntersecting = false;
1601                                                 return innermostIntersecting;
1602                                 });
1603                         }
1604
1605
1606                         if(innermostIntersecting) {
1607                                 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1608                                 if(!this.instance.isOver) {
1609
1610                                         this.instance.isOver = 1;
1611                                         //Now we fake the start of dragging for the sortable instance,
1612                                         //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1613                                         //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)
1614                                         this.instance.currentItem = $(that).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true);
1615                                         this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
1616                                         this.instance.options.helper = function() { return ui.helper[0]; };
1617
1618                                         event.target = this.instance.currentItem[0];
1619                                         this.instance._mouseCapture(event, true);
1620                                         this.instance._mouseStart(event, true, true);
1621
1622                                         //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1623                                         this.instance.offset.click.top = inst.offset.click.top;
1624                                         this.instance.offset.click.left = inst.offset.click.left;
1625                                         this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
1626                                         this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
1627
1628                                         inst._trigger("toSortable", event);
1629                                         inst.dropped = this.instance.element; //draggable revert needs that
1630                                         //hack so receive/update callbacks work (mostly)
1631                                         inst.currentItem = inst.element;
1632                                         this.instance.fromOutside = inst;
1633
1634                                 }
1635
1636                                 //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
1637                                 if(this.instance.currentItem) this.instance._mouseDrag(event);
1638
1639                         } else {
1640
1641                                 //If it doesn't intersect with the sortable, and it intersected before,
1642                                 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1643                                 if(this.instance.isOver) {
1644
1645                                         this.instance.isOver = 0;
1646                                         this.instance.cancelHelperRemoval = true;
1647
1648                                         //Prevent reverting on this forced stop
1649                                         this.instance.options.revert = false;
1650
1651                                         // The out event needs to be triggered independently
1652                                         this.instance._trigger('out', event, this.instance._uiHash(this.instance));
1653
1654                                         this.instance._mouseStop(event, true);
1655                                         this.instance.options.helper = this.instance.options._helper;
1656
1657                                         //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1658                                         this.instance.currentItem.remove();
1659                                         if(this.instance.placeholder) this.instance.placeholder.remove();
1660
1661                                         inst._trigger("fromSortable", event);
1662                                         inst.dropped = false; //draggable revert needs that
1663                                 }
1664
1665                         };
1666
1667                 });
1668
1669         }
1670 });
1671
1672 $.ui.plugin.add("draggable", "cursor", {
1673         start: function(event, ui) {
1674                 var t = $('body'), o = $(this).data('draggable').options;
1675                 if (t.css("cursor")) o._cursor = t.css("cursor");
1676                 t.css("cursor", o.cursor);
1677         },
1678         stop: function(event, ui) {
1679                 var o = $(this).data('draggable').options;
1680                 if (o._cursor) $('body').css("cursor", o._cursor);
1681         }
1682 });
1683
1684 $.ui.plugin.add("draggable", "opacity", {
1685         start: function(event, ui) {
1686                 var t = $(ui.helper), o = $(this).data('draggable').options;
1687                 if(t.css("opacity")) o._opacity = t.css("opacity");
1688                 t.css('opacity', o.opacity);
1689         },
1690         stop: function(event, ui) {
1691                 var o = $(this).data('draggable').options;
1692                 if(o._opacity) $(ui.helper).css('opacity', o._opacity);
1693         }
1694 });
1695
1696 $.ui.plugin.add("draggable", "scroll", {
1697         start: function(event, ui) {
1698                 var i = $(this).data("draggable");
1699                 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
1700         },
1701         drag: function(event, ui) {
1702
1703                 var i = $(this).data("draggable"), o = i.options, scrolled = false;
1704
1705                 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
1706
1707                         if(!o.axis || o.axis != 'x') {
1708                                 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
1709                                         i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
1710                                 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
1711                                         i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
1712                         }
1713
1714                         if(!o.axis || o.axis != 'y') {
1715                                 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
1716                                         i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
1717                                 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
1718                                         i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
1719                         }
1720
1721                 } else {
1722
1723                         if(!o.axis || o.axis != 'x') {
1724                                 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
1725                                         scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1726                                 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
1727                                         scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1728                         }
1729
1730                         if(!o.axis || o.axis != 'y') {
1731                                 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
1732                                         scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1733                                 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
1734                                         scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1735                         }
1736
1737                 }
1738
1739                 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
1740                         $.ui.ddmanager.prepareOffsets(i, event);
1741
1742         }
1743 });
1744
1745 $.ui.plugin.add("draggable", "snap", {
1746         start: function(event, ui) {
1747
1748                 var i = $(this).data("draggable"), o = i.options;
1749                 i.snapElements = [];
1750
1751                 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
1752                         var $t = $(this); var $o = $t.offset();
1753                         if(this != i.element[0]) i.snapElements.push({
1754                                 item: this,
1755                                 width: $t.outerWidth(), height: $t.outerHeight(),
1756                                 top: $o.top, left: $o.left
1757                         });
1758                 });
1759
1760         },
1761         drag: function(event, ui) {
1762
1763                 var inst = $(this).data("draggable"), o = inst.options;
1764                 var d = o.snapTolerance;
1765
1766                 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
1767                         y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
1768
1769                 for (var i = inst.snapElements.length - 1; i >= 0; i--){
1770
1771                         var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
1772                                 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
1773
1774                         //Yes, I know, this is insane ;)
1775                         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))) {
1776                                 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 })));
1777                                 inst.snapElements[i].snapping = false;
1778                                 continue;
1779                         }
1780
1781                         if(o.snapMode != 'inner') {
1782                                 var ts = Math.abs(t - y2) <= d;
1783                                 var bs = Math.abs(b - y1) <= d;
1784                                 var ls = Math.abs(l - x2) <= d;
1785                                 var rs = Math.abs(r - x1) <= d;
1786                                 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1787                                 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
1788                                 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
1789                                 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
1790                         }
1791
1792                         var first = (ts || bs || ls || rs);
1793
1794                         if(o.snapMode != 'outer') {
1795                                 var ts = Math.abs(t - y1) <= d;
1796                                 var bs = Math.abs(b - y2) <= d;
1797                                 var ls = Math.abs(l - x1) <= d;
1798                                 var rs = Math.abs(r - x2) <= d;
1799                                 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
1800                                 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1801                                 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
1802                                 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
1803                         }
1804
1805                         if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
1806                                 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1807                         inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
1808
1809                 };
1810
1811         }
1812 });
1813
1814 $.ui.plugin.add("draggable", "stack", {
1815         start: function(event, ui) {
1816
1817                 var o = $(this).data("draggable").options;
1818
1819                 var group = $.makeArray($(o.stack)).sort(function(a,b) {
1820                         return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
1821                 });
1822                 if (!group.length) { return; }
1823
1824                 var min = parseInt(group[0].style.zIndex) || 0;
1825                 $(group).each(function(i) {
1826                         this.style.zIndex = min + i;
1827                 });
1828
1829                 this[0].style.zIndex = min + group.length;
1830
1831         }
1832 });
1833
1834 $.ui.plugin.add("draggable", "zIndex", {
1835         start: function(event, ui) {
1836                 var t = $(ui.helper), o = $(this).data("draggable").options;
1837                 if(t.css("zIndex")) o._zIndex = t.css("zIndex");
1838                 t.css('zIndex', o.zIndex);
1839         },
1840         stop: function(event, ui) {
1841                 var o = $(this).data("draggable").options;
1842                 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
1843         }
1844 });
1845
1846 })(jQuery);
1847 (function( $, undefined ) {
1848
1849 $.widget("ui.droppable", {
1850         version: "1.9.2",
1851         widgetEventPrefix: "drop",
1852         options: {
1853                 accept: '*',
1854                 activeClass: false,
1855                 addClasses: true,
1856                 greedy: false,
1857                 hoverClass: false,
1858                 scope: 'default',
1859                 tolerance: 'intersect'
1860         },
1861         _create: function() {
1862
1863                 var o = this.options, accept = o.accept;
1864                 this.isover = 0; this.isout = 1;
1865
1866                 this.accept = $.isFunction(accept) ? accept : function(d) {
1867                         return d.is(accept);
1868                 };
1869
1870                 //Store the droppable's proportions
1871                 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
1872
1873                 // Add the reference and positions to the manager
1874                 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
1875                 $.ui.ddmanager.droppables[o.scope].push(this);
1876
1877                 (o.addClasses && this.element.addClass("ui-droppable"));
1878
1879         },
1880
1881         _destroy: function() {
1882                 var drop = $.ui.ddmanager.droppables[this.options.scope];
1883                 for ( var i = 0; i < drop.length; i++ )
1884                         if ( drop[i] == this )
1885                                 drop.splice(i, 1);
1886
1887                 this.element.removeClass("ui-droppable ui-droppable-disabled");
1888         },
1889
1890         _setOption: function(key, value) {
1891
1892                 if(key == 'accept') {
1893                         this.accept = $.isFunction(value) ? value : function(d) {
1894                                 return d.is(value);
1895                         };
1896                 }
1897                 $.Widget.prototype._setOption.apply(this, arguments);
1898         },
1899
1900         _activate: function(event) {
1901                 var draggable = $.ui.ddmanager.current;
1902                 if(this.options.activeClass) this.element.addClass(this.options.activeClass);
1903                 (draggable && this._trigger('activate', event, this.ui(draggable)));
1904         },
1905
1906         _deactivate: function(event) {
1907                 var draggable = $.ui.ddmanager.current;
1908                 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1909                 (draggable && this._trigger('deactivate', event, this.ui(draggable)));
1910         },
1911
1912         _over: function(event) {
1913
1914                 var draggable = $.ui.ddmanager.current;
1915                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1916
1917                 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1918                         if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
1919                         this._trigger('over', event, this.ui(draggable));
1920                 }
1921
1922         },
1923
1924         _out: function(event) {
1925
1926                 var draggable = $.ui.ddmanager.current;
1927                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1928
1929                 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1930                         if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1931                         this._trigger('out', event, this.ui(draggable));
1932                 }
1933
1934         },
1935
1936         _drop: function(event,custom) {
1937
1938                 var draggable = custom || $.ui.ddmanager.current;
1939                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
1940
1941                 var childrenIntersection = false;
1942                 this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
1943                         var inst = $.data(this, 'droppable');
1944                         if(
1945                                 inst.options.greedy
1946                                 && !inst.options.disabled
1947                                 && inst.options.scope == draggable.options.scope
1948                                 && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
1949                                 && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
1950                         ) { childrenIntersection = true; return false; }
1951                 });
1952                 if(childrenIntersection) return false;
1953
1954                 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1955                         if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1956                         if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1957                         this._trigger('drop', event, this.ui(draggable));
1958                         return this.element;
1959                 }
1960
1961                 return false;
1962
1963         },
1964
1965         ui: function(c) {
1966                 return {
1967                         draggable: (c.currentItem || c.element),
1968                         helper: c.helper,
1969                         position: c.position,
1970                         offset: c.positionAbs
1971                 };
1972         }
1973
1974 });
1975
1976 $.ui.intersect = function(draggable, droppable, toleranceMode) {
1977
1978         if (!droppable.offset) return false;
1979
1980         var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
1981                 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
1982         var l = droppable.offset.left, r = l + droppable.proportions.width,
1983                 t = droppable.offset.top, b = t + droppable.proportions.height;
1984
1985         switch (toleranceMode) {
1986                 case 'fit':
1987                         return (l <= x1 && x2 <= r
1988                                 && t <= y1 && y2 <= b);
1989                         break;
1990                 case 'intersect':
1991                         return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
1992                                 && x2 - (draggable.helperProportions.width / 2) < r // Left Half
1993                                 && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
1994                                 && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
1995                         break;
1996                 case 'pointer':
1997                         var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
1998                                 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
1999                                 isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
2000                         return isOver;
2001                         break;
2002                 case 'touch':
2003                         return (
2004                                         (y1 >= t && y1 <= b) || // Top edge touching
2005                                         (y2 >= t && y2 <= b) || // Bottom edge touching
2006                                         (y1 < t && y2 > b)              // Surrounded vertically
2007                                 ) && (
2008                                         (x1 >= l && x1 <= r) || // Left edge touching
2009                                         (x2 >= l && x2 <= r) || // Right edge touching
2010                                         (x1 < l && x2 > r)              // Surrounded horizontally
2011                                 );
2012                         break;
2013                 default:
2014                         return false;
2015                         break;
2016                 }
2017
2018 };
2019
2020 /*
2021         This manager tracks offsets of draggables and droppables
2022 */
2023 $.ui.ddmanager = {
2024         current: null,
2025         droppables: { 'default': [] },
2026         prepareOffsets: function(t, event) {
2027
2028                 var m = $.ui.ddmanager.droppables[t.options.scope] || [];
2029                 var type = event ? event.type : null; // workaround for #2317
2030                 var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
2031
2032                 droppablesLoop: for (var i = 0; i < m.length; i++) {
2033
2034                         if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;   //No disabled and non-accepted
2035                         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
2036                         m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue;                                                                       //If the element is not visible, continue
2037
2038                         if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
2039
2040                         m[i].offset = m[i].element.offset();
2041                         m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
2042
2043                 }
2044
2045         },
2046         drop: function(draggable, event) {
2047
2048                 var dropped = false;
2049                 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
2050
2051                         if(!this.options) return;
2052                         if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
2053                                 dropped = this._drop.call(this, event) || dropped;
2054
2055                         if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2056                                 this.isout = 1; this.isover = 0;
2057                                 this._deactivate.call(this, event);
2058                         }
2059
2060                 });
2061                 return dropped;
2062
2063         },
2064         dragStart: function( draggable, event ) {
2065                 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
2066                 draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
2067                         if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
2068                 });
2069         },
2070         drag: function(draggable, event) {
2071
2072                 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
2073                 if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
2074
2075                 //Run through all droppables and check their positions based on specific tolerance options
2076                 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
2077
2078                         if(this.options.disabled || this.greedyChild || !this.visible) return;
2079                         var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
2080
2081                         var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
2082                         if(!c) return;
2083
2084                         var parentInstance;
2085                         if (this.options.greedy) {
2086                                 // find droppable parents with same scope
2087                                 var scope = this.options.scope;
2088                                 var parent = this.element.parents(':data(droppable)').filter(function () {
2089                                         return $.data(this, 'droppable').options.scope === scope;
2090                                 });
2091
2092                                 if (parent.length) {
2093                                         parentInstance = $.data(parent[0], 'droppable');
2094                                         parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
2095                                 }
2096                         }
2097
2098                         // we just moved into a greedy child
2099                         if (parentInstance && c == 'isover') {
2100                                 parentInstance['isover'] = 0;
2101                                 parentInstance['isout'] = 1;
2102                                 parentInstance._out.call(parentInstance, event);
2103                         }
2104
2105                         this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
2106                         this[c == "isover" ? "_over" : "_out"].call(this, event);
2107
2108                         // we just moved out of a greedy child
2109                         if (parentInstance && c == 'isout') {
2110                                 parentInstance['isout'] = 0;
2111                                 parentInstance['isover'] = 1;
2112                                 parentInstance._over.call(parentInstance, event);
2113                         }
2114                 });
2115
2116         },
2117         dragStop: function( draggable, event ) {
2118                 draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
2119                 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
2120                 if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
2121         }
2122 };
2123
2124 })(jQuery);
2125 (function( $, undefined ) {
2126
2127 $.widget("ui.resizable", $.ui.mouse, {
2128         version: "1.9.2",
2129         widgetEventPrefix: "resize",
2130         options: {
2131                 alsoResize: false,
2132                 animate: false,
2133                 animateDuration: "slow",
2134                 animateEasing: "swing",
2135                 aspectRatio: false,
2136                 autoHide: false,
2137                 containment: false,
2138                 ghost: false,
2139                 grid: false,
2140                 handles: "e,s,se",
2141                 helper: false,
2142                 maxHeight: null,
2143                 maxWidth: null,
2144                 minHeight: 10,
2145                 minWidth: 10,
2146                 zIndex: 1000
2147         },
2148         _create: function() {
2149
2150                 var that = this, o = this.options;
2151                 this.element.addClass("ui-resizable");
2152
2153                 $.extend(this, {
2154                         _aspectRatio: !!(o.aspectRatio),
2155                         aspectRatio: o.aspectRatio,
2156                         originalElement: this.element,
2157                         _proportionallyResizeElements: [],
2158                         _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
2159                 });
2160
2161                 //Wrap the element if it cannot hold child nodes
2162                 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
2163
2164                         //Create a wrapper element and set the wrapper to the new current internal element
2165                         this.element.wrap(
2166                                 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
2167                                         position: this.element.css('position'),
2168                                         width: this.element.outerWidth(),
2169                                         height: this.element.outerHeight(),
2170                                         top: this.element.css('top'),
2171                                         left: this.element.css('left')
2172                                 })
2173                         );
2174
2175                         //Overwrite the original this.element
2176                         this.element = this.element.parent().data(
2177                                 "resizable", this.element.data('resizable')
2178                         );
2179
2180                         this.elementIsWrapper = true;
2181
2182                         //Move margins to the wrapper
2183                         this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
2184                         this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
2185
2186                         //Prevent Safari textarea resize
2187                         this.originalResizeStyle = this.originalElement.css('resize');
2188                         this.originalElement.css('resize', 'none');
2189
2190                         //Push the actual element to our proportionallyResize internal array
2191                         this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
2192
2193                         // avoid IE jump (hard set the margin)
2194                         this.originalElement.css({ margin: this.originalElement.css('margin') });
2195
2196                         // fix handlers offset
2197                         this._proportionallyResize();
2198
2199                 }
2200
2201                 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' });
2202                 if(this.handles.constructor == String) {
2203
2204                         if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
2205                         var n = this.handles.split(","); this.handles = {};
2206
2207                         for(var i = 0; i < n.length; i++) {
2208
2209                                 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
2210                                 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
2211
2212                                 // Apply zIndex to all handles - see #7960
2213                                 axis.css({ zIndex: o.zIndex });
2214
2215                                 //TODO : What's going on here?
2216                                 if ('se' == handle) {
2217                                         axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
2218                                 };
2219
2220                                 //Insert into internal handles object and append to element
2221                                 this.handles[handle] = '.ui-resizable-'+handle;
2222                                 this.element.append(axis);
2223                         }
2224
2225                 }
2226
2227                 this._renderAxis = function(target) {
2228
2229                         target = target || this.element;
2230
2231                         for(var i in this.handles) {
2232
2233                                 if(this.handles[i].constructor == String)
2234                                         this.handles[i] = $(this.handles[i], this.element).show();
2235
2236                                 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
2237                                 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
2238
2239                                         var axis = $(this.handles[i], this.element), padWrapper = 0;
2240
2241                                         //Checking the correct pad and border
2242                                         padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
2243
2244                                         //The padding type i have to apply...
2245                                         var padPos = [ 'padding',
2246                                                 /ne|nw|n/.test(i) ? 'Top' :
2247                                                 /se|sw|s/.test(i) ? 'Bottom' :
2248                                                 /^e$/.test(i) ? 'Right' : 'Left' ].join("");
2249
2250                                         target.css(padPos, padWrapper);
2251
2252                                         this._proportionallyResize();
2253
2254                                 }
2255
2256                                 //TODO: What's that good for? There's not anything to be executed left
2257                                 if(!$(this.handles[i]).length)
2258                                         continue;
2259
2260                         }
2261                 };
2262
2263                 //TODO: make renderAxis a prototype function
2264                 this._renderAxis(this.element);
2265
2266                 this._handles = $('.ui-resizable-handle', this.element)
2267                         .disableSelection();
2268
2269                 //Matching axis name
2270                 this._handles.mouseover(function() {
2271                         if (!that.resizing) {
2272                                 if (this.className)
2273                                         var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
2274                                 //Axis, default = se
2275                                 that.axis = axis && axis[1] ? axis[1] : 'se';
2276                         }
2277                 });
2278
2279                 //If we want to auto hide the elements
2280                 if (o.autoHide) {
2281                         this._handles.hide();
2282                         $(this.element)
2283                                 .addClass("ui-resizable-autohide")
2284                                 .mouseenter(function() {
2285                                         if (o.disabled) return;
2286                                         $(this).removeClass("ui-resizable-autohide");
2287                                         that._handles.show();
2288                                 })
2289                                 .mouseleave(function(){
2290                                         if (o.disabled) return;
2291                                         if (!that.resizing) {
2292                                                 $(this).addClass("ui-resizable-autohide");
2293                                                 that._handles.hide();
2294                                         }
2295                                 });
2296                 }
2297
2298                 //Initialize the mouse interaction
2299                 this._mouseInit();
2300
2301         },
2302
2303         _destroy: function() {
2304
2305                 this._mouseDestroy();
2306
2307                 var _destroy = function(exp) {
2308                         $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
2309                                 .removeData("resizable").removeData("ui-resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
2310                 };
2311
2312                 //TODO: Unwrap at same DOM position
2313                 if (this.elementIsWrapper) {
2314                         _destroy(this.element);
2315                         var wrapper = this.element;
2316                         this.originalElement.css({
2317                                 position: wrapper.css('position'),
2318                                 width: wrapper.outerWidth(),
2319                                 height: wrapper.outerHeight(),
2320                                 top: wrapper.css('top'),
2321                                 left: wrapper.css('left')
2322                         }).insertAfter( wrapper );
2323                         wrapper.remove();
2324                 }
2325
2326                 this.originalElement.css('resize', this.originalResizeStyle);
2327                 _destroy(this.originalElement);
2328
2329                 return this;
2330         },
2331
2332         _mouseCapture: function(event) {
2333                 var handle = false;
2334                 for (var i in this.handles) {
2335                         if ($(this.handles[i])[0] == event.target) {
2336                                 handle = true;
2337                         }
2338                 }
2339
2340                 return !this.options.disabled && handle;
2341         },
2342
2343         _mouseStart: function(event) {
2344
2345                 var o = this.options, iniPos = this.element.position(), el = this.element;
2346
2347                 this.resizing = true;
2348                 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
2349
2350                 // bugfix for http://dev.jquery.com/ticket/1749
2351                 if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
2352                         el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
2353                 }
2354
2355                 this._renderProxy();
2356
2357                 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
2358
2359                 if (o.containment) {
2360                         curleft += $(o.containment).scrollLeft() || 0;
2361                         curtop += $(o.containment).scrollTop() || 0;
2362                 }
2363
2364                 //Store needed variables
2365                 this.offset = this.helper.offset();
2366                 this.position = { left: curleft, top: curtop };
2367                 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2368                 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2369                 this.originalPosition = { left: curleft, top: curtop };
2370                 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
2371                 this.originalMousePosition = { left: event.pageX, top: event.pageY };
2372
2373                 //Aspect Ratio
2374                 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
2375
2376                 var cursor = $('.ui-resizable-' + this.axis).css('cursor');
2377                 $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
2378
2379                 el.addClass("ui-resizable-resizing");
2380                 this._propagate("start", event);
2381                 return true;
2382         },
2383
2384         _mouseDrag: function(event) {
2385
2386                 //Increase performance, avoid regex
2387                 var el = this.helper, o = this.options, props = {},
2388                         that = this, smp = this.originalMousePosition, a = this.axis;
2389
2390                 var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
2391                 var trigger = this._change[a];
2392                 if (!trigger) return false;
2393
2394                 // Calculate the attrs that will be change
2395                 var data = trigger.apply(this, [event, dx, dy]);
2396
2397                 // Put this in the mouseDrag handler since the user can start pressing shift while resizing
2398                 this._updateVirtualBoundaries(event.shiftKey);
2399                 if (this._aspectRatio || event.shiftKey)
2400                         data = this._updateRatio(data, event);
2401
2402                 data = this._respectSize(data, event);
2403
2404                 // plugins callbacks need to be called first
2405                 this._propagate("resize", event);
2406
2407                 el.css({
2408                         top: this.position.top + "px", left: this.position.left + "px",
2409                         width: this.size.width + "px", height: this.size.height + "px"
2410                 });
2411
2412                 if (!this._helper && this._proportionallyResizeElements.length)
2413                         this._proportionallyResize();
2414
2415                 this._updateCache(data);
2416
2417                 // calling the user callback at the end
2418                 this._trigger('resize', event, this.ui());
2419
2420                 return false;
2421         },
2422
2423         _mouseStop: function(event) {
2424
2425                 this.resizing = false;
2426                 var o = this.options, that = this;
2427
2428                 if(this._helper) {
2429                         var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2430                                 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : that.sizeDiff.height,
2431                                 soffsetw = ista ? 0 : that.sizeDiff.width;
2432
2433                         var s = { width: (that.helper.width()  - soffsetw), height: (that.helper.height() - soffseth) },
2434                                 left = (parseInt(that.element.css('left'), 10) + (that.position.left - that.originalPosition.left)) || null,
2435                                 top = (parseInt(that.element.css('top'), 10) + (that.position.top - that.originalPosition.top)) || null;
2436
2437                         if (!o.animate)
2438                                 this.element.css($.extend(s, { top: top, left: left }));
2439
2440                         that.helper.height(that.size.height);
2441                         that.helper.width(that.size.width);
2442
2443                         if (this._helper && !o.animate) this._proportionallyResize();
2444                 }
2445
2446                 $('body').css('cursor', 'auto');
2447
2448                 this.element.removeClass("ui-resizable-resizing");
2449
2450                 this._propagate("stop", event);
2451
2452                 if (this._helper) this.helper.remove();
2453                 return false;
2454
2455         },
2456
2457         _updateVirtualBoundaries: function(forceAspectRatio) {
2458                 var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b;
2459
2460                 b = {
2461                         minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
2462                         maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
2463                         minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
2464                         maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
2465                 };
2466
2467                 if(this._aspectRatio || forceAspectRatio) {
2468                         // We want to create an enclosing box whose aspect ration is the requested one
2469                         // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
2470                         pMinWidth = b.minHeight * this.aspectRatio;
2471                         pMinHeight = b.minWidth / this.aspectRatio;
2472                         pMaxWidth = b.maxHeight * this.aspectRatio;
2473                         pMaxHeight = b.maxWidth / this.aspectRatio;
2474
2475                         if(pMinWidth > b.minWidth) b.minWidth = pMinWidth;
2476                         if(pMinHeight > b.minHeight) b.minHeight = pMinHeight;
2477                         if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth;
2478                         if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight;
2479                 }
2480                 this._vBoundaries = b;
2481         },
2482
2483         _updateCache: function(data) {
2484                 var o = this.options;
2485                 this.offset = this.helper.offset();
2486                 if (isNumber(data.left)) this.position.left = data.left;
2487                 if (isNumber(data.top)) this.position.top = data.top;
2488                 if (isNumber(data.height)) this.size.height = data.height;
2489                 if (isNumber(data.width)) this.size.width = data.width;
2490         },
2491
2492         _updateRatio: function(data, event) {
2493
2494                 var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
2495
2496                 if (isNumber(data.height)) data.width = (data.height * this.aspectRatio);
2497                 else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio);
2498
2499                 if (a == 'sw') {
2500                         data.left = cpos.left + (csize.width - data.width);
2501                         data.top = null;
2502                 }
2503                 if (a == 'nw') {
2504                         data.top = cpos.top + (csize.height - data.height);
2505                         data.left = cpos.left + (csize.width - data.width);
2506                 }
2507
2508                 return data;
2509         },
2510
2511         _respectSize: function(data, event) {
2512
2513                 var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
2514                                 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
2515                                         isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
2516
2517                 if (isminw) data.width = o.minWidth;
2518                 if (isminh) data.height = o.minHeight;
2519                 if (ismaxw) data.width = o.maxWidth;
2520                 if (ismaxh) data.height = o.maxHeight;
2521
2522                 var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
2523                 var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
2524
2525                 if (isminw && cw) data.left = dw - o.minWidth;
2526                 if (ismaxw && cw) data.left = dw - o.maxWidth;
2527                 if (isminh && ch)       data.top = dh - o.minHeight;
2528                 if (ismaxh && ch)       data.top = dh - o.maxHeight;
2529
2530                 // fixing jump error on top/left - bug #2330
2531                 var isNotwh = !data.width && !data.height;
2532                 if (isNotwh && !data.left && data.top) data.top = null;
2533                 else if (isNotwh && !data.top && data.left) data.left = null;
2534
2535                 return data;
2536         },
2537
2538         _proportionallyResize: function() {
2539
2540                 var o = this.options;
2541                 if (!this._proportionallyResizeElements.length) return;
2542                 var element = this.helper || this.element;
2543
2544                 for (var i=0; i < this._proportionallyResizeElements.length; i++) {
2545
2546                         var prel = this._proportionallyResizeElements[i];
2547
2548                         if (!this.borderDif) {
2549                                 var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
2550                                         p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
2551
2552                                 this.borderDif = $.map(b, function(v, i) {
2553                                         var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
2554                                         return border + padding;
2555                                 });
2556                         }
2557
2558                         prel.css({
2559                                 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
2560                                 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
2561                         });
2562
2563                 };
2564
2565         },
2566
2567         _renderProxy: function() {
2568
2569                 var el = this.element, o = this.options;
2570                 this.elementOffset = el.offset();
2571
2572                 if(this._helper) {
2573
2574                         this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
2575
2576                         // fix ie6 offset TODO: This seems broken
2577                         var ie6offset = ($.ui.ie6 ? 1 : 0),
2578                         pxyoffset = ( $.ui.ie6 ? 2 : -1 );
2579
2580                         this.helper.addClass(this._helper).css({
2581                                 width: this.element.outerWidth() + pxyoffset,
2582                                 height: this.element.outerHeight() + pxyoffset,
2583                                 position: 'absolute',
2584                                 left: this.elementOffset.left - ie6offset +'px',
2585                                 top: this.elementOffset.top - ie6offset +'px',
2586                                 zIndex: ++o.zIndex //TODO: Don't modify option
2587                         });
2588
2589                         this.helper
2590                                 .appendTo("body")
2591                                 .disableSelection();
2592
2593                 } else {
2594                         this.helper = this.element;
2595                 }
2596
2597         },
2598
2599         _change: {
2600                 e: function(event, dx, dy) {
2601                         return { width: this.originalSize.width + dx };
2602                 },
2603                 w: function(event, dx, dy) {
2604                         var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2605                         return { left: sp.left + dx, width: cs.width - dx };
2606                 },
2607                 n: function(event, dx, dy) {
2608                         var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2609                         return { top: sp.top + dy, height: cs.height - dy };
2610                 },
2611                 s: function(event, dx, dy) {
2612                         return { height: this.originalSize.height + dy };
2613                 },
2614                 se: function(event, dx, dy) {
2615                         return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2616                 },
2617                 sw: function(event, dx, dy) {
2618                         return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2619                 },
2620                 ne: function(event, dx, dy) {
2621                         return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2622                 },
2623                 nw: function(event, dx, dy) {
2624                         return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2625                 }
2626         },
2627
2628         _propagate: function(n, event) {
2629                 $.ui.plugin.call(this, n, [event, this.ui()]);
2630                 (n != "resize" && this._trigger(n, event, this.ui()));
2631         },
2632
2633         plugins: {},
2634
2635         ui: function() {
2636                 return {
2637                         originalElement: this.originalElement,
2638                         element: this.element,
2639                         helper: this.helper,
2640                         position: this.position,
2641                         size: this.size,
2642                         originalSize: this.originalSize,
2643                         originalPosition: this.originalPosition
2644                 };
2645         }
2646
2647 });
2648
2649 /*
2650  * Resizable Extensions
2651  */
2652
2653 $.ui.plugin.add("resizable", "alsoResize", {
2654
2655         start: function (event, ui) {
2656                 var that = $(this).data("resizable"), o = that.options;
2657
2658                 var _store = function (exp) {
2659                         $(exp).each(function() {
2660                                 var el = $(this);
2661                                 el.data("resizable-alsoresize", {
2662                                         width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
2663                                         left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10)
2664                                 });
2665                         });
2666                 };
2667
2668                 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
2669                         if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
2670                         else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
2671                 }else{
2672                         _store(o.alsoResize);
2673                 }
2674         },
2675
2676         resize: function (event, ui) {
2677                 var that = $(this).data("resizable"), o = that.options, os = that.originalSize, op = that.originalPosition;
2678
2679                 var delta = {
2680                         height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0,
2681                         top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0
2682                 },
2683
2684                 _alsoResize = function (exp, c) {
2685                         $(exp).each(function() {
2686                                 var el = $(this), start = $(this).data("resizable-alsoresize"), style = {},
2687                                         css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
2688
2689                                 $.each(css, function (i, prop) {
2690                                         var sum = (start[prop]||0) + (delta[prop]||0);
2691                                         if (sum && sum >= 0)
2692                                                 style[prop] = sum || null;
2693                                 });
2694
2695                                 el.css(style);
2696                         });
2697                 };
2698
2699                 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2700                         $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
2701                 }else{
2702                         _alsoResize(o.alsoResize);
2703                 }
2704         },
2705
2706         stop: function (event, ui) {
2707                 $(this).removeData("resizable-alsoresize");
2708         }
2709 });
2710
2711 $.ui.plugin.add("resizable", "animate", {
2712
2713         stop: function(event, ui) {
2714                 var that = $(this).data("resizable"), o = that.options;
2715
2716                 var pr = that._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2717                                         soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : that.sizeDiff.height,
2718                                                 soffsetw = ista ? 0 : that.sizeDiff.width;
2719
2720                 var style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
2721                                         left = (parseInt(that.element.css('left'), 10) + (that.position.left - that.originalPosition.left)) || null,
2722                                                 top = (parseInt(that.element.css('top'), 10) + (that.position.top - that.originalPosition.top)) || null;
2723
2724                 that.element.animate(
2725                         $.extend(style, top && left ? { top: top, left: left } : {}), {
2726                                 duration: o.animateDuration,
2727                                 easing: o.animateEasing,
2728                                 step: function() {
2729
2730                                         var data = {
2731                                                 width: parseInt(that.element.css('width'), 10),
2732                                                 height: parseInt(that.element.css('height'), 10),
2733                                                 top: parseInt(that.element.css('top'), 10),
2734                                                 left: parseInt(that.element.css('left'), 10)
2735                                         };
2736
2737                                         if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
2738
2739                                         // propagating resize, and updating values for each animation step
2740                                         that._updateCache(data);
2741                                         that._propagate("resize", event);
2742
2743                                 }
2744                         }
2745                 );
2746         }
2747
2748 });
2749
2750 $.ui.plugin.add("resizable", "containment", {
2751
2752         start: function(event, ui) {
2753                 var that = $(this).data("resizable"), o = that.options, el = that.element;
2754                 var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
2755                 if (!ce) return;
2756
2757                 that.containerElement = $(ce);
2758
2759                 if (/document/.test(oc) || oc == document) {
2760                         that.containerOffset = { left: 0, top: 0 };
2761                         that.containerPosition = { left: 0, top: 0 };
2762
2763                         that.parentData = {
2764                                 element: $(document), left: 0, top: 0,
2765                                 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
2766                         };
2767                 }
2768
2769                 // i'm a node, so compute top, left, right, bottom
2770                 else {
2771                         var element = $(ce), p = [];
2772                         $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
2773
2774                         that.containerOffset = element.offset();
2775                         that.containerPosition = element.position();
2776                         that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
2777
2778                         var co = that.containerOffset, ch = that.containerSize.height,  cw = that.containerSize.width,
2779                                                 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
2780
2781                         that.parentData = {
2782                                 element: ce, left: co.left, top: co.top, width: width, height: height
2783                         };
2784                 }
2785         },
2786
2787         resize: function(event, ui) {
2788                 var that = $(this).data("resizable"), o = that.options,
2789                                 ps = that.containerSize, co = that.containerOffset, cs = that.size, cp = that.position,
2790                                 pRatio = that._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = that.containerElement;
2791
2792                 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
2793
2794                 if (cp.left < (that._helper ? co.left : 0)) {
2795                         that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left));
2796                         if (pRatio) that.size.height = that.size.width / that.aspectRatio;
2797                         that.position.left = o.helper ? co.left : 0;
2798                 }
2799
2800                 if (cp.top < (that._helper ? co.top : 0)) {
2801                         that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top);
2802                         if (pRatio) that.size.width = that.size.height * that.aspectRatio;
2803                         that.position.top = that._helper ? co.top : 0;
2804                 }
2805
2806                 that.offset.left = that.parentData.left+that.position.left;
2807                 that.offset.top = that.parentData.top+that.position.top;
2808
2809                 var woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width ),
2810                                         hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height );
2811
2812                 var isParent = that.containerElement.get(0) == that.element.parent().get(0),
2813                         isOffsetRelative = /relative|absolute/.test(that.containerElement.css('position'));
2814
2815                 if(isParent && isOffsetRelative) woset -= that.parentData.left;
2816
2817                 if (woset + that.size.width >= that.parentData.width) {
2818                         that.size.width = that.parentData.width - woset;
2819                         if (pRatio) that.size.height = that.size.width / that.aspectRatio;
2820                 }
2821
2822                 if (hoset + that.size.height >= that.parentData.height) {
2823                         that.size.height = that.parentData.height - hoset;
2824                         if (pRatio) that.size.width = that.size.height * that.aspectRatio;
2825                 }
2826         },
2827
2828         stop: function(event, ui){
2829                 var that = $(this).data("resizable"), o = that.options, cp = that.position,
2830                                 co = that.containerOffset, cop = that.containerPosition, ce = that.containerElement;
2831
2832                 var helper = $(that.helper), ho = helper.offset(), w = helper.outerWidth() - that.sizeDiff.width, h = helper.outerHeight() - that.sizeDiff.height;
2833
2834                 if (that._helper && !o.animate && (/relative/).test(ce.css('position')))
2835                         $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2836
2837                 if (that._helper && !o.animate && (/static/).test(ce.css('position')))
2838                         $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2839
2840         }
2841 });
2842
2843 $.ui.plugin.add("resizable", "ghost", {
2844
2845         start: function(event, ui) {
2846
2847                 var that = $(this).data("resizable"), o = that.options, cs = that.size;
2848
2849                 that.ghost = that.originalElement.clone();
2850                 that.ghost
2851                         .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
2852                         .addClass('ui-resizable-ghost')
2853                         .addClass(typeof o.ghost == 'string' ? o.ghost : '');
2854
2855                 that.ghost.appendTo(that.helper);
2856
2857         },
2858
2859         resize: function(event, ui){
2860                 var that = $(this).data("resizable"), o = that.options;
2861                 if (that.ghost) that.ghost.css({ position: 'relative', height: that.size.height, width: that.size.width });
2862         },
2863
2864         stop: function(event, ui){
2865                 var that = $(this).data("resizable"), o = that.options;
2866                 if (that.ghost && that.helper) that.helper.get(0).removeChild(that.ghost.get(0));
2867         }
2868
2869 });
2870
2871 $.ui.plugin.add("resizable", "grid", {
2872
2873         resize: function(event, ui) {
2874                 var that = $(this).data("resizable"), o = that.options, cs = that.size, os = that.originalSize, op = that.originalPosition, a = that.axis, ratio = o._aspectRatio || event.shiftKey;
2875                 o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
2876                 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);
2877
2878                 if (/^(se|s|e)$/.test(a)) {
2879                         that.size.width = os.width + ox;
2880                         that.size.height = os.height + oy;
2881                 }
2882                 else if (/^(ne)$/.test(a)) {
2883                         that.size.width = os.width + ox;
2884                         that.size.height = os.height + oy;
2885                         that.position.top = op.top - oy;
2886                 }
2887                 else if (/^(sw)$/.test(a)) {
2888                         that.size.width = os.width + ox;
2889                         that.size.height = os.height + oy;
2890                         that.position.left = op.left - ox;
2891                 }
2892                 else {
2893                         that.size.width = os.width + ox;
2894                         that.size.height = os.height + oy;
2895                         that.position.top = op.top - oy;
2896                         that.position.left = op.left - ox;
2897                 }
2898         }
2899
2900 });
2901
2902 var num = function(v) {
2903         return parseInt(v, 10) || 0;
2904 };
2905
2906 var isNumber = function(value) {
2907         return !isNaN(parseInt(value, 10));
2908 };
2909
2910 })(jQuery);
2911 (function( $, undefined ) {
2912
2913 $.widget("ui.selectable", $.ui.mouse, {
2914         version: "1.9.2",
2915         options: {
2916                 appendTo: 'body',
2917                 autoRefresh: true,
2918                 distance: 0,
2919                 filter: '*',
2920                 tolerance: 'touch'
2921         },
2922         _create: function() {
2923                 var that = this;
2924
2925                 this.element.addClass("ui-selectable");
2926
2927                 this.dragged = false;
2928
2929                 // cache selectee children based on filter
2930                 var selectees;
2931                 this.refresh = function() {
2932                         selectees = $(that.options.filter, that.element[0]);
2933                         selectees.addClass("ui-selectee");
2934                         selectees.each(function() {
2935                                 var $this = $(this);
2936                                 var pos = $this.offset();
2937                                 $.data(this, "selectable-item", {
2938                                         element: this,
2939                                         $element: $this,
2940                                         left: pos.left,
2941                                         top: pos.top,
2942                                         right: pos.left + $this.outerWidth(),
2943                                         bottom: pos.top + $this.outerHeight(),
2944                                         startselected: false,
2945                                         selected: $this.hasClass('ui-selected'),
2946                                         selecting: $this.hasClass('ui-selecting'),
2947                                         unselecting: $this.hasClass('ui-unselecting')
2948                                 });
2949                         });
2950                 };
2951                 this.refresh();
2952
2953                 this.selectees = selectees.addClass("ui-selectee");
2954
2955                 this._mouseInit();
2956
2957                 this.helper = $("<div class='ui-selectable-helper'></div>");
2958         },
2959
2960         _destroy: function() {
2961                 this.selectees
2962                         .removeClass("ui-selectee")
2963                         .removeData("selectable-item");
2964                 this.element
2965                         .removeClass("ui-selectable ui-selectable-disabled");
2966                 this._mouseDestroy();
2967         },
2968
2969         _mouseStart: function(event) {
2970                 var that = this;
2971
2972                 this.opos = [event.pageX, event.pageY];
2973
2974                 if (this.options.disabled)
2975                         return;
2976
2977                 var options = this.options;
2978
2979                 this.selectees = $(options.filter, this.element[0]);
2980
2981                 this._trigger("start", event);
2982
2983                 $(options.appendTo).append(this.helper);
2984                 // position helper (lasso)
2985                 this.helper.css({
2986                         "left": event.clientX,
2987                         "top": event.clientY,
2988                         "width": 0,
2989                         "height": 0
2990                 });
2991
2992                 if (options.autoRefresh) {
2993                         this.refresh();
2994                 }
2995
2996                 this.selectees.filter('.ui-selected').each(function() {
2997                         var selectee = $.data(this, "selectable-item");
2998                         selectee.startselected = true;
2999                         if (!event.metaKey && !event.ctrlKey) {
3000                                 selectee.$element.removeClass('ui-selected');
3001                                 selectee.selected = false;
3002                                 selectee.$element.addClass('ui-unselecting');
3003                                 selectee.unselecting = true;
3004                                 // selectable UNSELECTING callback
3005                                 that._trigger("unselecting", event, {
3006                                         unselecting: selectee.element
3007                                 });
3008                         }
3009                 });
3010
3011                 $(event.target).parents().andSelf().each(function() {
3012                         var selectee = $.data(this, "selectable-item");
3013                         if (selectee) {
3014                                 var doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass('ui-selected');
3015                                 selectee.$element
3016                                         .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
3017                                         .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
3018                                 selectee.unselecting = !doSelect;
3019                                 selectee.selecting = doSelect;
3020                                 selectee.selected = doSelect;
3021                                 // selectable (UN)SELECTING callback
3022                                 if (doSelect) {
3023                                         that._trigger("selecting", event, {
3024                                                 selecting: selectee.element
3025                                         });
3026                                 } else {
3027                                         that._trigger("unselecting", event, {
3028                                                 unselecting: selectee.element
3029                                         });
3030                                 }
3031                                 return false;
3032                         }
3033                 });
3034
3035         },
3036
3037         _mouseDrag: function(event) {
3038                 var that = this;
3039                 this.dragged = true;
3040
3041                 if (this.options.disabled)
3042                         return;
3043
3044                 var options = this.options;
3045
3046                 var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
3047                 if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
3048                 if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
3049                 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
3050
3051                 this.selectees.each(function() {
3052                         var selectee = $.data(this, "selectable-item");
3053                         //prevent helper from being selected if appendTo: selectable
3054                         if (!selectee || selectee.element == that.element[0])
3055                                 return;
3056                         var hit = false;
3057                         if (options.tolerance == 'touch') {
3058                                 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
3059                         } else if (options.tolerance == 'fit') {
3060                                 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
3061                         }
3062
3063                         if (hit) {
3064                                 // SELECT
3065                                 if (selectee.selected) {
3066                                         selectee.$element.removeClass('ui-selected');
3067                                         selectee.selected = false;
3068                                 }
3069                                 if (selectee.unselecting) {
3070                                         selectee.$element.removeClass('ui-unselecting');
3071                                         selectee.unselecting = false;
3072                                 }
3073                                 if (!selectee.selecting) {
3074                                         selectee.$element.addClass('ui-selecting');
3075                                         selectee.selecting = true;
3076                                         // selectable SELECTING callback
3077                                         that._trigger("selecting", event, {
3078                                                 selecting: selectee.element
3079                                         });
3080                                 }
3081                         } else {
3082                                 // UNSELECT
3083                                 if (selectee.selecting) {
3084                                         if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
3085                                                 selectee.$element.removeClass('ui-selecting');
3086                                                 selectee.selecting = false;
3087                                                 selectee.$element.addClass('ui-selected');
3088                                                 selectee.selected = true;
3089                                         } else {
3090                                                 selectee.$element.removeClass('ui-selecting');
3091                                                 selectee.selecting = false;
3092                                                 if (selectee.startselected) {
3093                                                         selectee.$element.addClass('ui-unselecting');
3094                                                         selectee.unselecting = true;
3095                                                 }
3096                                                 // selectable UNSELECTING callback
3097                                                 that._trigger("unselecting", event, {
3098                                                         unselecting: selectee.element
3099                                                 });
3100                                         }
3101                                 }
3102                                 if (selectee.selected) {
3103                                         if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
3104                                                 selectee.$element.removeClass('ui-selected');
3105                                                 selectee.selected = false;
3106
3107                                                 selectee.$element.addClass('ui-unselecting');
3108                                                 selectee.unselecting = true;
3109                                                 // selectable UNSELECTING callback
3110                                                 that._trigger("unselecting", event, {
3111                                                         unselecting: selectee.element
3112                                                 });
3113                                         }
3114                                 }
3115                         }
3116                 });
3117
3118                 return false;
3119         },
3120
3121         _mouseStop: function(event) {
3122                 var that = this;
3123
3124                 this.dragged = false;
3125
3126                 var options = this.options;
3127
3128                 $('.ui-unselecting', this.element[0]).each(function() {
3129                         var selectee = $.data(this, "selectable-item");
3130                         selectee.$element.removeClass('ui-unselecting');
3131                         selectee.unselecting = false;
3132                         selectee.startselected = false;
3133                         that._trigger("unselected", event, {
3134                                 unselected: selectee.element
3135                         });
3136                 });
3137                 $('.ui-selecting', this.element[0]).each(function() {
3138                         var selectee = $.data(this, "selectable-item");
3139                         selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
3140                         selectee.selecting = false;
3141                         selectee.selected = true;
3142                         selectee.startselected = true;
3143                         that._trigger("selected", event, {
3144                                 selected: selectee.element
3145                         });
3146                 });
3147                 this._trigger("stop", event);
3148
3149                 this.helper.remove();
3150
3151                 return false;
3152         }
3153
3154 });
3155
3156 })(jQuery);
3157 (function( $, undefined ) {
3158
3159 $.widget("ui.sortable", $.ui.mouse, {
3160         version: "1.9.2",
3161         widgetEventPrefix: "sort",
3162         ready: false,
3163         options: {
3164                 appendTo: "parent",
3165                 axis: false,
3166                 connectWith: false,
3167                 containment: false,
3168                 cursor: 'auto',
3169                 cursorAt: false,
3170                 dropOnEmpty: true,
3171                 forcePlaceholderSize: false,
3172                 forceHelperSize: false,
3173                 grid: false,
3174                 handle: false,
3175                 helper: "original",
3176                 items: '> *',
3177                 opacity: false,
3178                 placeholder: false,
3179                 revert: false,
3180                 scroll: true,
3181                 scrollSensitivity: 20,
3182                 scrollSpeed: 20,
3183                 scope: "default",
3184                 tolerance: "intersect",
3185                 zIndex: 1000
3186         },
3187         _create: function() {
3188
3189                 var o = this.options;
3190                 this.containerCache = {};
3191                 this.element.addClass("ui-sortable");
3192
3193                 //Get the items
3194                 this.refresh();
3195
3196                 //Let's determine if the items are being displayed horizontally
3197                 this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;
3198
3199                 //Let's determine the parent's offset
3200                 this.offset = this.element.offset();
3201
3202                 //Initialize mouse events for interaction
3203                 this._mouseInit();
3204
3205                 //We're ready to go
3206                 this.ready = true
3207
3208         },
3209
3210         _destroy: function() {
3211                 this.element
3212                         .removeClass("ui-sortable ui-sortable-disabled");
3213                 this._mouseDestroy();
3214
3215                 for ( var i = this.items.length - 1; i >= 0; i-- )
3216                         this.items[i].item.removeData(this.widgetName + "-item");
3217
3218                 return this;
3219         },
3220
3221         _setOption: function(key, value){
3222                 if ( key === "disabled" ) {
3223                         this.options[ key ] = value;
3224
3225                         this.widget().toggleClass( "ui-sortable-disabled", !!value );
3226                 } else {
3227                         // Don't call widget base _setOption for disable as it adds ui-state-disabled class
3228                         $.Widget.prototype._setOption.apply(this, arguments);
3229                 }
3230         },
3231
3232         _mouseCapture: function(event, overrideHandle) {
3233                 var that = this;
3234
3235                 if (this.reverting) {
3236                         return false;
3237                 }
3238
3239                 if(this.options.disabled || this.options.type == 'static') return false;
3240
3241                 //We have to refresh the items data once first
3242                 this._refreshItems(event);
3243
3244                 //Find out if the clicked node (or one of its parents) is a actual item in this.items
3245                 var currentItem = null, nodes = $(event.target).parents().each(function() {
3246                         if($.data(this, that.widgetName + '-item') == that) {
3247                                 currentItem = $(this);
3248                                 return false;
3249                         }
3250                 });
3251                 if($.data(event.target, that.widgetName + '-item') == that) currentItem = $(event.target);
3252
3253                 if(!currentItem) return false;
3254                 if(this.options.handle && !overrideHandle) {
3255                         var validHandle = false;
3256
3257                         $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
3258                         if(!validHandle) return false;
3259                 }
3260
3261                 this.currentItem = currentItem;
3262                 this._removeCurrentsFromItems();
3263                 return true;
3264
3265         },
3266
3267         _mouseStart: function(event, overrideHandle, noActivation) {
3268
3269                 var o = this.options;
3270                 this.currentContainer = this;
3271
3272                 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
3273                 this.refreshPositions();
3274
3275                 //Create and append the visible helper
3276                 this.helper = this._createHelper(event);
3277
3278                 //Cache the helper size
3279                 this._cacheHelperProportions();
3280
3281                 /*
3282                  * - Position generation -
3283                  * This block generates everything position related - it's the core of draggables.
3284                  */
3285
3286                 //Cache the margins of the original element
3287                 this._cacheMargins();
3288
3289                 //Get the next scrolling parent
3290                 this.scrollParent = this.helper.scrollParent();
3291
3292                 //The element's absolute position on the page minus margins
3293                 this.offset = this.currentItem.offset();
3294                 this.offset = {
3295                         top: this.offset.top - this.margins.top,
3296                         left: this.offset.left - this.margins.left
3297                 };
3298
3299                 $.extend(this.offset, {
3300                         click: { //Where the click happened, relative to the element
3301                                 left: event.pageX - this.offset.left,
3302                                 top: event.pageY - this.offset.top
3303                         },
3304                         parent: this._getParentOffset(),
3305                         relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
3306                 });
3307
3308                 // Only after we got the offset, we can change the helper's position to absolute
3309                 // TODO: Still need to figure out a way to make relative sorting possible
3310                 this.helper.css("position", "absolute");
3311                 this.cssPosition = this.helper.css("position");
3312
3313                 //Generate the original position
3314                 this.originalPosition = this._generatePosition(event);
3315                 this.originalPageX = event.pageX;
3316                 this.originalPageY = event.pageY;
3317
3318                 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
3319                 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
3320
3321                 //Cache the former DOM position
3322                 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
3323
3324                 //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
3325                 if(this.helper[0] != this.currentItem[0]) {
3326                         this.currentItem.hide();
3327                 }
3328
3329                 //Create the placeholder
3330                 this._createPlaceholder();
3331
3332                 //Set a containment if given in the options
3333                 if(o.containment)
3334                         this._setContainment();
3335
3336                 if(o.cursor) { // cursor option
3337                         if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
3338                         $('body').css("cursor", o.cursor);
3339                 }
3340
3341                 if(o.opacity) { // opacity option
3342                         if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
3343                         this.helper.css("opacity", o.opacity);
3344                 }
3345
3346                 if(o.zIndex) { // zIndex option
3347                         if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
3348                         this.helper.css("zIndex", o.zIndex);
3349                 }
3350
3351                 //Prepare scrolling
3352                 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
3353                         this.overflowOffset = this.scrollParent.offset();
3354
3355                 //Call callbacks
3356                 this._trigger("start", event, this._uiHash());
3357
3358                 //Recache the helper size
3359                 if(!this._preserveHelperProportions)
3360                         this._cacheHelperProportions();
3361
3362
3363                 //Post 'activate' events to possible containers
3364                 if(!noActivation) {
3365                          for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, this._uiHash(this)); }
3366                 }
3367
3368                 //Prepare possible droppables
3369                 if($.ui.ddmanager)
3370                         $.ui.ddmanager.current = this;
3371
3372                 if ($.ui.ddmanager && !o.dropBehaviour)
3373                         $.ui.ddmanager.prepareOffsets(this, event);
3374
3375                 this.dragging = true;
3376
3377                 this.helper.addClass("ui-sortable-helper");
3378                 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
3379                 return true;
3380
3381         },
3382
3383         _mouseDrag: function(event) {
3384
3385                 //Compute the helpers position
3386                 this.position = this._generatePosition(event);
3387                 this.positionAbs = this._convertPositionTo("absolute");
3388
3389                 if (!this.lastPositionAbs) {
3390                         this.lastPositionAbs = this.positionAbs;
3391                 }
3392
3393                 //Do scrolling
3394                 if(this.options.scroll) {
3395                         var o = this.options, scrolled = false;
3396                         if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
3397
3398                                 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
3399                                         this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
3400                                 else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
3401                                         this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
3402
3403                                 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
3404                                         this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
3405                                 else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
3406                                         this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
3407
3408                         } else {
3409
3410                                 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
3411                                         scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
3412                                 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
3413                                         scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
3414
3415                                 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
3416                                         scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
3417                                 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
3418                                         scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
3419
3420                         }
3421
3422                         if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
3423                                 $.ui.ddmanager.prepareOffsets(this, event);
3424                 }
3425
3426                 //Regenerate the absolute position used for position checks
3427                 this.positionAbs = this._convertPositionTo("absolute");
3428
3429                 //Set the helper position
3430                 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
3431                 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
3432
3433                 //Rearrange
3434                 for (var i = this.items.length - 1; i >= 0; i--) {
3435
3436                         //Cache variables and intersection, continue if no intersection
3437                         var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
3438                         if (!intersection) continue;
3439
3440                         // Only put the placeholder inside the current Container, skip all
3441                         // items form other containers. This works because when moving
3442                         // an item from one container to another the
3443                         // currentContainer is switched before the placeholder is moved.
3444                         //
3445                         // Without this moving items in "sub-sortables" can cause the placeholder to jitter
3446                         // beetween the outer and inner container.
3447                         if (item.instance !== this.currentContainer) continue;
3448
3449                         if (itemElement != this.currentItem[0] //cannot intersect with itself
3450                                 &&      this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
3451                                 &&      !$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
3452                                 && (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true)
3453                                 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
3454                         ) {
3455
3456                                 this.direction = intersection == 1 ? "down" : "up";
3457
3458                                 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
3459                                         this._rearrange(event, item);
3460                                 } else {
3461                                         break;
3462                                 }
3463
3464                                 this._trigger("change", event, this._uiHash());
3465                                 break;
3466                         }
3467                 }
3468
3469                 //Post events to containers
3470                 this._contactContainers(event);
3471
3472                 //Interconnect with droppables
3473                 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
3474
3475                 //Call callbacks
3476                 this._trigger('sort', event, this._uiHash());
3477
3478                 this.lastPositionAbs = this.positionAbs;
3479                 return false;
3480
3481         },
3482
3483         _mouseStop: function(event, noPropagation) {
3484
3485                 if(!event) return;
3486
3487                 //If we are using droppables, inform the manager about the drop
3488                 if ($.ui.ddmanager && !this.options.dropBehaviour)
3489                         $.ui.ddmanager.drop(this, event);
3490
3491                 if(this.options.revert) {
3492                         var that = this;
3493                         var cur = this.placeholder.offset();
3494
3495                         this.reverting = true;
3496
3497                         $(this.helper).animate({
3498                                 left: cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
3499                                 top: cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
3500                         }, parseInt(this.options.revert, 10) || 500, function() {
3501                                 that._clear(event);
3502                         });
3503                 } else {
3504                         this._clear(event, noPropagation);
3505                 }
3506
3507                 return false;
3508
3509         },
3510
3511         cancel: function() {
3512
3513                 if(this.dragging) {
3514
3515                         this._mouseUp({ target: null });
3516
3517                         if(this.options.helper == "original")
3518                                 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
3519                         else
3520                                 this.currentItem.show();
3521
3522                         //Post deactivating events to containers
3523                         for (var i = this.containers.length - 1; i >= 0; i--){
3524                                 this.containers[i]._trigger("deactivate", null, this._uiHash(this));
3525                                 if(this.containers[i].containerCache.over) {
3526                                         this.containers[i]._trigger("out", null, this._uiHash(this));
3527                                         this.containers[i].containerCache.over = 0;
3528                                 }
3529                         }
3530
3531                 }
3532
3533                 if (this.placeholder) {
3534                         //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3535                         if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
3536                         if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
3537
3538                         $.extend(this, {
3539                                 helper: null,
3540                                 dragging: false,
3541                                 reverting: false,
3542                                 _noFinalSort: null
3543                         });
3544
3545                         if(this.domPosition.prev) {
3546                                 $(this.domPosition.prev).after(this.currentItem);
3547                         } else {
3548                                 $(this.domPosition.parent).prepend(this.currentItem);
3549                         }
3550                 }
3551
3552                 return this;
3553
3554         },
3555
3556         serialize: function(o) {
3557
3558                 var items = this._getItemsAsjQuery(o && o.connected);
3559                 var str = []; o = o || {};
3560
3561                 $(items).each(function() {
3562                         var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
3563                         if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
3564                 });
3565
3566                 if(!str.length && o.key) {
3567                         str.push(o.key + '=');
3568                 }
3569
3570                 return str.join('&');
3571
3572         },
3573
3574         toArray: function(o) {
3575
3576                 var items = this._getItemsAsjQuery(o && o.connected);
3577                 var ret = []; o = o || {};
3578
3579                 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
3580                 return ret;
3581
3582         },
3583
3584         /* Be careful with the following core functions */
3585         _intersectsWith: function(item) {
3586
3587                 var x1 = this.positionAbs.left,
3588                         x2 = x1 + this.helperProportions.width,
3589                         y1 = this.positionAbs.top,
3590                         y2 = y1 + this.helperProportions.height;
3591
3592                 var l = item.left,
3593                         r = l + item.width,
3594                         t = item.top,
3595                         b = t + item.height;
3596
3597                 var dyClick = this.offset.click.top,
3598                         dxClick = this.offset.click.left;
3599
3600                 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
3601
3602                 if(        this.options.tolerance == "pointer"
3603                         || this.options.forcePointerForContainers
3604                         || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
3605                 ) {
3606                         return isOverElement;
3607                 } else {
3608
3609                         return (l < x1 + (this.helperProportions.width / 2) // Right Half
3610                                 && x2 - (this.helperProportions.width / 2) < r // Left Half
3611                                 && t < y1 + (this.helperProportions.height / 2) // Bottom Half
3612                                 && y2 - (this.helperProportions.height / 2) < b ); // Top Half
3613
3614                 }
3615         },
3616
3617         _intersectsWithPointer: function(item) {
3618
3619                 var isOverElementHeight = (this.options.axis === 'x') || $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
3620                         isOverElementWidth = (this.options.axis === 'y') || $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
3621                         isOverElement = isOverElementHeight && isOverElementWidth,
3622                         verticalDirection = this._getDragVerticalDirection(),
3623                         horizontalDirection = this._getDragHorizontalDirection();
3624
3625                 if (!isOverElement)
3626                         return false;
3627
3628                 return this.floating ?
3629                         ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
3630                         : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
3631
3632         },
3633
3634         _intersectsWithSides: function(item) {
3635
3636                 var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
3637                         isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
3638                         verticalDirection = this._getDragVerticalDirection(),
3639                         horizontalDirection = this._getDragHorizontalDirection();
3640
3641                 if (this.floating && horizontalDirection) {
3642                         return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
3643                 } else {
3644                         return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
3645                 }
3646
3647         },
3648
3649         _getDragVerticalDirection: function() {
3650                 var delta = this.positionAbs.top - this.lastPositionAbs.top;
3651                 return delta != 0 && (delta > 0 ? "down" : "up");
3652         },
3653
3654         _getDragHorizontalDirection: function() {
3655                 var delta = this.positionAbs.left - this.lastPositionAbs.left;
3656                 return delta != 0 && (delta > 0 ? "right" : "left");
3657         },
3658
3659         refresh: function(event) {
3660                 this._refreshItems(event);
3661                 this.refreshPositions();
3662                 return this;
3663         },
3664
3665         _connectWith: function() {
3666                 var options = this.options;
3667                 return options.connectWith.constructor == String
3668                         ? [options.connectWith]
3669                         : options.connectWith;
3670         },
3671
3672         _getItemsAsjQuery: function(connected) {
3673
3674                 var items = [];
3675                 var queries = [];
3676                 var connectWith = this._connectWith();
3677
3678                 if(connectWith && connected) {
3679                         for (var i = connectWith.length - 1; i >= 0; i--){
3680                                 var cur = $(connectWith[i]);
3681                                 for (var j = cur.length - 1; j >= 0; j--){
3682                                         var inst = $.data(cur[j], this.widgetName);
3683                                         if(inst && inst != this && !inst.options.disabled) {
3684                                                 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]);
3685                                         }
3686                                 };
3687                         };
3688                 }
3689
3690                 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]);
3691
3692                 for (var i = queries.length - 1; i >= 0; i--){
3693                         queries[i][0].each(function() {
3694                                 items.push(this);
3695                         });
3696                 };
3697
3698                 return $(items);
3699
3700         },
3701
3702         _removeCurrentsFromItems: function() {
3703
3704                 var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
3705
3706                 this.items = $.grep(this.items, function (item) {
3707                         for (var j=0; j < list.length; j++) {
3708                                 if(list[j] == item.item[0])
3709                                         return false;
3710                         };
3711                         return true;
3712                 });
3713
3714         },
3715
3716         _refreshItems: function(event) {
3717
3718                 this.items = [];
3719                 this.containers = [this];
3720                 var items = this.items;
3721                 var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
3722                 var connectWith = this._connectWith();
3723
3724                 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
3725                         for (var i = connectWith.length - 1; i >= 0; i--){
3726                                 var cur = $(connectWith[i]);
3727                                 for (var j = cur.length - 1; j >= 0; j--){
3728                                         var inst = $.data(cur[j], this.widgetName);
3729                                         if(inst && inst != this && !inst.options.disabled) {
3730                                                 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
3731                                                 this.containers.push(inst);
3732                                         }
3733                                 };
3734                         };
3735                 }
3736
3737                 for (var i = queries.length - 1; i >= 0; i--) {
3738                         var targetData = queries[i][1];
3739                         var _queries = queries[i][0];
3740
3741                         for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
3742                                 var item = $(_queries[j]);
3743
3744                                 item.data(this.widgetName + '-item', targetData); // Data for target checking (mouse manager)
3745
3746                                 items.push({
3747                                         item: item,
3748                                         instance: targetData,
3749                                         width: 0, height: 0,
3750                                         left: 0, top: 0
3751                                 });
3752                         };
3753                 };
3754
3755         },
3756
3757         refreshPositions: function(fast) {
3758
3759                 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
3760                 if(this.offsetParent && this.helper) {
3761                         this.offset.parent = this._getParentOffset();
3762                 }
3763
3764                 for (var i = this.items.length - 1; i >= 0; i--){
3765                         var item = this.items[i];
3766
3767                         //We ignore calculating positions of all connected containers when we're not over them
3768                         if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
3769                                 continue;
3770
3771                         var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
3772
3773                         if (!fast) {
3774                                 item.width = t.outerWidth();
3775                                 item.height = t.outerHeight();
3776                         }
3777
3778                         var p = t.offset();
3779                         item.left = p.left;
3780                         item.top = p.top;
3781                 };
3782
3783                 if(this.options.custom && this.options.custom.refreshContainers) {
3784                         this.options.custom.refreshContainers.call(this);
3785                 } else {
3786                         for (var i = this.containers.length - 1; i >= 0; i--){
3787                                 var p = this.containers[i].element.offset();
3788                                 this.containers[i].containerCache.left = p.left;
3789                                 this.containers[i].containerCache.top = p.top;
3790                                 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
3791                                 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
3792                         };
3793                 }
3794
3795                 return this;
3796         },
3797
3798         _createPlaceholder: function(that) {
3799                 that = that || this;
3800                 var o = that.options;
3801
3802                 if(!o.placeholder || o.placeholder.constructor == String) {
3803                         var className = o.placeholder;
3804                         o.placeholder = {
3805                                 element: function() {
3806
3807                                         var el = $(document.createElement(that.currentItem[0].nodeName))
3808                                                 .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
3809                                                 .removeClass("ui-sortable-helper")[0];
3810
3811                                         if(!className)
3812                                                 el.style.visibility = "hidden";
3813
3814                                         return el;
3815                                 },
3816                                 update: function(container, p) {
3817
3818                                         // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
3819                                         // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
3820                                         if(className && !o.forcePlaceholderSize) return;
3821
3822                                         //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
3823                                         if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css('paddingTop')||0, 10) - parseInt(that.currentItem.css('paddingBottom')||0, 10)); };
3824                                         if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css('paddingLeft')||0, 10) - parseInt(that.currentItem.css('paddingRight')||0, 10)); };
3825                                 }
3826                         };
3827                 }
3828
3829                 //Create the placeholder
3830                 that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
3831
3832                 //Append it after the actual current item
3833                 that.currentItem.after(that.placeholder);
3834
3835                 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
3836                 o.placeholder.update(that, that.placeholder);
3837
3838         },
3839
3840         _contactContainers: function(event) {
3841
3842                 // get innermost container that intersects with item
3843                 var innermostContainer = null, innermostIndex = null;
3844
3845
3846                 for (var i = this.containers.length - 1; i >= 0; i--){
3847
3848                         // never consider a container that's located within the item itself
3849                         if($.contains(this.currentItem[0], this.containers[i].element[0]))
3850                                 continue;
3851
3852                         if(this._intersectsWith(this.containers[i].containerCache)) {
3853
3854                                 // if we've already found a container and it's more "inner" than this, then continue
3855                                 if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0]))
3856                                         continue;
3857
3858                                 innermostContainer = this.containers[i];
3859                                 innermostIndex = i;
3860
3861                         } else {
3862                                 // container doesn't intersect. trigger "out" event if necessary
3863                                 if(this.containers[i].containerCache.over) {
3864                                         this.containers[i]._trigger("out", event, this._uiHash(this));
3865                                         this.containers[i].containerCache.over = 0;
3866                                 }
3867                         }
3868
3869                 }
3870
3871                 // if no intersecting containers found, return
3872                 if(!innermostContainer) return;
3873
3874                 // move the item into the container if it's not there already
3875                 if(this.containers.length === 1) {
3876                         this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3877                         this.containers[innermostIndex].containerCache.over = 1;
3878                 } else {
3879
3880                         //When entering a new container, we will find the item with the least distance and append our item near it
3881                         var dist = 10000; var itemWithLeastDistance = null;
3882                         var posProperty = this.containers[innermostIndex].floating ? 'left' : 'top';
3883                         var sizeProperty = this.containers[innermostIndex].floating ? 'width' : 'height';
3884                         var base = this.positionAbs[posProperty] + this.offset.click[posProperty];
3885                         for (var j = this.items.length - 1; j >= 0; j--) {
3886                                 if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
3887                                 if(this.items[j].item[0] == this.currentItem[0]) continue;
3888                                 var cur = this.items[j].item.offset()[posProperty];
3889                                 var nearBottom = false;
3890                                 if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){
3891                                         nearBottom = true;
3892                                         cur += this.items[j][sizeProperty];
3893                                 }
3894
3895                                 if(Math.abs(cur - base) < dist) {
3896                                         dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
3897                                         this.direction = nearBottom ? "up": "down";
3898                                 }
3899                         }
3900
3901                         if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
3902                                 return;
3903
3904                         this.currentContainer = this.containers[innermostIndex];
3905                         itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
3906                         this._trigger("change", event, this._uiHash());
3907                         this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
3908
3909                         //Update the placeholder
3910                         this.options.placeholder.update(this.currentContainer, this.placeholder);
3911
3912                         this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3913                         this.containers[innermostIndex].containerCache.over = 1;
3914                 }
3915
3916
3917         },
3918
3919         _createHelper: function(event) {
3920
3921                 var o = this.options;
3922                 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
3923
3924                 if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
3925                         $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
3926
3927                 if(helper[0] == this.currentItem[0])
3928                         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") };
3929
3930                 if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
3931                 if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
3932
3933                 return helper;
3934
3935         },
3936
3937         _adjustOffsetFromHelper: function(obj) {
3938                 if (typeof obj == 'string') {
3939                         obj = obj.split(' ');
3940                 }
3941                 if ($.isArray(obj)) {
3942                         obj = {left: +obj[0], top: +obj[1] || 0};
3943                 }
3944                 if ('left' in obj) {
3945                         this.offset.click.left = obj.left + this.margins.left;
3946                 }
3947                 if ('right' in obj) {
3948                         this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
3949                 }
3950                 if ('top' in obj) {
3951                         this.offset.click.top = obj.top + this.margins.top;
3952                 }
3953                 if ('bottom' in obj) {
3954                         this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
3955                 }
3956         },
3957
3958         _getParentOffset: function() {
3959
3960
3961                 //Get the offsetParent and cache its position
3962                 this.offsetParent = this.helper.offsetParent();
3963                 var po = this.offsetParent.offset();
3964
3965                 // This is a special case where we need to modify a offset calculated on start, since the following happened:
3966                 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
3967                 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
3968                 //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
3969                 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
3970                         po.left += this.scrollParent.scrollLeft();
3971                         po.top += this.scrollParent.scrollTop();
3972                 }
3973
3974                 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
3975                 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.ui.ie)) //Ugly IE fix
3976                         po = { top: 0, left: 0 };
3977
3978                 return {
3979                         top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
3980                         left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
3981                 };
3982
3983         },
3984
3985         _getRelativeOffset: function() {
3986
3987                 if(this.cssPosition == "relative") {
3988                         var p = this.currentItem.position();
3989                         return {
3990                                 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
3991                                 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
3992                         };
3993                 } else {
3994                         return { top: 0, left: 0 };
3995                 }
3996
3997         },
3998
3999         _cacheMargins: function() {
4000                 this.margins = {
4001                         left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
4002                         top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
4003                 };
4004         },
4005
4006         _cacheHelperProportions: function() {
4007                 this.helperProportions = {
4008                         width: this.helper.outerWidth(),
4009                         height: this.helper.outerHeight()
4010                 };
4011         },
4012
4013         _setContainment: function() {
4014
4015                 var o = this.options;
4016                 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
4017                 if(o.containment == 'document' || o.containment == 'window') this.containment = [
4018                         0 - this.offset.relative.left - this.offset.parent.left,
4019                         0 - this.offset.relative.top - this.offset.parent.top,
4020                         $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
4021                         ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
4022                 ];
4023
4024                 if(!(/^(document|window|parent)$/).test(o.containment)) {
4025                         var ce = $(o.containment)[0];
4026                         var co = $(o.containment).offset();
4027                         var over = ($(ce).css("overflow") != 'hidden');
4028
4029                         this.containment = [
4030                                 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
4031                                 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
4032                                 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,
4033                                 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
4034                         ];
4035                 }
4036
4037         },
4038
4039         _convertPositionTo: function(d, pos) {
4040
4041                 if(!pos) pos = this.position;
4042                 var mod = d == "absolute" ? 1 : -1;
4043                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
4044
4045                 return {
4046                         top: (
4047                                 pos.top                                                                                                                                 // The absolute mouse position
4048                                 + this.offset.relative.top * mod                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
4049                                 + this.offset.parent.top * mod                                                                                  // The offsetParent's offset without borders (offset + border)
4050                                 - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
4051                         ),
4052                         left: (
4053                                 pos.left                                                                                                                                // The absolute mouse position
4054                                 + this.offset.relative.left * mod                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
4055                                 + this.offset.parent.left * mod                                                                                 // The offsetParent's offset without borders (offset + border)
4056                                 - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
4057                         )
4058                 };
4059
4060         },
4061
4062         _generatePosition: function(event) {
4063
4064                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
4065
4066                 // This is another very weird special case that only happens for relative elements:
4067                 // 1. If the css position is relative
4068                 // 2. and the scroll parent is the document or similar to the offset parent
4069                 // we have to refresh the relative offset during the scroll so there are no jumps
4070                 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
4071                         this.offset.relative = this._getRelativeOffset();
4072                 }
4073
4074                 var pageX = event.pageX;
4075                 var pageY = event.pageY;
4076
4077                 /*
4078                  * - Position constraining -
4079                  * Constrain the position to a mix of grid, containment.
4080                  */
4081
4082                 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
4083
4084                         if(this.containment) {
4085                                 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
4086                                 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
4087                                 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
4088                                 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
4089                         }
4090
4091                         if(o.grid) {
4092                                 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
4093                                 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;
4094
4095                                 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
4096                                 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;
4097                         }
4098
4099                 }
4100
4101                 return {
4102                         top: (
4103                                 pageY                                                                                                                           // The absolute mouse position
4104                                 - this.offset.click.top                                                                                                 // Click offset (relative to the element)
4105                                 - this.offset.relative.top                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
4106                                 - this.offset.parent.top                                                                                                // The offsetParent's offset without borders (offset + border)
4107                                 + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
4108                         ),
4109                         left: (
4110                                 pageX                                                                                                                           // The absolute mouse position
4111                                 - this.offset.click.left                                                                                                // Click offset (relative to the element)
4112                                 - this.offset.relative.left                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
4113                                 - this.offset.parent.left                                                                                               // The offsetParent's offset without borders (offset + border)
4114                                 + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
4115                         )
4116                 };
4117
4118         },
4119
4120         _rearrange: function(event, i, a, hardRefresh) {
4121
4122                 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));
4123
4124                 //Various things done here to improve the performance:
4125                 // 1. we create a setTimeout, that calls refreshPositions
4126                 // 2. on the instance, we have a counter variable, that get's higher after every append
4127                 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
4128                 // 4. this lets only the last addition to the timeout stack through
4129                 this.counter = this.counter ? ++this.counter : 1;
4130                 var counter = this.counter;
4131
4132                 this._delay(function() {
4133                         if(counter == this.counter) this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
4134                 });
4135
4136         },
4137
4138         _clear: function(event, noPropagation) {
4139
4140                 this.reverting = false;
4141                 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
4142                 // everything else normalized again
4143                 var delayedTriggers = [];
4144
4145                 // We first have to update the dom position of the actual currentItem
4146                 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
4147                 if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem);
4148                 this._noFinalSort = null;
4149
4150                 if(this.helper[0] == this.currentItem[0]) {
4151                         for(var i in this._storedCSS) {
4152                                 if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
4153                         }
4154                         this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
4155                 } else {
4156                         this.currentItem.show();
4157                 }
4158
4159                 if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
4160                 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
4161
4162                 // Check if the items Container has Changed and trigger appropriate
4163                 // events.
4164                 if (this !== this.currentContainer) {
4165                         if(!noPropagation) {
4166                                 delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
4167                                 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.currentContainer));
4168                                 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.currentContainer));
4169                         }
4170                 }
4171
4172
4173                 //Post events to containers
4174                 for (var i = this.containers.length - 1; i >= 0; i--){
4175                         if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
4176                         if(this.containers[i].containerCache.over) {
4177                                 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
4178                                 this.containers[i].containerCache.over = 0;
4179                         }
4180                 }
4181
4182                 //Do what was originally in plugins
4183                 if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
4184                 if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
4185                 if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
4186
4187                 this.dragging = false;
4188                 if(this.cancelHelperRemoval) {
4189                         if(!noPropagation) {
4190                                 this._trigger("beforeStop", event, this._uiHash());
4191                                 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
4192                                 this._trigger("stop", event, this._uiHash());
4193                         }
4194
4195                         this.fromOutside = false;
4196                         return false;
4197                 }
4198
4199                 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
4200
4201                 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
4202                 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
4203
4204                 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
4205
4206                 if(!noPropagation) {
4207                         for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
4208                         this._trigger("stop", event, this._uiHash());
4209                 }
4210
4211                 this.fromOutside = false;
4212                 return true;
4213
4214         },
4215
4216         _trigger: function() {
4217                 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
4218                         this.cancel();
4219                 }
4220         },
4221
4222         _uiHash: function(_inst) {
4223                 var inst = _inst || this;
4224                 return {
4225                         helper: inst.helper,
4226                         placeholder: inst.placeholder || $([]),
4227                         position: inst.position,
4228                         originalPosition: inst.originalPosition,
4229                         offset: inst.positionAbs,
4230                         item: inst.currentItem,
4231                         sender: _inst ? _inst.element : null
4232                 };
4233         }
4234
4235 });
4236
4237 })(jQuery);
4238 (function( $, undefined ) {
4239
4240 $.widget( "ui.progressbar", {
4241         version: "1.9.2",
4242         options: {
4243                 value: 0,
4244                 max: 100
4245         },
4246
4247         min: 0,
4248
4249         _create: function() {
4250                 this.element
4251                         .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
4252                         .attr({
4253                                 role: "progressbar",
4254                                 "aria-valuemin": this.min,
4255                                 "aria-valuemax": this.options.max,
4256                                 "aria-valuenow": this._value()
4257                         });
4258
4259                 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
4260                         .appendTo( this.element );
4261
4262                 this.oldValue = this._value();
4263                 this._refreshValue();
4264         },
4265
4266         _destroy: function() {
4267                 this.element
4268                         .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
4269                         .removeAttr( "role" )
4270                         .removeAttr( "aria-valuemin" )
4271                         .removeAttr( "aria-valuemax" )
4272                         .removeAttr( "aria-valuenow" );
4273
4274                 this.valueDiv.remove();
4275         },
4276
4277         value: function( newValue ) {
4278                 if ( newValue === undefined ) {
4279                         return this._value();
4280                 }
4281
4282                 this._setOption( "value", newValue );
4283                 return this;
4284         },
4285
4286         _setOption: function( key, value ) {
4287                 if ( key === "value" ) {
4288                         this.options.value = value;
4289                         this._refreshValue();
4290                         if ( this._value() === this.options.max ) {
4291                                 this._trigger( "complete" );
4292                         }
4293                 }
4294
4295                 this._super( key, value );
4296         },
4297
4298         _value: function() {
4299                 var val = this.options.value;
4300                 // normalize invalid value
4301                 if ( typeof val !== "number" ) {
4302                         val = 0;
4303                 }
4304                 return Math.min( this.options.max, Math.max( this.min, val ) );
4305         },
4306
4307         _percentage: function() {
4308                 return 100 * this._value() / this.options.max;
4309         },
4310
4311         _refreshValue: function() {
4312                 var value = this.value(),
4313                         percentage = this._percentage();
4314
4315                 if ( this.oldValue !== value ) {
4316                         this.oldValue = value;
4317                         this._trigger( "change" );
4318                 }
4319
4320                 this.valueDiv
4321                         .toggle( value > this.min )
4322                         .toggleClass( "ui-corner-right", value === this.options.max )
4323                         .width( percentage.toFixed(0) + "%" );
4324                 this.element.attr( "aria-valuenow", value );
4325         }
4326 });
4327
4328 })( jQuery );
4329 (function( $, undefined ) {
4330
4331 var tabId = 0,
4332         rhash = /#.*$/;
4333
4334 function getNextTabId() {
4335         return ++tabId;
4336 }
4337
4338 function isLocal( anchor ) {
4339         return anchor.hash.length > 1 &&
4340                 anchor.href.replace( rhash, "" ) ===
4341                         location.href.replace( rhash, "" )
4342                                 // support: Safari 5.1
4343                                 // Safari 5.1 doesn't encode spaces in window.location
4344                                 // but it does encode spaces from anchors (#8777)
4345                                 .replace( /\s/g, "%20" );
4346 }
4347
4348 $.widget( "ui.tabs", {
4349         version: "1.9.2",
4350         delay: 300,
4351         options: {
4352                 active: null,
4353                 collapsible: false,
4354                 event: "click",
4355                 heightStyle: "content",
4356                 hide: null,
4357                 show: null,
4358
4359                 // callbacks
4360                 activate: null,
4361                 beforeActivate: null,
4362                 beforeLoad: null,
4363                 load: null
4364         },
4365
4366         _create: function() {
4367                 var that = this,
4368                         options = this.options,
4369                         active = options.active,
4370                         locationHash = location.hash.substring( 1 );
4371
4372                 this.running = false;
4373
4374                 this.element
4375                         .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
4376                         .toggleClass( "ui-tabs-collapsible", options.collapsible )
4377                         // Prevent users from focusing disabled tabs via click
4378                         .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
4379                                 if ( $( this ).is( ".ui-state-disabled" ) ) {
4380                                         event.preventDefault();
4381                                 }
4382                         })
4383                         // support: IE <9
4384                         // Preventing the default action in mousedown doesn't prevent IE
4385                         // from focusing the element, so if the anchor gets focused, blur.
4386                         // We don't have to worry about focusing the previously focused
4387                         // element since clicking on a non-focusable element should focus
4388                         // the body anyway.
4389                         .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
4390                                 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
4391                                         this.blur();
4392                                 }
4393                         });
4394
4395                 this._processTabs();
4396
4397                 if ( active === null ) {
4398                         // check the fragment identifier in the URL
4399                         if ( locationHash ) {
4400                                 this.tabs.each(function( i, tab ) {
4401                                         if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
4402                                                 active = i;
4403                                                 return false;
4404                                         }
4405                                 });
4406                         }
4407
4408                         // check for a tab marked active via a class
4409                         if ( active === null ) {
4410                                 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
4411                         }
4412
4413                         // no active tab, set to false
4414                         if ( active === null || active === -1 ) {
4415                                 active = this.tabs.length ? 0 : false;
4416                         }
4417                 }
4418
4419                 // handle numbers: negative, out of range
4420                 if ( active !== false ) {
4421                         active = this.tabs.index( this.tabs.eq( active ) );
4422                         if ( active === -1 ) {
4423                                 active = options.collapsible ? false : 0;
4424                         }
4425                 }
4426                 options.active = active;
4427
4428                 // don't allow collapsible: false and active: false
4429                 if ( !options.collapsible && options.active === false && this.anchors.length ) {
4430                         options.active = 0;
4431                 }
4432
4433                 // Take disabling tabs via class attribute from HTML
4434                 // into account and update option properly.
4435                 if ( $.isArray( options.disabled ) ) {
4436                         options.disabled = $.unique( options.disabled.concat(
4437                                 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
4438                                         return that.tabs.index( li );
4439                                 })
4440                         ) ).sort();
4441                 }
4442
4443                 // check for length avoids error when initializing empty list
4444                 if ( this.options.active !== false && this.anchors.length ) {
4445                         this.active = this._findActive( this.options.active );
4446                 } else {
4447                         this.active = $();
4448                 }
4449
4450                 this._refresh();
4451
4452                 if ( this.active.length ) {
4453                         this.load( options.active );
4454                 }
4455         },
4456
4457         _getCreateEventData: function() {
4458                 return {
4459                         tab: this.active,
4460                         panel: !this.active.length ? $() : this._getPanelForTab( this.active )
4461                 };
4462         },
4463
4464         _tabKeydown: function( event ) {
4465                 var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
4466                         selectedIndex = this.tabs.index( focusedTab ),
4467                         goingForward = true;
4468
4469                 if ( this._handlePageNav( event ) ) {
4470                         return;
4471                 }
4472
4473                 switch ( event.keyCode ) {
4474                         case $.ui.keyCode.RIGHT:
4475                         case $.ui.keyCode.DOWN:
4476                                 selectedIndex++;
4477                                 break;
4478                         case $.ui.keyCode.UP:
4479                         case $.ui.keyCode.LEFT:
4480                                 goingForward = false;
4481                                 selectedIndex--;
4482                                 break;
4483                         case $.ui.keyCode.END:
4484                                 selectedIndex = this.anchors.length - 1;
4485                                 break;
4486                         case $.ui.keyCode.HOME:
4487                                 selectedIndex = 0;
4488                                 break;
4489                         case $.ui.keyCode.SPACE:
4490                                 // Activate only, no collapsing
4491                                 event.preventDefault();
4492                                 clearTimeout( this.activating );
4493                                 this._activate( selectedIndex );
4494                                 return;
4495                         case $.ui.keyCode.ENTER:
4496                                 // Toggle (cancel delayed activation, allow collapsing)
4497                                 event.preventDefault();
4498                                 clearTimeout( this.activating );
4499                                 // Determine if we should collapse or activate
4500                                 this._activate( selectedIndex === this.options.active ? false : selectedIndex );
4501                                 return;
4502                         default:
4503                                 return;
4504                 }
4505
4506                 // Focus the appropriate tab, based on which key was pressed
4507                 event.preventDefault();
4508                 clearTimeout( this.activating );
4509                 selectedIndex = this._focusNextTab( selectedIndex, goingForward );
4510
4511                 // Navigating with control key will prevent automatic activation
4512                 if ( !event.ctrlKey ) {
4513                         // Update aria-selected immediately so that AT think the tab is already selected.
4514                         // Otherwise AT may confuse the user by stating that they need to activate the tab,
4515                         // but the tab will already be activated by the time the announcement finishes.
4516                         focusedTab.attr( "aria-selected", "false" );
4517                         this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
4518
4519                         this.activating = this._delay(function() {
4520                                 this.option( "active", selectedIndex );
4521                         }, this.delay );
4522                 }
4523         },
4524
4525         _panelKeydown: function( event ) {
4526                 if ( this._handlePageNav( event ) ) {
4527                         return;
4528                 }
4529
4530                 // Ctrl+up moves focus to the current tab
4531                 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
4532                         event.preventDefault();
4533                         this.active.focus();
4534                 }
4535         },
4536
4537         // Alt+page up/down moves focus to the previous/next tab (and activates)
4538         _handlePageNav: function( event ) {
4539                 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
4540                         this._activate( this._focusNextTab( this.options.active - 1, false ) );
4541                         return true;
4542                 }
4543                 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
4544                         this._activate( this._focusNextTab( this.options.active + 1, true ) );
4545                         return true;
4546                 }
4547         },
4548
4549         _findNextTab: function( index, goingForward ) {
4550                 var lastTabIndex = this.tabs.length - 1;
4551
4552                 function constrain() {
4553                         if ( index > lastTabIndex ) {
4554                                 index = 0;
4555                         }
4556                         if ( index < 0 ) {
4557                                 index = lastTabIndex;
4558                         }
4559                         return index;
4560                 }
4561
4562                 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
4563                         index = goingForward ? index + 1 : index - 1;
4564                 }
4565
4566                 return index;
4567         },
4568
4569         _focusNextTab: function( index, goingForward ) {
4570                 index = this._findNextTab( index, goingForward );
4571                 this.tabs.eq( index ).focus();
4572                 return index;
4573         },
4574
4575         _setOption: function( key, value ) {
4576                 if ( key === "active" ) {
4577                         // _activate() will handle invalid values and update this.options
4578                         this._activate( value );
4579                         return;
4580                 }
4581
4582                 if ( key === "disabled" ) {
4583                         // don't use the widget factory's disabled handling
4584                         this._setupDisabled( value );
4585                         return;
4586                 }
4587
4588                 this._super( key, value);
4589
4590                 if ( key === "collapsible" ) {
4591                         this.element.toggleClass( "ui-tabs-collapsible", value );
4592                         // Setting collapsible: false while collapsed; open first panel
4593                         if ( !value && this.options.active === false ) {
4594                                 this._activate( 0 );
4595                         }
4596                 }
4597
4598                 if ( key === "event" ) {
4599                         this._setupEvents( value );
4600                 }
4601
4602                 if ( key === "heightStyle" ) {
4603                         this._setupHeightStyle( value );
4604                 }
4605         },
4606
4607         _tabId: function( tab ) {
4608                 return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();
4609         },
4610
4611         _sanitizeSelector: function( hash ) {
4612                 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
4613         },
4614
4615         refresh: function() {
4616                 var options = this.options,
4617                         lis = this.tablist.children( ":has(a[href])" );
4618
4619                 // get disabled tabs from class attribute from HTML
4620                 // this will get converted to a boolean if needed in _refresh()
4621                 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
4622                         return lis.index( tab );
4623                 });
4624
4625                 this._processTabs();
4626
4627                 // was collapsed or no tabs
4628                 if ( options.active === false || !this.anchors.length ) {
4629                         options.active = false;
4630                         this.active = $();
4631                 // was active, but active tab is gone
4632                 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
4633                         // all remaining tabs are disabled
4634                         if ( this.tabs.length === options.disabled.length ) {
4635                                 options.active = false;
4636                                 this.active = $();
4637                         // activate previous tab
4638                         } else {
4639                                 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
4640                         }
4641                 // was active, active tab still exists
4642                 } else {
4643                         // make sure active index is correct
4644                         options.active = this.tabs.index( this.active );
4645                 }
4646
4647                 this._refresh();
4648         },
4649
4650         _refresh: function() {
4651                 this._setupDisabled( this.options.disabled );
4652                 this._setupEvents( this.options.event );
4653                 this._setupHeightStyle( this.options.heightStyle );
4654
4655                 this.tabs.not( this.active ).attr({
4656                         "aria-selected": "false",
4657                         tabIndex: -1
4658                 });
4659                 this.panels.not( this._getPanelForTab( this.active ) )
4660                         .hide()
4661                         .attr({
4662                                 "aria-expanded": "false",
4663                                 "aria-hidden": "true"
4664                         });
4665
4666                 // Make sure one tab is in the tab order
4667                 if ( !this.active.length ) {
4668                         this.tabs.eq( 0 ).attr( "tabIndex", 0 );
4669                 } else {
4670                         this.active
4671                                 .addClass( "ui-tabs-active ui-state-active" )
4672                                 .attr({
4673                                         "aria-selected": "true",
4674                                         tabIndex: 0
4675                                 });
4676                         this._getPanelForTab( this.active )
4677                                 .show()
4678                                 .attr({
4679                                         "aria-expanded": "true",
4680                                         "aria-hidden": "false"
4681                                 });
4682                 }
4683         },
4684
4685         _processTabs: function() {
4686                 var that = this;
4687
4688                 this.tablist = this._getList()
4689                         .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
4690                         .attr( "role", "tablist" );
4691
4692                 this.tabs = this.tablist.find( "> li:has(a[href])" )
4693                         .addClass( "ui-state-default ui-corner-top" )
4694                         .attr({
4695                                 role: "tab",
4696                                 tabIndex: -1
4697                         });
4698
4699                 this.anchors = this.tabs.map(function() {
4700                                 return $( "a", this )[ 0 ];
4701                         })
4702                         .addClass( "ui-tabs-anchor" )
4703                         .attr({
4704                                 role: "presentation",
4705                                 tabIndex: -1
4706                         });
4707
4708                 this.panels = $();
4709
4710                 this.anchors.each(function( i, anchor ) {
4711                         var selector, panel, panelId,
4712                                 anchorId = $( anchor ).uniqueId().attr( "id" ),
4713                                 tab = $( anchor ).closest( "li" ),
4714                                 originalAriaControls = tab.attr( "aria-controls" );
4715
4716                         // inline tab
4717                         if ( isLocal( anchor ) ) {
4718                                 selector = anchor.hash;
4719                                 panel = that.element.find( that._sanitizeSelector( selector ) );
4720                         // remote tab
4721                         } else {
4722                                 panelId = that._tabId( tab );
4723                                 selector = "#" + panelId;
4724                                 panel = that.element.find( selector );
4725                                 if ( !panel.length ) {
4726                                         panel = that._createPanel( panelId );
4727                                         panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
4728                                 }
4729                                 panel.attr( "aria-live", "polite" );
4730                         }
4731
4732                         if ( panel.length) {
4733                                 that.panels = that.panels.add( panel );
4734                         }
4735                         if ( originalAriaControls ) {
4736                                 tab.data( "ui-tabs-aria-controls", originalAriaControls );
4737                         }
4738                         tab.attr({
4739                                 "aria-controls": selector.substring( 1 ),
4740                                 "aria-labelledby": anchorId
4741                         });
4742                         panel.attr( "aria-labelledby", anchorId );
4743                 });
4744
4745                 this.panels
4746                         .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
4747                         .attr( "role", "tabpanel" );
4748         },
4749
4750         // allow overriding how to find the list for rare usage scenarios (#7715)
4751         _getList: function() {
4752                 return this.element.find( "ol,ul" ).eq( 0 );
4753         },
4754
4755         _createPanel: function( id ) {
4756                 return $( "<div>" )
4757                         .attr( "id", id )
4758                         .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
4759                         .data( "ui-tabs-destroy", true );
4760         },
4761
4762         _setupDisabled: function( disabled ) {
4763                 if ( $.isArray( disabled ) ) {
4764                         if ( !disabled.length ) {
4765                                 disabled = false;
4766                         } else if ( disabled.length === this.anchors.length ) {
4767                                 disabled = true;
4768                         }
4769                 }
4770
4771                 // disable tabs
4772                 for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
4773                         if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
4774                                 $( li )
4775                                         .addClass( "ui-state-disabled" )
4776                                         .attr( "aria-disabled", "true" );
4777                         } else {
4778                                 $( li )
4779                                         .removeClass( "ui-state-disabled" )
4780                                         .removeAttr( "aria-disabled" );
4781                         }
4782                 }
4783
4784                 this.options.disabled = disabled;
4785         },
4786
4787         _setupEvents: function( event ) {
4788                 var events = {
4789                         click: function( event ) {
4790                                 event.preventDefault();
4791                         }
4792                 };
4793                 if ( event ) {
4794                         $.each( event.split(" "), function( index, eventName ) {
4795                                 events[ eventName ] = "_eventHandler";
4796                         });
4797                 }
4798
4799                 this._off( this.anchors.add( this.tabs ).add( this.panels ) );
4800                 this._on( this.anchors, events );
4801                 this._on( this.tabs, { keydown: "_tabKeydown" } );
4802                 this._on( this.panels, { keydown: "_panelKeydown" } );
4803
4804                 this._focusable( this.tabs );
4805                 this._hoverable( this.tabs );
4806         },
4807
4808         _setupHeightStyle: function( heightStyle ) {
4809                 var maxHeight, overflow,
4810                         parent = this.element.parent();
4811
4812                 if ( heightStyle === "fill" ) {
4813                         // IE 6 treats height like minHeight, so we need to turn off overflow
4814                         // in order to get a reliable height
4815                         // we use the minHeight support test because we assume that only
4816                         // browsers that don't support minHeight will treat height as minHeight
4817                         if ( !$.support.minHeight ) {
4818                                 overflow = parent.css( "overflow" );
4819                                 parent.css( "overflow", "hidden");
4820                         }
4821                         maxHeight = parent.height();
4822                         this.element.siblings( ":visible" ).each(function() {
4823                                 var elem = $( this ),
4824                                         position = elem.css( "position" );
4825
4826                                 if ( position === "absolute" || position === "fixed" ) {
4827                                         return;
4828                                 }
4829                                 maxHeight -= elem.outerHeight( true );
4830                         });
4831                         if ( overflow ) {
4832                                 parent.css( "overflow", overflow );
4833                         }
4834
4835                         this.element.children().not( this.panels ).each(function() {
4836                                 maxHeight -= $( this ).outerHeight( true );
4837                         });
4838
4839                         this.panels.each(function() {
4840                                 $( this ).height( Math.max( 0, maxHeight -
4841                                         $( this ).innerHeight() + $( this ).height() ) );
4842                         })
4843                         .css( "overflow", "auto" );
4844                 } else if ( heightStyle === "auto" ) {
4845                         maxHeight = 0;
4846                         this.panels.each(function() {
4847                                 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
4848                         }).height( maxHeight );
4849                 }
4850         },
4851
4852         _eventHandler: function( event ) {
4853                 var options = this.options,
4854                         active = this.active,
4855                         anchor = $( event.currentTarget ),
4856                         tab = anchor.closest( "li" ),
4857                         clickedIsActive = tab[ 0 ] === active[ 0 ],
4858                         collapsing = clickedIsActive && options.collapsible,
4859                         toShow = collapsing ? $() : this._getPanelForTab( tab ),
4860                         toHide = !active.length ? $() : this._getPanelForTab( active ),
4861                         eventData = {
4862                                 oldTab: active,
4863                                 oldPanel: toHide,
4864                                 newTab: collapsing ? $() : tab,
4865                                 newPanel: toShow
4866                         };
4867
4868                 event.preventDefault();
4869
4870                 if ( tab.hasClass( "ui-state-disabled" ) ||
4871                                 // tab is already loading
4872                                 tab.hasClass( "ui-tabs-loading" ) ||
4873                                 // can't switch durning an animation
4874                                 this.running ||
4875                                 // click on active header, but not collapsible
4876                                 ( clickedIsActive && !options.collapsible ) ||
4877                                 // allow canceling activation
4878                                 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
4879                         return;
4880                 }
4881
4882                 options.active = collapsing ? false : this.tabs.index( tab );
4883
4884                 this.active = clickedIsActive ? $() : tab;
4885                 if ( this.xhr ) {
4886                         this.xhr.abort();
4887                 }
4888
4889                 if ( !toHide.length && !toShow.length ) {
4890                         $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
4891                 }
4892
4893                 if ( toShow.length ) {
4894                         this.load( this.tabs.index( tab ), event );
4895                 }
4896                 this._toggle( event, eventData );
4897         },
4898
4899         // handles show/hide for selecting tabs
4900         _toggle: function( event, eventData ) {
4901                 var that = this,
4902                         toShow = eventData.newPanel,
4903                         toHide = eventData.oldPanel;
4904
4905                 this.running = true;
4906
4907                 function complete() {
4908                         that.running = false;
4909                         that._trigger( "activate", event, eventData );
4910                 }
4911
4912                 function show() {
4913                         eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
4914
4915                         if ( toShow.length && that.options.show ) {
4916                                 that._show( toShow, that.options.show, complete );
4917                         } else {
4918                                 toShow.show();
4919                                 complete();
4920                         }
4921                 }
4922
4923                 // start out by hiding, then showing, then completing
4924                 if ( toHide.length && this.options.hide ) {
4925                         this._hide( toHide, this.options.hide, function() {
4926                                 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
4927                                 show();
4928                         });
4929                 } else {
4930                         eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
4931                         toHide.hide();
4932                         show();
4933                 }
4934
4935                 toHide.attr({
4936                         "aria-expanded": "false",
4937                         "aria-hidden": "true"
4938                 });
4939                 eventData.oldTab.attr( "aria-selected", "false" );
4940                 // If we're switching tabs, remove the old tab from the tab order.
4941                 // If we're opening from collapsed state, remove the previous tab from the tab order.
4942                 // If we're collapsing, then keep the collapsing tab in the tab order.
4943                 if ( toShow.length && toHide.length ) {
4944                         eventData.oldTab.attr( "tabIndex", -1 );
4945                 } else if ( toShow.length ) {
4946                         this.tabs.filter(function() {
4947                                 return $( this ).attr( "tabIndex" ) === 0;
4948                         })
4949                         .attr( "tabIndex", -1 );
4950                 }
4951
4952                 toShow.attr({
4953                         "aria-expanded": "true",
4954                         "aria-hidden": "false"
4955                 });
4956                 eventData.newTab.attr({
4957                         "aria-selected": "true",
4958                         tabIndex: 0
4959                 });
4960         },
4961
4962         _activate: function( index ) {
4963                 var anchor,
4964                         active = this._findActive( index );
4965
4966                 // trying to activate the already active panel
4967                 if ( active[ 0 ] === this.active[ 0 ] ) {
4968                         return;
4969                 }
4970
4971                 // trying to collapse, simulate a click on the current active header
4972                 if ( !active.length ) {
4973                         active = this.active;
4974                 }
4975
4976                 anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
4977                 this._eventHandler({
4978                         target: anchor,
4979                         currentTarget: anchor,
4980                         preventDefault: $.noop
4981                 });
4982         },
4983
4984         _findActive: function( index ) {
4985                 return index === false ? $() : this.tabs.eq( index );
4986         },
4987
4988         _getIndex: function( index ) {
4989                 // meta-function to give users option to provide a href string instead of a numerical index.
4990                 if ( typeof index === "string" ) {
4991                         index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
4992                 }
4993
4994                 return index;
4995         },
4996
4997         _destroy: function() {
4998                 if ( this.xhr ) {
4999                         this.xhr.abort();
5000                 }
5001
5002                 this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
5003
5004                 this.tablist
5005                         .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
5006                         .removeAttr( "role" );
5007
5008                 this.anchors
5009                         .removeClass( "ui-tabs-anchor" )
5010                         .removeAttr( "role" )
5011                         .removeAttr( "tabIndex" )
5012                         .removeData( "href.tabs" )
5013                         .removeData( "load.tabs" )
5014                         .removeUniqueId();
5015
5016                 this.tabs.add( this.panels ).each(function() {
5017                         if ( $.data( this, "ui-tabs-destroy" ) ) {
5018                                 $( this ).remove();
5019                         } else {
5020                                 $( this )
5021                                         .removeClass( "ui-state-default ui-state-active ui-state-disabled " +
5022                                                 "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
5023                                         .removeAttr( "tabIndex" )
5024                                         .removeAttr( "aria-live" )
5025                                         .removeAttr( "aria-busy" )
5026                                         .removeAttr( "aria-selected" )
5027                                         .removeAttr( "aria-labelledby" )
5028                                         .removeAttr( "aria-hidden" )
5029                                         .removeAttr( "aria-expanded" )
5030                                         .removeAttr( "role" );
5031                         }
5032                 });
5033
5034                 this.tabs.each(function() {
5035                         var li = $( this ),
5036                                 prev = li.data( "ui-tabs-aria-controls" );
5037                         if ( prev ) {
5038                                 li.attr( "aria-controls", prev );
5039                         } else {
5040                                 li.removeAttr( "aria-controls" );
5041                         }
5042                 });
5043
5044                 this.panels.show();
5045
5046                 if ( this.options.heightStyle !== "content" ) {
5047                         this.panels.css( "height", "" );
5048                 }
5049         },
5050
5051         enable: function( index ) {
5052                 var disabled = this.options.disabled;
5053                 if ( disabled === false ) {
5054                         return;
5055                 }
5056
5057                 if ( index === undefined ) {
5058                         disabled = false;
5059                 } else {
5060                         index = this._getIndex( index );
5061                         if ( $.isArray( disabled ) ) {
5062                                 disabled = $.map( disabled, function( num ) {
5063                                         return num !== index ? num : null;
5064                                 });
5065                         } else {
5066                                 disabled = $.map( this.tabs, function( li, num ) {
5067                                         return num !== index ? num : null;
5068                                 });
5069                         }
5070                 }
5071                 this._setupDisabled( disabled );
5072         },
5073
5074         disable: function( index ) {
5075                 var disabled = this.options.disabled;
5076                 if ( disabled === true ) {
5077                         return;
5078                 }
5079
5080                 if ( index === undefined ) {
5081                         disabled = true;
5082                 } else {
5083                         index = this._getIndex( index );
5084                         if ( $.inArray( index, disabled ) !== -1 ) {
5085                                 return;
5086                         }
5087                         if ( $.isArray( disabled ) ) {
5088                                 disabled = $.merge( [ index ], disabled ).sort();
5089                         } else {
5090                                 disabled = [ index ];
5091                         }
5092                 }
5093                 this._setupDisabled( disabled );
5094         },
5095
5096         load: function( index, event ) {
5097                 index = this._getIndex( index );
5098                 var that = this,
5099                         tab = this.tabs.eq( index ),
5100                         anchor = tab.find( ".ui-tabs-anchor" ),
5101                         panel = this._getPanelForTab( tab ),
5102                         eventData = {
5103                                 tab: tab,
5104                                 panel: panel
5105                         };
5106
5107                 // not remote
5108                 if ( isLocal( anchor[ 0 ] ) ) {
5109                         return;
5110                 }
5111
5112                 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
5113
5114                 // support: jQuery <1.8
5115                 // jQuery <1.8 returns false if the request is canceled in beforeSend,
5116                 // but as of 1.8, $.ajax() always returns a jqXHR object.
5117                 if ( this.xhr && this.xhr.statusText !== "canceled" ) {
5118                         tab.addClass( "ui-tabs-loading" );
5119                         panel.attr( "aria-busy", "true" );
5120
5121                         this.xhr
5122                                 .success(function( response ) {
5123                                         // support: jQuery <1.8
5124                                         // http://bugs.jquery.com/ticket/11778
5125                                         setTimeout(function() {
5126                                                 panel.html( response );
5127                                                 that._trigger( "load", event, eventData );
5128                                         }, 1 );
5129                                 })
5130                                 .complete(function( jqXHR, status ) {
5131                                         // support: jQuery <1.8
5132                                         // http://bugs.jquery.com/ticket/11778
5133                                         setTimeout(function() {
5134                                                 if ( status === "abort" ) {
5135                                                         that.panels.stop( false, true );
5136                                                 }
5137
5138                                                 tab.removeClass( "ui-tabs-loading" );
5139                                                 panel.removeAttr( "aria-busy" );
5140
5141                                                 if ( jqXHR === that.xhr ) {
5142                                                         delete that.xhr;
5143                                                 }
5144                                         }, 1 );
5145                                 });
5146                 }
5147         },
5148
5149         // TODO: Remove this function in 1.10 when ajaxOptions is removed
5150         _ajaxSettings: function( anchor, event, eventData ) {
5151                 var that = this;
5152                 return {
5153                         url: anchor.attr( "href" ),
5154                         beforeSend: function( jqXHR, settings ) {
5155                                 return that._trigger( "beforeLoad", event,
5156                                         $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );
5157                         }
5158                 };
5159         },
5160
5161         _getPanelForTab: function( tab ) {
5162                 var id = $( tab ).attr( "aria-controls" );
5163                 return this.element.find( this._sanitizeSelector( "#" + id ) );
5164         }
5165 });
5166
5167 // DEPRECATED
5168 if ( $.uiBackCompat !== false ) {
5169
5170         // helper method for a lot of the back compat extensions
5171         $.ui.tabs.prototype._ui = function( tab, panel ) {
5172                 return {
5173                         tab: tab,
5174                         panel: panel,
5175                         index: this.anchors.index( tab )
5176                 };
5177         };
5178
5179         // url method
5180         $.widget( "ui.tabs", $.ui.tabs, {
5181                 url: function( index, url ) {
5182                         this.anchors.eq( index ).attr( "href", url );
5183                 }
5184         });
5185
5186         // TODO: Remove _ajaxSettings() method when removing this extension
5187         // ajaxOptions and cache options
5188         $.widget( "ui.tabs", $.ui.tabs, {
5189                 options: {
5190                         ajaxOptions: null,
5191                         cache: false
5192                 },
5193
5194                 _create: function() {
5195                         this._super();
5196
5197                         var that = this;
5198
5199                         this._on({ tabsbeforeload: function( event, ui ) {
5200                                 // tab is already cached
5201                                 if ( $.data( ui.tab[ 0 ], "cache.tabs" ) ) {
5202                                         event.preventDefault();
5203                                         return;
5204                                 }
5205
5206                                 ui.jqXHR.success(function() {
5207                                         if ( that.options.cache ) {
5208                                                 $.data( ui.tab[ 0 ], "cache.tabs", true );
5209                                         }
5210                                 });
5211                         }});
5212                 },
5213
5214                 _ajaxSettings: function( anchor, event, ui ) {
5215                         var ajaxOptions = this.options.ajaxOptions;
5216                         return $.extend( {}, ajaxOptions, {
5217                                 error: function( xhr, status ) {
5218                                         try {
5219                                                 // Passing index avoid a race condition when this method is
5220                                                 // called after the user has selected another tab.
5221                                                 // Pass the anchor that initiated this request allows
5222                                                 // loadError to manipulate the tab content panel via $(a.hash)
5223                                                 ajaxOptions.error(
5224                                                         xhr, status, ui.tab.closest( "li" ).index(), ui.tab[ 0 ] );
5225                                         }
5226                                         catch ( error ) {}
5227                                 }
5228                         }, this._superApply( arguments ) );
5229                 },
5230
5231                 _setOption: function( key, value ) {
5232                         // reset cache if switching from cached to not cached
5233                         if ( key === "cache" && value === false ) {
5234                                 this.anchors.removeData( "cache.tabs" );
5235                         }
5236                         this._super( key, value );
5237                 },
5238
5239                 _destroy: function() {
5240                         this.anchors.removeData( "cache.tabs" );
5241                         this._super();
5242                 },
5243
5244                 url: function( index ){
5245                         this.anchors.eq( index ).removeData( "cache.tabs" );
5246                         this._superApply( arguments );
5247                 }
5248         });
5249
5250         // abort method
5251         $.widget( "ui.tabs", $.ui.tabs, {
5252                 abort: function() {
5253                         if ( this.xhr ) {
5254                                 this.xhr.abort();
5255                         }
5256                 }
5257         });
5258
5259         // spinner
5260         $.widget( "ui.tabs", $.ui.tabs, {
5261                 options: {
5262                         spinner: "<em>Loading&#8230;</em>"
5263                 },
5264                 _create: function() {
5265                         this._super();
5266                         this._on({
5267                                 tabsbeforeload: function( event, ui ) {
5268                                         // Don't react to nested tabs or tabs that don't use a spinner
5269                                         if ( event.target !== this.element[ 0 ] ||
5270                                                         !this.options.spinner ) {
5271                                                 return;
5272                                         }
5273
5274                                         var span = ui.tab.find( "span" ),
5275                                                 html = span.html();
5276                                         span.html( this.options.spinner );
5277                                         ui.jqXHR.complete(function() {
5278                                                 span.html( html );
5279                                         });
5280                                 }
5281                         });
5282                 }
5283         });
5284
5285         // enable/disable events
5286         $.widget( "ui.tabs", $.ui.tabs, {
5287                 options: {
5288                         enable: null,
5289                         disable: null
5290                 },
5291
5292                 enable: function( index ) {
5293                         var options = this.options,
5294                                 trigger;
5295
5296                         if ( index && options.disabled === true ||
5297                                         ( $.isArray( options.disabled ) && $.inArray( index, options.disabled ) !== -1 ) ) {
5298                                 trigger = true;
5299                         }
5300
5301                         this._superApply( arguments );
5302
5303                         if ( trigger ) {
5304                                 this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
5305                         }
5306                 },
5307
5308                 disable: function( index ) {
5309                         var options = this.options,
5310                                 trigger;
5311
5312                         if ( index && options.disabled === false ||
5313                                         ( $.isArray( options.disabled ) && $.inArray( index, options.disabled ) === -1 ) ) {
5314                                 trigger = true;
5315                         }
5316
5317                         this._superApply( arguments );
5318
5319                         if ( trigger ) {
5320                                 this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
5321                         }
5322                 }
5323         });
5324
5325         // add/remove methods and events
5326         $.widget( "ui.tabs", $.ui.tabs, {
5327                 options: {
5328                         add: null,
5329                         remove: null,
5330                         tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
5331                 },
5332
5333                 add: function( url, label, index ) {
5334                         if ( index === undefined ) {
5335                                 index = this.anchors.length;
5336                         }
5337
5338                         var doInsertAfter, panel,
5339                                 options = this.options,
5340                                 li = $( options.tabTemplate
5341                                         .replace( /#\{href\}/g, url )
5342                                         .replace( /#\{label\}/g, label ) ),
5343                                 id = !url.indexOf( "#" ) ?
5344                                         url.replace( "#", "" ) :
5345                                         this._tabId( li );
5346
5347                         li.addClass( "ui-state-default ui-corner-top" ).data( "ui-tabs-destroy", true );
5348                         li.attr( "aria-controls", id );
5349
5350                         doInsertAfter = index >= this.tabs.length;
5351
5352                         // try to find an existing element before creating a new one
5353                         panel = this.element.find( "#" + id );
5354                         if ( !panel.length ) {
5355                                 panel = this._createPanel( id );
5356                                 if ( doInsertAfter ) {
5357                                         if ( index > 0 ) {
5358                                                 panel.insertAfter( this.panels.eq( -1 ) );
5359                                         } else {
5360                                                 panel.appendTo( this.element );
5361                                         }
5362                                 } else {
5363                                         panel.insertBefore( this.panels[ index ] );
5364                                 }
5365                         }
5366                         panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ).hide();
5367
5368                         if ( doInsertAfter ) {
5369                                 li.appendTo( this.tablist );
5370                         } else {
5371                                 li.insertBefore( this.tabs[ index ] );
5372                         }
5373
5374                         options.disabled = $.map( options.disabled, function( n ) {
5375                                 return n >= index ? ++n : n;
5376                         });
5377
5378                         this.refresh();
5379                         if ( this.tabs.length === 1 && options.active === false ) {
5380                                 this.option( "active", 0 );
5381                         }
5382
5383                         this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
5384                         return this;
5385                 },
5386
5387                 remove: function( index ) {
5388                         index = this._getIndex( index );
5389                         var options = this.options,
5390                                 tab = this.tabs.eq( index ).remove(),
5391                                 panel = this._getPanelForTab( tab ).remove();
5392
5393                         // If selected tab was removed focus tab to the right or
5394                         // in case the last tab was removed the tab to the left.
5395                         // We check for more than 2 tabs, because if there are only 2,
5396                         // then when we remove this tab, there will only be one tab left
5397                         // so we don't need to detect which tab to activate.
5398                         if ( tab.hasClass( "ui-tabs-active" ) && this.anchors.length > 2 ) {
5399                                 this._activate( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
5400                         }
5401
5402                         options.disabled = $.map(
5403                                 $.grep( options.disabled, function( n ) {
5404                                         return n !== index;
5405                                 }),
5406                                 function( n ) {
5407                                         return n >= index ? --n : n;
5408                                 });
5409
5410                         this.refresh();
5411
5412                         this._trigger( "remove", null, this._ui( tab.find( "a" )[ 0 ], panel[ 0 ] ) );
5413                         return this;
5414                 }
5415         });
5416
5417         // length method
5418         $.widget( "ui.tabs", $.ui.tabs, {
5419                 length: function() {
5420                         return this.anchors.length;
5421                 }
5422         });
5423
5424         // panel ids (idPrefix option + title attribute)
5425         $.widget( "ui.tabs", $.ui.tabs, {
5426                 options: {
5427                         idPrefix: "ui-tabs-"
5428                 },
5429
5430                 _tabId: function( tab ) {
5431                         var a = tab.is( "li" ) ? tab.find( "a[href]" ) : tab;
5432                         a = a[0];
5433                         return $( a ).closest( "li" ).attr( "aria-controls" ) ||
5434                                 a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF\-]/g, "" ) ||
5435                                 this.options.idPrefix + getNextTabId();
5436                 }
5437         });
5438
5439         // _createPanel method
5440         $.widget( "ui.tabs", $.ui.tabs, {
5441                 options: {
5442                         panelTemplate: "<div></div>"
5443                 },
5444
5445                 _createPanel: function( id ) {
5446                         return $( this.options.panelTemplate )
5447                                 .attr( "id", id )
5448                                 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
5449                                 .data( "ui-tabs-destroy", true );
5450                 }
5451         });
5452
5453         // selected option
5454         $.widget( "ui.tabs", $.ui.tabs, {
5455                 _create: function() {
5456                         var options = this.options;
5457                         if ( options.active === null && options.selected !== undefined ) {
5458                                 options.active = options.selected === -1 ? false : options.selected;
5459                         }
5460                         this._super();
5461                         options.selected = options.active;
5462                         if ( options.selected === false ) {
5463                                 options.selected = -1;
5464                         }
5465                 },
5466
5467                 _setOption: function( key, value ) {
5468                         if ( key !== "selected" ) {
5469                                 return this._super( key, value );
5470                         }
5471
5472                         var options = this.options;
5473                         this._super( "active", value === -1 ? false : value );
5474                         options.selected = options.active;
5475                         if ( options.selected === false ) {
5476                                 options.selected = -1;
5477                         }
5478                 },
5479
5480                 _eventHandler: function() {
5481                         this._superApply( arguments );
5482                         this.options.selected = this.options.active;
5483                         if ( this.options.selected === false ) {
5484                                 this.options.selected = -1;
5485                         }
5486                 }
5487         });
5488
5489         // show and select event
5490         $.widget( "ui.tabs", $.ui.tabs, {
5491                 options: {
5492                         show: null,
5493                         select: null
5494                 },
5495                 _create: function() {
5496                         this._super();
5497                         if ( this.options.active !== false ) {
5498                                 this._trigger( "show", null, this._ui(
5499                                         this.active.find( ".ui-tabs-anchor" )[ 0 ],
5500                                         this._getPanelForTab( this.active )[ 0 ] ) );
5501                         }
5502                 },
5503                 _trigger: function( type, event, data ) {
5504                         var tab, panel,
5505                                 ret = this._superApply( arguments );
5506
5507                         if ( !ret ) {
5508                                 return false;
5509                         }
5510
5511                         if ( type === "beforeActivate" ) {
5512                                 tab = data.newTab.length ? data.newTab : data.oldTab;
5513                                 panel = data.newPanel.length ? data.newPanel : data.oldPanel;
5514                                 ret = this._super( "select", event, {
5515                                         tab: tab.find( ".ui-tabs-anchor" )[ 0],
5516                                         panel: panel[ 0 ],
5517                                         index: tab.closest( "li" ).index()
5518                                 });
5519                         } else if ( type === "activate" && data.newTab.length ) {
5520                                 ret = this._super( "show", event, {
5521                                         tab: data.newTab.find( ".ui-tabs-anchor" )[ 0 ],
5522                                         panel: data.newPanel[ 0 ],
5523                                         index: data.newTab.closest( "li" ).index()
5524                                 });
5525                         }
5526                         return ret;
5527                 }
5528         });
5529
5530         // select method
5531         $.widget( "ui.tabs", $.ui.tabs, {
5532                 select: function( index ) {
5533                         index = this._getIndex( index );
5534                         if ( index === -1 ) {
5535                                 if ( this.options.collapsible && this.options.selected !== -1 ) {
5536                                         index = this.options.selected;
5537                                 } else {
5538                                         return;
5539                                 }
5540                         }
5541                         this.anchors.eq( index ).trigger( this.options.event + this.eventNamespace );
5542                 }
5543         });
5544
5545         // cookie option
5546         (function() {
5547
5548         var listId = 0;
5549
5550         $.widget( "ui.tabs", $.ui.tabs, {
5551                 options: {
5552                         cookie: null // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
5553                 },
5554                 _create: function() {
5555                         var options = this.options,
5556                                 active;
5557                         if ( options.active == null && options.cookie ) {
5558                                 active = parseInt( this._cookie(), 10 );
5559                                 if ( active === -1 ) {
5560                                         active = false;
5561                                 }
5562                                 options.active = active;
5563                         }
5564                         this._super();
5565                 },
5566                 _cookie: function( active ) {
5567                         var cookie = [ this.cookie ||
5568                                 ( this.cookie = this.options.cookie.name || "ui-tabs-" + (++listId) ) ];
5569                         if ( arguments.length ) {
5570                                 cookie.push( active === false ? -1 : active );
5571                                 cookie.push( this.options.cookie );
5572                         }
5573                         return $.cookie.apply( null, cookie );
5574                 },
5575                 _refresh: function() {
5576                         this._super();
5577                         if ( this.options.cookie ) {
5578                                 this._cookie( this.options.active, this.options.cookie );
5579                         }
5580                 },
5581                 _eventHandler: function() {
5582                         this._superApply( arguments );
5583                         if ( this.options.cookie ) {
5584                                 this._cookie( this.options.active, this.options.cookie );
5585                         }
5586                 },
5587                 _destroy: function() {
5588                         this._super();
5589                         if ( this.options.cookie ) {
5590                                 this._cookie( null, this.options.cookie );
5591                         }
5592                 }
5593         });
5594
5595         })();
5596
5597         // load event
5598         $.widget( "ui.tabs", $.ui.tabs, {
5599                 _trigger: function( type, event, data ) {
5600                         var _data = $.extend( {}, data );
5601                         if ( type === "load" ) {
5602                                 _data.panel = _data.panel[ 0 ];
5603                                 _data.tab = _data.tab.find( ".ui-tabs-anchor" )[ 0 ];
5604                         }
5605                         return this._super( type, event, _data );
5606                 }
5607         });
5608
5609         // fx option
5610         // The new animation options (show, hide) conflict with the old show callback.
5611         // The old fx option wins over show/hide anyway (always favor back-compat).
5612         // If a user wants to use the new animation API, they must give up the old API.
5613         $.widget( "ui.tabs", $.ui.tabs, {
5614                 options: {
5615                         fx: null // e.g. { height: "toggle", opacity: "toggle", duration: 200 }
5616                 },
5617
5618                 _getFx: function() {
5619                         var hide, show,
5620                                 fx = this.options.fx;
5621
5622                         if ( fx ) {
5623                                 if ( $.isArray( fx ) ) {
5624                                         hide = fx[ 0 ];
5625                                         show = fx[ 1 ];
5626                                 } else {
5627                                         hide = show = fx;
5628                                 }
5629                         }
5630
5631                         return fx ? { show: show, hide: hide } : null;
5632                 },
5633
5634                 _toggle: function( event, eventData ) {
5635                         var that = this,
5636                                 toShow = eventData.newPanel,
5637                                 toHide = eventData.oldPanel,
5638                                 fx = this._getFx();
5639
5640                         if ( !fx ) {
5641                                 return this._super( event, eventData );
5642                         }
5643
5644                         that.running = true;
5645
5646                         function complete() {
5647                                 that.running = false;
5648                                 that._trigger( "activate", event, eventData );
5649                         }
5650
5651                         function show() {
5652                                 eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
5653
5654                                 if ( toShow.length && fx.show ) {
5655                                         toShow
5656                                                 .animate( fx.show, fx.show.duration, function() {
5657                                                         complete();
5658                                                 });
5659                                 } else {
5660                                         toShow.show();
5661                                         complete();
5662                                 }
5663                         }
5664
5665                         // start out by hiding, then showing, then completing
5666                         if ( toHide.length && fx.hide ) {
5667                                 toHide.animate( fx.hide, fx.hide.duration, function() {
5668                                         eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
5669                                         show();
5670                                 });
5671                         } else {
5672                                 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
5673                                 toHide.hide();
5674                                 show();
5675                         }
5676                 }
5677         });
5678 }
5679
5680 })( jQuery );