luci2: use custom jQuery UI build with all uneeded functionality trimmed, saves 320K...
[project/luci2/ui.git] / luci2 / htdocs / luci2 / jquery-ui-1.10.3.custom.js
1 /*! jQuery UI - v1.10.3 - 2013-10-15
2 * http://jqueryui.com
3 * Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.sortable.js, jquery.ui.accordion.js, jquery.ui.tabs.js
4 * Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */
5
6 (function( $, undefined ) {
7
8 var uuid = 0,
9         runiqueId = /^ui-id-\d+$/;
10
11 // $.ui might exist from components with no dependencies, e.g., $.ui.position
12 $.ui = $.ui || {};
13
14 $.extend( $.ui, {
15         version: "1.10.3",
16
17         keyCode: {
18                 BACKSPACE: 8,
19                 COMMA: 188,
20                 DELETE: 46,
21                 DOWN: 40,
22                 END: 35,
23                 ENTER: 13,
24                 ESCAPE: 27,
25                 HOME: 36,
26                 LEFT: 37,
27                 NUMPAD_ADD: 107,
28                 NUMPAD_DECIMAL: 110,
29                 NUMPAD_DIVIDE: 111,
30                 NUMPAD_ENTER: 108,
31                 NUMPAD_MULTIPLY: 106,
32                 NUMPAD_SUBTRACT: 109,
33                 PAGE_DOWN: 34,
34                 PAGE_UP: 33,
35                 PERIOD: 190,
36                 RIGHT: 39,
37                 SPACE: 32,
38                 TAB: 9,
39                 UP: 38
40         }
41 });
42
43 // plugins
44 $.fn.extend({
45         focus: (function( orig ) {
46                 return function( delay, fn ) {
47                         return typeof delay === "number" ?
48                                 this.each(function() {
49                                         var elem = this;
50                                         setTimeout(function() {
51                                                 $( elem ).focus();
52                                                 if ( fn ) {
53                                                         fn.call( elem );
54                                                 }
55                                         }, delay );
56                                 }) :
57                                 orig.apply( this, arguments );
58                 };
59         })( $.fn.focus ),
60
61         scrollParent: function() {
62                 var scrollParent;
63                 if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) {
64                         scrollParent = this.parents().filter(function() {
65                                 return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
66                         }).eq(0);
67                 } else {
68                         scrollParent = this.parents().filter(function() {
69                                 return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
70                         }).eq(0);
71                 }
72
73                 return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent;
74         },
75
76         zIndex: function( zIndex ) {
77                 if ( zIndex !== undefined ) {
78                         return this.css( "zIndex", zIndex );
79                 }
80
81                 if ( this.length ) {
82                         var elem = $( this[ 0 ] ), position, value;
83                         while ( elem.length && elem[ 0 ] !== document ) {
84                                 // Ignore z-index if position is set to a value where z-index is ignored by the browser
85                                 // This makes behavior of this function consistent across browsers
86                                 // WebKit always returns auto if the element is positioned
87                                 position = elem.css( "position" );
88                                 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
89                                         // IE returns 0 when zIndex is not specified
90                                         // other browsers return a string
91                                         // we ignore the case of nested elements with an explicit value of 0
92                                         // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
93                                         value = parseInt( elem.css( "zIndex" ), 10 );
94                                         if ( !isNaN( value ) && value !== 0 ) {
95                                                 return value;
96                                         }
97                                 }
98                                 elem = elem.parent();
99                         }
100                 }
101
102                 return 0;
103         },
104
105         uniqueId: function() {
106                 return this.each(function() {
107                         if ( !this.id ) {
108                                 this.id = "ui-id-" + (++uuid);
109                         }
110                 });
111         },
112
113         removeUniqueId: function() {
114                 return this.each(function() {
115                         if ( runiqueId.test( this.id ) ) {
116                                 $( this ).removeAttr( "id" );
117                         }
118                 });
119         }
120 });
121
122 // selectors
123 function focusable( element, isTabIndexNotNaN ) {
124         var map, mapName, img,
125                 nodeName = element.nodeName.toLowerCase();
126         if ( "area" === nodeName ) {
127                 map = element.parentNode;
128                 mapName = map.name;
129                 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
130                         return false;
131                 }
132                 img = $( "img[usemap=#" + mapName + "]" )[0];
133                 return !!img && visible( img );
134         }
135         return ( /input|select|textarea|button|object/.test( nodeName ) ?
136                 !element.disabled :
137                 "a" === nodeName ?
138                         element.href || isTabIndexNotNaN :
139                         isTabIndexNotNaN) &&
140                 // the element and all of its ancestors must be visible
141                 visible( element );
142 }
143
144 function visible( element ) {
145         return $.expr.filters.visible( element ) &&
146                 !$( element ).parents().addBack().filter(function() {
147                         return $.css( this, "visibility" ) === "hidden";
148                 }).length;
149 }
150
151 $.extend( $.expr[ ":" ], {
152         data: $.expr.createPseudo ?
153                 $.expr.createPseudo(function( dataName ) {
154                         return function( elem ) {
155                                 return !!$.data( elem, dataName );
156                         };
157                 }) :
158                 // support: jQuery <1.8
159                 function( elem, i, match ) {
160                         return !!$.data( elem, match[ 3 ] );
161                 },
162
163         focusable: function( element ) {
164                 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
165         },
166
167         tabbable: function( element ) {
168                 var tabIndex = $.attr( element, "tabindex" ),
169                         isTabIndexNaN = isNaN( tabIndex );
170                 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
171         }
172 });
173
174 // support: jQuery <1.8
175 if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
176         $.each( [ "Width", "Height" ], function( i, name ) {
177                 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
178                         type = name.toLowerCase(),
179                         orig = {
180                                 innerWidth: $.fn.innerWidth,
181                                 innerHeight: $.fn.innerHeight,
182                                 outerWidth: $.fn.outerWidth,
183                                 outerHeight: $.fn.outerHeight
184                         };
185
186                 function reduce( elem, size, border, margin ) {
187                         $.each( side, function() {
188                                 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
189                                 if ( border ) {
190                                         size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
191                                 }
192                                 if ( margin ) {
193                                         size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
194                                 }
195                         });
196                         return size;
197                 }
198
199                 $.fn[ "inner" + name ] = function( size ) {
200                         if ( size === undefined ) {
201                                 return orig[ "inner" + name ].call( this );
202                         }
203
204                         return this.each(function() {
205                                 $( this ).css( type, reduce( this, size ) + "px" );
206                         });
207                 };
208
209                 $.fn[ "outer" + name] = function( size, margin ) {
210                         if ( typeof size !== "number" ) {
211                                 return orig[ "outer" + name ].call( this, size );
212                         }
213
214                         return this.each(function() {
215                                 $( this).css( type, reduce( this, size, true, margin ) + "px" );
216                         });
217                 };
218         });
219 }
220
221 // support: jQuery <1.8
222 if ( !$.fn.addBack ) {
223         $.fn.addBack = function( selector ) {
224                 return this.add( selector == null ?
225                         this.prevObject : this.prevObject.filter( selector )
226                 );
227         };
228 }
229
230 // support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
231 if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
232         $.fn.removeData = (function( removeData ) {
233                 return function( key ) {
234                         if ( arguments.length ) {
235                                 return removeData.call( this, $.camelCase( key ) );
236                         } else {
237                                 return removeData.call( this );
238                         }
239                 };
240         })( $.fn.removeData );
241 }
242
243
244
245
246
247 // deprecated
248 $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
249
250 $.support.selectstart = "onselectstart" in document.createElement( "div" );
251 $.fn.extend({
252         disableSelection: function() {
253                 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
254                         ".ui-disableSelection", function( event ) {
255                                 event.preventDefault();
256                         });
257         },
258
259         enableSelection: function() {
260                 return this.unbind( ".ui-disableSelection" );
261         }
262 });
263
264 $.extend( $.ui, {
265         // $.ui.plugin is deprecated. Use $.widget() extensions instead.
266         plugin: {
267                 add: function( module, option, set ) {
268                         var i,
269                                 proto = $.ui[ module ].prototype;
270                         for ( i in set ) {
271                                 proto.plugins[ i ] = proto.plugins[ i ] || [];
272                                 proto.plugins[ i ].push( [ option, set[ i ] ] );
273                         }
274                 },
275                 call: function( instance, name, args ) {
276                         var i,
277                                 set = instance.plugins[ name ];
278                         if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
279                                 return;
280                         }
281
282                         for ( i = 0; i < set.length; i++ ) {
283                                 if ( instance.options[ set[ i ][ 0 ] ] ) {
284                                         set[ i ][ 1 ].apply( instance.element, args );
285                                 }
286                         }
287                 }
288         },
289
290         // only used by resizable
291         hasScroll: function( el, a ) {
292
293                 //If overflow is hidden, the element might have extra content, but the user wants to hide it
294                 if ( $( el ).css( "overflow" ) === "hidden") {
295                         return false;
296                 }
297
298                 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
299                         has = false;
300
301                 if ( el[ scroll ] > 0 ) {
302                         return true;
303                 }
304
305                 // TODO: determine which cases actually cause this to happen
306                 // if the element doesn't have the scroll set, see if it's possible to
307                 // set the scroll
308                 el[ scroll ] = 1;
309                 has = ( el[ scroll ] > 0 );
310                 el[ scroll ] = 0;
311                 return has;
312         }
313 });
314
315 })( jQuery );
316 (function( $, undefined ) {
317
318 var uuid = 0,
319         slice = Array.prototype.slice,
320         _cleanData = $.cleanData;
321 $.cleanData = function( elems ) {
322         for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
323                 try {
324                         $( elem ).triggerHandler( "remove" );
325                 // http://bugs.jquery.com/ticket/8235
326                 } catch( e ) {}
327         }
328         _cleanData( elems );
329 };
330
331 $.widget = function( name, base, prototype ) {
332         var fullName, existingConstructor, constructor, basePrototype,
333                 // proxiedPrototype allows the provided prototype to remain unmodified
334                 // so that it can be used as a mixin for multiple widgets (#8876)
335                 proxiedPrototype = {},
336                 namespace = name.split( "." )[ 0 ];
337
338         name = name.split( "." )[ 1 ];
339         fullName = namespace + "-" + name;
340
341         if ( !prototype ) {
342                 prototype = base;
343                 base = $.Widget;
344         }
345
346         // create selector for plugin
347         $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
348                 return !!$.data( elem, fullName );
349         };
350
351         $[ namespace ] = $[ namespace ] || {};
352         existingConstructor = $[ namespace ][ name ];
353         constructor = $[ namespace ][ name ] = function( options, element ) {
354                 // allow instantiation without "new" keyword
355                 if ( !this._createWidget ) {
356                         return new constructor( options, element );
357                 }
358
359                 // allow instantiation without initializing for simple inheritance
360                 // must use "new" keyword (the code above always passes args)
361                 if ( arguments.length ) {
362                         this._createWidget( options, element );
363                 }
364         };
365         // extend with the existing constructor to carry over any static properties
366         $.extend( constructor, existingConstructor, {
367                 version: prototype.version,
368                 // copy the object used to create the prototype in case we need to
369                 // redefine the widget later
370                 _proto: $.extend( {}, prototype ),
371                 // track widgets that inherit from this widget in case this widget is
372                 // redefined after a widget inherits from it
373                 _childConstructors: []
374         });
375
376         basePrototype = new base();
377         // we need to make the options hash a property directly on the new instance
378         // otherwise we'll modify the options hash on the prototype that we're
379         // inheriting from
380         basePrototype.options = $.widget.extend( {}, basePrototype.options );
381         $.each( prototype, function( prop, value ) {
382                 if ( !$.isFunction( value ) ) {
383                         proxiedPrototype[ prop ] = value;
384                         return;
385                 }
386                 proxiedPrototype[ prop ] = (function() {
387                         var _super = function() {
388                                         return base.prototype[ prop ].apply( this, arguments );
389                                 },
390                                 _superApply = function( args ) {
391                                         return base.prototype[ prop ].apply( this, args );
392                                 };
393                         return function() {
394                                 var __super = this._super,
395                                         __superApply = this._superApply,
396                                         returnValue;
397
398                                 this._super = _super;
399                                 this._superApply = _superApply;
400
401                                 returnValue = value.apply( this, arguments );
402
403                                 this._super = __super;
404                                 this._superApply = __superApply;
405
406                                 return returnValue;
407                         };
408                 })();
409         });
410         constructor.prototype = $.widget.extend( basePrototype, {
411                 // TODO: remove support for widgetEventPrefix
412                 // always use the name + a colon as the prefix, e.g., draggable:start
413                 // don't prefix for widgets that aren't DOM-based
414                 widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
415         }, proxiedPrototype, {
416                 constructor: constructor,
417                 namespace: namespace,
418                 widgetName: name,
419                 widgetFullName: fullName
420         });
421
422         // If this widget is being redefined then we need to find all widgets that
423         // are inheriting from it and redefine all of them so that they inherit from
424         // the new version of this widget. We're essentially trying to replace one
425         // level in the prototype chain.
426         if ( existingConstructor ) {
427                 $.each( existingConstructor._childConstructors, function( i, child ) {
428                         var childPrototype = child.prototype;
429
430                         // redefine the child widget using the same prototype that was
431                         // originally used, but inherit from the new version of the base
432                         $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
433                 });
434                 // remove the list of existing child constructors from the old constructor
435                 // so the old child constructors can be garbage collected
436                 delete existingConstructor._childConstructors;
437         } else {
438                 base._childConstructors.push( constructor );
439         }
440
441         $.widget.bridge( name, constructor );
442 };
443
444 $.widget.extend = function( target ) {
445         var input = slice.call( arguments, 1 ),
446                 inputIndex = 0,
447                 inputLength = input.length,
448                 key,
449                 value;
450         for ( ; inputIndex < inputLength; inputIndex++ ) {
451                 for ( key in input[ inputIndex ] ) {
452                         value = input[ inputIndex ][ key ];
453                         if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
454                                 // Clone objects
455                                 if ( $.isPlainObject( value ) ) {
456                                         target[ key ] = $.isPlainObject( target[ key ] ) ?
457                                                 $.widget.extend( {}, target[ key ], value ) :
458                                                 // Don't extend strings, arrays, etc. with objects
459                                                 $.widget.extend( {}, value );
460                                 // Copy everything else by reference
461                                 } else {
462                                         target[ key ] = value;
463                                 }
464                         }
465                 }
466         }
467         return target;
468 };
469
470 $.widget.bridge = function( name, object ) {
471         var fullName = object.prototype.widgetFullName || name;
472         $.fn[ name ] = function( options ) {
473                 var isMethodCall = typeof options === "string",
474                         args = slice.call( arguments, 1 ),
475                         returnValue = this;
476
477                 // allow multiple hashes to be passed on init
478                 options = !isMethodCall && args.length ?
479                         $.widget.extend.apply( null, [ options ].concat(args) ) :
480                         options;
481
482                 if ( isMethodCall ) {
483                         this.each(function() {
484                                 var methodValue,
485                                         instance = $.data( this, fullName );
486                                 if ( !instance ) {
487                                         return $.error( "cannot call methods on " + name + " prior to initialization; " +
488                                                 "attempted to call method '" + options + "'" );
489                                 }
490                                 if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
491                                         return $.error( "no such method '" + options + "' for " + name + " widget instance" );
492                                 }
493                                 methodValue = instance[ options ].apply( instance, args );
494                                 if ( methodValue !== instance && methodValue !== undefined ) {
495                                         returnValue = methodValue && methodValue.jquery ?
496                                                 returnValue.pushStack( methodValue.get() ) :
497                                                 methodValue;
498                                         return false;
499                                 }
500                         });
501                 } else {
502                         this.each(function() {
503                                 var instance = $.data( this, fullName );
504                                 if ( instance ) {
505                                         instance.option( options || {} )._init();
506                                 } else {
507                                         $.data( this, fullName, new object( options, this ) );
508                                 }
509                         });
510                 }
511
512                 return returnValue;
513         };
514 };
515
516 $.Widget = function( /* options, element */ ) {};
517 $.Widget._childConstructors = [];
518
519 $.Widget.prototype = {
520         widgetName: "widget",
521         widgetEventPrefix: "",
522         defaultElement: "<div>",
523         options: {
524                 disabled: false,
525
526                 // callbacks
527                 create: null
528         },
529         _createWidget: function( options, element ) {
530                 element = $( element || this.defaultElement || this )[ 0 ];
531                 this.element = $( element );
532                 this.uuid = uuid++;
533                 this.eventNamespace = "." + this.widgetName + this.uuid;
534                 this.options = $.widget.extend( {},
535                         this.options,
536                         this._getCreateOptions(),
537                         options );
538
539                 this.bindings = $();
540                 this.hoverable = $();
541                 this.focusable = $();
542
543                 if ( element !== this ) {
544                         $.data( element, this.widgetFullName, this );
545                         this._on( true, this.element, {
546                                 remove: function( event ) {
547                                         if ( event.target === element ) {
548                                                 this.destroy();
549                                         }
550                                 }
551                         });
552                         this.document = $( element.style ?
553                                 // element within the document
554                                 element.ownerDocument :
555                                 // element is window or document
556                                 element.document || element );
557                         this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
558                 }
559
560                 this._create();
561                 this._trigger( "create", null, this._getCreateEventData() );
562                 this._init();
563         },
564         _getCreateOptions: $.noop,
565         _getCreateEventData: $.noop,
566         _create: $.noop,
567         _init: $.noop,
568
569         destroy: function() {
570                 this._destroy();
571                 // we can probably remove the unbind calls in 2.0
572                 // all event bindings should go through this._on()
573                 this.element
574                         .unbind( this.eventNamespace )
575                         // 1.9 BC for #7810
576                         // TODO remove dual storage
577                         .removeData( this.widgetName )
578                         .removeData( this.widgetFullName )
579                         // support: jquery <1.6.3
580                         // http://bugs.jquery.com/ticket/9413
581                         .removeData( $.camelCase( this.widgetFullName ) );
582                 this.widget()
583                         .unbind( this.eventNamespace )
584                         .removeAttr( "aria-disabled" )
585                         .removeClass(
586                                 this.widgetFullName + "-disabled " +
587                                 "ui-state-disabled" );
588
589                 // clean up events and states
590                 this.bindings.unbind( this.eventNamespace );
591                 this.hoverable.removeClass( "ui-state-hover" );
592                 this.focusable.removeClass( "ui-state-focus" );
593         },
594         _destroy: $.noop,
595
596         widget: function() {
597                 return this.element;
598         },
599
600         option: function( key, value ) {
601                 var options = key,
602                         parts,
603                         curOption,
604                         i;
605
606                 if ( arguments.length === 0 ) {
607                         // don't return a reference to the internal hash
608                         return $.widget.extend( {}, this.options );
609                 }
610
611                 if ( typeof key === "string" ) {
612                         // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
613                         options = {};
614                         parts = key.split( "." );
615                         key = parts.shift();
616                         if ( parts.length ) {
617                                 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
618                                 for ( i = 0; i < parts.length - 1; i++ ) {
619                                         curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
620                                         curOption = curOption[ parts[ i ] ];
621                                 }
622                                 key = parts.pop();
623                                 if ( value === undefined ) {
624                                         return curOption[ key ] === undefined ? null : curOption[ key ];
625                                 }
626                                 curOption[ key ] = value;
627                         } else {
628                                 if ( value === undefined ) {
629                                         return this.options[ key ] === undefined ? null : this.options[ key ];
630                                 }
631                                 options[ key ] = value;
632                         }
633                 }
634
635                 this._setOptions( options );
636
637                 return this;
638         },
639         _setOptions: function( options ) {
640                 var key;
641
642                 for ( key in options ) {
643                         this._setOption( key, options[ key ] );
644                 }
645
646                 return this;
647         },
648         _setOption: function( key, value ) {
649                 this.options[ key ] = value;
650
651                 if ( key === "disabled" ) {
652                         this.widget()
653                                 .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
654                                 .attr( "aria-disabled", value );
655                         this.hoverable.removeClass( "ui-state-hover" );
656                         this.focusable.removeClass( "ui-state-focus" );
657                 }
658
659                 return this;
660         },
661
662         enable: function() {
663                 return this._setOption( "disabled", false );
664         },
665         disable: function() {
666                 return this._setOption( "disabled", true );
667         },
668
669         _on: function( suppressDisabledCheck, element, handlers ) {
670                 var delegateElement,
671                         instance = this;
672
673                 // no suppressDisabledCheck flag, shuffle arguments
674                 if ( typeof suppressDisabledCheck !== "boolean" ) {
675                         handlers = element;
676                         element = suppressDisabledCheck;
677                         suppressDisabledCheck = false;
678                 }
679
680                 // no element argument, shuffle and use this.element
681                 if ( !handlers ) {
682                         handlers = element;
683                         element = this.element;
684                         delegateElement = this.widget();
685                 } else {
686                         // accept selectors, DOM elements
687                         element = delegateElement = $( element );
688                         this.bindings = this.bindings.add( element );
689                 }
690
691                 $.each( handlers, function( event, handler ) {
692                         function handlerProxy() {
693                                 // allow widgets to customize the disabled handling
694                                 // - disabled as an array instead of boolean
695                                 // - disabled class as method for disabling individual parts
696                                 if ( !suppressDisabledCheck &&
697                                                 ( instance.options.disabled === true ||
698                                                         $( this ).hasClass( "ui-state-disabled" ) ) ) {
699                                         return;
700                                 }
701                                 return ( typeof handler === "string" ? instance[ handler ] : handler )
702                                         .apply( instance, arguments );
703                         }
704
705                         // copy the guid so direct unbinding works
706                         if ( typeof handler !== "string" ) {
707                                 handlerProxy.guid = handler.guid =
708                                         handler.guid || handlerProxy.guid || $.guid++;
709                         }
710
711                         var match = event.match( /^(\w+)\s*(.*)$/ ),
712                                 eventName = match[1] + instance.eventNamespace,
713                                 selector = match[2];
714                         if ( selector ) {
715                                 delegateElement.delegate( selector, eventName, handlerProxy );
716                         } else {
717                                 element.bind( eventName, handlerProxy );
718                         }
719                 });
720         },
721
722         _off: function( element, eventName ) {
723                 eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
724                 element.unbind( eventName ).undelegate( eventName );
725         },
726
727         _delay: function( handler, delay ) {
728                 function handlerProxy() {
729                         return ( typeof handler === "string" ? instance[ handler ] : handler )
730                                 .apply( instance, arguments );
731                 }
732                 var instance = this;
733                 return setTimeout( handlerProxy, delay || 0 );
734         },
735
736         _hoverable: function( element ) {
737                 this.hoverable = this.hoverable.add( element );
738                 this._on( element, {
739                         mouseenter: function( event ) {
740                                 $( event.currentTarget ).addClass( "ui-state-hover" );
741                         },
742                         mouseleave: function( event ) {
743                                 $( event.currentTarget ).removeClass( "ui-state-hover" );
744                         }
745                 });
746         },
747
748         _focusable: function( element ) {
749                 this.focusable = this.focusable.add( element );
750                 this._on( element, {
751                         focusin: function( event ) {
752                                 $( event.currentTarget ).addClass( "ui-state-focus" );
753                         },
754                         focusout: function( event ) {
755                                 $( event.currentTarget ).removeClass( "ui-state-focus" );
756                         }
757                 });
758         },
759
760         _trigger: function( type, event, data ) {
761                 var prop, orig,
762                         callback = this.options[ type ];
763
764                 data = data || {};
765                 event = $.Event( event );
766                 event.type = ( type === this.widgetEventPrefix ?
767                         type :
768                         this.widgetEventPrefix + type ).toLowerCase();
769                 // the original event may come from any element
770                 // so we need to reset the target on the new event
771                 event.target = this.element[ 0 ];
772
773                 // copy original event properties over to the new event
774                 orig = event.originalEvent;
775                 if ( orig ) {
776                         for ( prop in orig ) {
777                                 if ( !( prop in event ) ) {
778                                         event[ prop ] = orig[ prop ];
779                                 }
780                         }
781                 }
782
783                 this.element.trigger( event, data );
784                 return !( $.isFunction( callback ) &&
785                         callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
786                         event.isDefaultPrevented() );
787         }
788 };
789
790 $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
791         $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
792                 if ( typeof options === "string" ) {
793                         options = { effect: options };
794                 }
795                 var hasOptions,
796                         effectName = !options ?
797                                 method :
798                                 options === true || typeof options === "number" ?
799                                         defaultEffect :
800                                         options.effect || defaultEffect;
801                 options = options || {};
802                 if ( typeof options === "number" ) {
803                         options = { duration: options };
804                 }
805                 hasOptions = !$.isEmptyObject( options );
806                 options.complete = callback;
807                 if ( options.delay ) {
808                         element.delay( options.delay );
809                 }
810                 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
811                         element[ method ]( options );
812                 } else if ( effectName !== method && element[ effectName ] ) {
813                         element[ effectName ]( options.duration, options.easing, callback );
814                 } else {
815                         element.queue(function( next ) {
816                                 $( this )[ method ]();
817                                 if ( callback ) {
818                                         callback.call( element[ 0 ] );
819                                 }
820                                 next();
821                         });
822                 }
823         };
824 });
825
826 })( jQuery );
827 (function( $, undefined ) {
828
829 var mouseHandled = false;
830 $( document ).mouseup( function() {
831         mouseHandled = false;
832 });
833
834 $.widget("ui.mouse", {
835         version: "1.10.3",
836         options: {
837                 cancel: "input,textarea,button,select,option",
838                 distance: 1,
839                 delay: 0
840         },
841         _mouseInit: function() {
842                 var that = this;
843
844                 this.element
845                         .bind("mousedown."+this.widgetName, function(event) {
846                                 return that._mouseDown(event);
847                         })
848                         .bind("click."+this.widgetName, function(event) {
849                                 if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
850                                         $.removeData(event.target, that.widgetName + ".preventClickEvent");
851                                         event.stopImmediatePropagation();
852                                         return false;
853                                 }
854                         });
855
856                 this.started = false;
857         },
858
859         // TODO: make sure destroying one instance of mouse doesn't mess with
860         // other instances of mouse
861         _mouseDestroy: function() {
862                 this.element.unbind("."+this.widgetName);
863                 if ( this._mouseMoveDelegate ) {
864                         $(document)
865                                 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
866                                 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
867                 }
868         },
869
870         _mouseDown: function(event) {
871                 // don't let more than one widget handle mouseStart
872                 if( mouseHandled ) { return; }
873
874                 // we may have missed mouseup (out of window)
875                 (this._mouseStarted && this._mouseUp(event));
876
877                 this._mouseDownEvent = event;
878
879                 var that = this,
880                         btnIsLeft = (event.which === 1),
881                         // event.target.nodeName works around a bug in IE 8 with
882                         // disabled inputs (#7620)
883                         elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
884                 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
885                         return true;
886                 }
887
888                 this.mouseDelayMet = !this.options.delay;
889                 if (!this.mouseDelayMet) {
890                         this._mouseDelayTimer = setTimeout(function() {
891                                 that.mouseDelayMet = true;
892                         }, this.options.delay);
893                 }
894
895                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
896                         this._mouseStarted = (this._mouseStart(event) !== false);
897                         if (!this._mouseStarted) {
898                                 event.preventDefault();
899                                 return true;
900                         }
901                 }
902
903                 // Click event may never have fired (Gecko & Opera)
904                 if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
905                         $.removeData(event.target, this.widgetName + ".preventClickEvent");
906                 }
907
908                 // these delegates are required to keep context
909                 this._mouseMoveDelegate = function(event) {
910                         return that._mouseMove(event);
911                 };
912                 this._mouseUpDelegate = function(event) {
913                         return that._mouseUp(event);
914                 };
915                 $(document)
916                         .bind("mousemove."+this.widgetName, this._mouseMoveDelegate)
917                         .bind("mouseup."+this.widgetName, this._mouseUpDelegate);
918
919                 event.preventDefault();
920
921                 mouseHandled = true;
922                 return true;
923         },
924
925         _mouseMove: function(event) {
926                 // IE mouseup check - mouseup happened when mouse was out of window
927                 if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
928                         return this._mouseUp(event);
929                 }
930
931                 if (this._mouseStarted) {
932                         this._mouseDrag(event);
933                         return event.preventDefault();
934                 }
935
936                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
937                         this._mouseStarted =
938                                 (this._mouseStart(this._mouseDownEvent, event) !== false);
939                         (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
940                 }
941
942                 return !this._mouseStarted;
943         },
944
945         _mouseUp: function(event) {
946                 $(document)
947                         .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
948                         .unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
949
950                 if (this._mouseStarted) {
951                         this._mouseStarted = false;
952
953                         if (event.target === this._mouseDownEvent.target) {
954                                 $.data(event.target, this.widgetName + ".preventClickEvent", true);
955                         }
956
957                         this._mouseStop(event);
958                 }
959
960                 return false;
961         },
962
963         _mouseDistanceMet: function(event) {
964                 return (Math.max(
965                                 Math.abs(this._mouseDownEvent.pageX - event.pageX),
966                                 Math.abs(this._mouseDownEvent.pageY - event.pageY)
967                         ) >= this.options.distance
968                 );
969         },
970
971         _mouseDelayMet: function(/* event */) {
972                 return this.mouseDelayMet;
973         },
974
975         // These are placeholder methods, to be overriden by extending plugin
976         _mouseStart: function(/* event */) {},
977         _mouseDrag: function(/* event */) {},
978         _mouseStop: function(/* event */) {},
979         _mouseCapture: function(/* event */) { return true; }
980 });
981
982 })(jQuery);
983 (function( $, undefined ) {
984
985 /*jshint loopfunc: true */
986
987 function isOverAxis( x, reference, size ) {
988         return ( x > reference ) && ( x < ( reference + size ) );
989 }
990
991 function isFloating(item) {
992         return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display"));
993 }
994
995 $.widget("ui.sortable", $.ui.mouse, {
996         version: "1.10.3",
997         widgetEventPrefix: "sort",
998         ready: false,
999         options: {
1000                 appendTo: "parent",
1001                 axis: false,
1002                 connectWith: false,
1003                 containment: false,
1004                 cursor: "auto",
1005                 cursorAt: false,
1006                 dropOnEmpty: true,
1007                 forcePlaceholderSize: false,
1008                 forceHelperSize: false,
1009                 grid: false,
1010                 handle: false,
1011                 helper: "original",
1012                 items: "> *",
1013                 opacity: false,
1014                 placeholder: false,
1015                 revert: false,
1016                 scroll: true,
1017                 scrollSensitivity: 20,
1018                 scrollSpeed: 20,
1019                 scope: "default",
1020                 tolerance: "intersect",
1021                 zIndex: 1000,
1022
1023                 // callbacks
1024                 activate: null,
1025                 beforeStop: null,
1026                 change: null,
1027                 deactivate: null,
1028                 out: null,
1029                 over: null,
1030                 receive: null,
1031                 remove: null,
1032                 sort: null,
1033                 start: null,
1034                 stop: null,
1035                 update: null
1036         },
1037         _create: function() {
1038
1039                 var o = this.options;
1040                 this.containerCache = {};
1041                 this.element.addClass("ui-sortable");
1042
1043                 //Get the items
1044                 this.refresh();
1045
1046                 //Let's determine if the items are being displayed horizontally
1047                 this.floating = this.items.length ? o.axis === "x" || isFloating(this.items[0].item) : false;
1048
1049                 //Let's determine the parent's offset
1050                 this.offset = this.element.offset();
1051
1052                 //Initialize mouse events for interaction
1053                 this._mouseInit();
1054
1055                 //We're ready to go
1056                 this.ready = true;
1057
1058         },
1059
1060         _destroy: function() {
1061                 this.element
1062                         .removeClass("ui-sortable ui-sortable-disabled");
1063                 this._mouseDestroy();
1064
1065                 for ( var i = this.items.length - 1; i >= 0; i-- ) {
1066                         this.items[i].item.removeData(this.widgetName + "-item");
1067                 }
1068
1069                 return this;
1070         },
1071
1072         _setOption: function(key, value){
1073                 if ( key === "disabled" ) {
1074                         this.options[ key ] = value;
1075
1076                         this.widget().toggleClass( "ui-sortable-disabled", !!value );
1077                 } else {
1078                         // Don't call widget base _setOption for disable as it adds ui-state-disabled class
1079                         $.Widget.prototype._setOption.apply(this, arguments);
1080                 }
1081         },
1082
1083         _mouseCapture: function(event, overrideHandle) {
1084                 var currentItem = null,
1085                         validHandle = false,
1086                         that = this;
1087
1088                 if (this.reverting) {
1089                         return false;
1090                 }
1091
1092                 if(this.options.disabled || this.options.type === "static") {
1093                         return false;
1094                 }
1095
1096                 //We have to refresh the items data once first
1097                 this._refreshItems(event);
1098
1099                 //Find out if the clicked node (or one of its parents) is a actual item in this.items
1100                 $(event.target).parents().each(function() {
1101                         if($.data(this, that.widgetName + "-item") === that) {
1102                                 currentItem = $(this);
1103                                 return false;
1104                         }
1105                 });
1106                 if($.data(event.target, that.widgetName + "-item") === that) {
1107                         currentItem = $(event.target);
1108                 }
1109
1110                 if(!currentItem) {
1111                         return false;
1112                 }
1113                 if(this.options.handle && !overrideHandle) {
1114                         $(this.options.handle, currentItem).find("*").addBack().each(function() {
1115                                 if(this === event.target) {
1116                                         validHandle = true;
1117                                 }
1118                         });
1119                         if(!validHandle) {
1120                                 return false;
1121                         }
1122                 }
1123
1124                 this.currentItem = currentItem;
1125                 this._removeCurrentsFromItems();
1126                 return true;
1127
1128         },
1129
1130         _mouseStart: function(event, overrideHandle, noActivation) {
1131
1132                 var i, body,
1133                         o = this.options;
1134
1135                 this.currentContainer = this;
1136
1137                 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
1138                 this.refreshPositions();
1139
1140                 //Create and append the visible helper
1141                 this.helper = this._createHelper(event);
1142
1143                 //Cache the helper size
1144                 this._cacheHelperProportions();
1145
1146                 /*
1147                  * - Position generation -
1148                  * This block generates everything position related - it's the core of draggables.
1149                  */
1150
1151                 //Cache the margins of the original element
1152                 this._cacheMargins();
1153
1154                 //Get the next scrolling parent
1155                 this.scrollParent = this.helper.scrollParent();
1156
1157                 //The element's absolute position on the page minus margins
1158                 this.offset = this.currentItem.offset();
1159                 this.offset = {
1160                         top: this.offset.top - this.margins.top,
1161                         left: this.offset.left - this.margins.left
1162                 };
1163
1164                 $.extend(this.offset, {
1165                         click: { //Where the click happened, relative to the element
1166                                 left: event.pageX - this.offset.left,
1167                                 top: event.pageY - this.offset.top
1168                         },
1169                         parent: this._getParentOffset(),
1170                         relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
1171                 });
1172
1173                 // Only after we got the offset, we can change the helper's position to absolute
1174                 // TODO: Still need to figure out a way to make relative sorting possible
1175                 this.helper.css("position", "absolute");
1176                 this.cssPosition = this.helper.css("position");
1177
1178                 //Generate the original position
1179                 this.originalPosition = this._generatePosition(event);
1180                 this.originalPageX = event.pageX;
1181                 this.originalPageY = event.pageY;
1182
1183                 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
1184                 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
1185
1186                 //Cache the former DOM position
1187                 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
1188
1189                 //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
1190                 if(this.helper[0] !== this.currentItem[0]) {
1191                         this.currentItem.hide();
1192                 }
1193
1194                 //Create the placeholder
1195                 this._createPlaceholder();
1196
1197                 //Set a containment if given in the options
1198                 if(o.containment) {
1199                         this._setContainment();
1200                 }
1201
1202                 if( o.cursor && o.cursor !== "auto" ) { // cursor option
1203                         body = this.document.find( "body" );
1204
1205                         // support: IE
1206                         this.storedCursor = body.css( "cursor" );
1207                         body.css( "cursor", o.cursor );
1208
1209                         this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body );
1210                 }
1211
1212                 if(o.opacity) { // opacity option
1213                         if (this.helper.css("opacity")) {
1214                                 this._storedOpacity = this.helper.css("opacity");
1215                         }
1216                         this.helper.css("opacity", o.opacity);
1217                 }
1218
1219                 if(o.zIndex) { // zIndex option
1220                         if (this.helper.css("zIndex")) {
1221                                 this._storedZIndex = this.helper.css("zIndex");
1222                         }
1223                         this.helper.css("zIndex", o.zIndex);
1224                 }
1225
1226                 //Prepare scrolling
1227                 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
1228                         this.overflowOffset = this.scrollParent.offset();
1229                 }
1230
1231                 //Call callbacks
1232                 this._trigger("start", event, this._uiHash());
1233
1234                 //Recache the helper size
1235                 if(!this._preserveHelperProportions) {
1236                         this._cacheHelperProportions();
1237                 }
1238
1239
1240                 //Post "activate" events to possible containers
1241                 if( !noActivation ) {
1242                         for ( i = this.containers.length - 1; i >= 0; i-- ) {
1243                                 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
1244                         }
1245                 }
1246
1247                 //Prepare possible droppables
1248                 if($.ui.ddmanager) {
1249                         $.ui.ddmanager.current = this;
1250                 }
1251
1252                 if ($.ui.ddmanager && !o.dropBehaviour) {
1253                         $.ui.ddmanager.prepareOffsets(this, event);
1254                 }
1255
1256                 this.dragging = true;
1257
1258                 this.helper.addClass("ui-sortable-helper");
1259                 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
1260                 return true;
1261
1262         },
1263
1264         _mouseDrag: function(event) {
1265                 var i, item, itemElement, intersection,
1266                         o = this.options,
1267                         scrolled = false;
1268
1269                 //Compute the helpers position
1270                 this.position = this._generatePosition(event);
1271                 this.positionAbs = this._convertPositionTo("absolute");
1272
1273                 if (!this.lastPositionAbs) {
1274                         this.lastPositionAbs = this.positionAbs;
1275                 }
1276
1277                 //Do scrolling
1278                 if(this.options.scroll) {
1279                         if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
1280
1281                                 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
1282                                         this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
1283                                 } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
1284                                         this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
1285                                 }
1286
1287                                 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
1288                                         this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
1289                                 } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
1290                                         this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
1291                                 }
1292
1293                         } else {
1294
1295                                 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
1296                                         scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1297                                 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
1298                                         scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1299                                 }
1300
1301                                 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
1302                                         scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1303                                 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
1304                                         scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1305                                 }
1306
1307                         }
1308
1309                         if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
1310                                 $.ui.ddmanager.prepareOffsets(this, event);
1311                         }
1312                 }
1313
1314                 //Regenerate the absolute position used for position checks
1315                 this.positionAbs = this._convertPositionTo("absolute");
1316
1317                 //Set the helper position
1318                 if(!this.options.axis || this.options.axis !== "y") {
1319                         this.helper[0].style.left = this.position.left+"px";
1320                 }
1321                 if(!this.options.axis || this.options.axis !== "x") {
1322                         this.helper[0].style.top = this.position.top+"px";
1323                 }
1324
1325                 //Rearrange
1326                 for (i = this.items.length - 1; i >= 0; i--) {
1327
1328                         //Cache variables and intersection, continue if no intersection
1329                         item = this.items[i];
1330                         itemElement = item.item[0];
1331                         intersection = this._intersectsWithPointer(item);
1332                         if (!intersection) {
1333                                 continue;
1334                         }
1335
1336                         // Only put the placeholder inside the current Container, skip all
1337                         // items form other containers. This works because when moving
1338                         // an item from one container to another the
1339                         // currentContainer is switched before the placeholder is moved.
1340                         //
1341                         // Without this moving items in "sub-sortables" can cause the placeholder to jitter
1342                         // beetween the outer and inner container.
1343                         if (item.instance !== this.currentContainer) {
1344                                 continue;
1345                         }
1346
1347                         // cannot intersect with itself
1348                         // no useless actions that have been done before
1349                         // no action if the item moved is the parent of the item checked
1350                         if (itemElement !== this.currentItem[0] &&
1351                                 this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
1352                                 !$.contains(this.placeholder[0], itemElement) &&
1353                                 (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
1354                         ) {
1355
1356                                 this.direction = intersection === 1 ? "down" : "up";
1357
1358                                 if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
1359                                         this._rearrange(event, item);
1360                                 } else {
1361                                         break;
1362                                 }
1363
1364                                 this._trigger("change", event, this._uiHash());
1365                                 break;
1366                         }
1367                 }
1368
1369                 //Post events to containers
1370                 this._contactContainers(event);
1371
1372                 //Interconnect with droppables
1373                 if($.ui.ddmanager) {
1374                         $.ui.ddmanager.drag(this, event);
1375                 }
1376
1377                 //Call callbacks
1378                 this._trigger("sort", event, this._uiHash());
1379
1380                 this.lastPositionAbs = this.positionAbs;
1381                 return false;
1382
1383         },
1384
1385         _mouseStop: function(event, noPropagation) {
1386
1387                 if(!event) {
1388                         return;
1389                 }
1390
1391                 //If we are using droppables, inform the manager about the drop
1392                 if ($.ui.ddmanager && !this.options.dropBehaviour) {
1393                         $.ui.ddmanager.drop(this, event);
1394                 }
1395
1396                 if(this.options.revert) {
1397                         var that = this,
1398                                 cur = this.placeholder.offset(),
1399                                 axis = this.options.axis,
1400                                 animation = {};
1401
1402                         if ( !axis || axis === "x" ) {
1403                                 animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft);
1404                         }
1405                         if ( !axis || axis === "y" ) {
1406                                 animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop);
1407                         }
1408                         this.reverting = true;
1409                         $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() {
1410                                 that._clear(event);
1411                         });
1412                 } else {
1413                         this._clear(event, noPropagation);
1414                 }
1415
1416                 return false;
1417
1418         },
1419
1420         cancel: function() {
1421
1422                 if(this.dragging) {
1423
1424                         this._mouseUp({ target: null });
1425
1426                         if(this.options.helper === "original") {
1427                                 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
1428                         } else {
1429                                 this.currentItem.show();
1430                         }
1431
1432                         //Post deactivating events to containers
1433                         for (var i = this.containers.length - 1; i >= 0; i--){
1434                                 this.containers[i]._trigger("deactivate", null, this._uiHash(this));
1435                                 if(this.containers[i].containerCache.over) {
1436                                         this.containers[i]._trigger("out", null, this._uiHash(this));
1437                                         this.containers[i].containerCache.over = 0;
1438                                 }
1439                         }
1440
1441                 }
1442
1443                 if (this.placeholder) {
1444                         //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
1445                         if(this.placeholder[0].parentNode) {
1446                                 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
1447                         }
1448                         if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) {
1449                                 this.helper.remove();
1450                         }
1451
1452                         $.extend(this, {
1453                                 helper: null,
1454                                 dragging: false,
1455                                 reverting: false,
1456                                 _noFinalSort: null
1457                         });
1458
1459                         if(this.domPosition.prev) {
1460                                 $(this.domPosition.prev).after(this.currentItem);
1461                         } else {
1462                                 $(this.domPosition.parent).prepend(this.currentItem);
1463                         }
1464                 }
1465
1466                 return this;
1467
1468         },
1469
1470         serialize: function(o) {
1471
1472                 var items = this._getItemsAsjQuery(o && o.connected),
1473                         str = [];
1474                 o = o || {};
1475
1476                 $(items).each(function() {
1477                         var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/));
1478                         if (res) {
1479                                 str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2]));
1480                         }
1481                 });
1482
1483                 if(!str.length && o.key) {
1484                         str.push(o.key + "=");
1485                 }
1486
1487                 return str.join("&");
1488
1489         },
1490
1491         toArray: function(o) {
1492
1493                 var items = this._getItemsAsjQuery(o && o.connected),
1494                         ret = [];
1495
1496                 o = o || {};
1497
1498                 items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); });
1499                 return ret;
1500
1501         },
1502
1503         /* Be careful with the following core functions */
1504         _intersectsWith: function(item) {
1505
1506                 var x1 = this.positionAbs.left,
1507                         x2 = x1 + this.helperProportions.width,
1508                         y1 = this.positionAbs.top,
1509                         y2 = y1 + this.helperProportions.height,
1510                         l = item.left,
1511                         r = l + item.width,
1512                         t = item.top,
1513                         b = t + item.height,
1514                         dyClick = this.offset.click.top,
1515                         dxClick = this.offset.click.left,
1516                         isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ),
1517                         isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ),
1518                         isOverElement = isOverElementHeight && isOverElementWidth;
1519
1520                 if ( this.options.tolerance === "pointer" ||
1521                         this.options.forcePointerForContainers ||
1522                         (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"])
1523                 ) {
1524                         return isOverElement;
1525                 } else {
1526
1527                         return (l < x1 + (this.helperProportions.width / 2) && // Right Half
1528                                 x2 - (this.helperProportions.width / 2) < r && // Left Half
1529                                 t < y1 + (this.helperProportions.height / 2) && // Bottom Half
1530                                 y2 - (this.helperProportions.height / 2) < b ); // Top Half
1531
1532                 }
1533         },
1534
1535         _intersectsWithPointer: function(item) {
1536
1537                 var isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
1538                         isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
1539                         isOverElement = isOverElementHeight && isOverElementWidth,
1540                         verticalDirection = this._getDragVerticalDirection(),
1541                         horizontalDirection = this._getDragHorizontalDirection();
1542
1543                 if (!isOverElement) {
1544                         return false;
1545                 }
1546
1547                 return this.floating ?
1548                         ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 )
1549                         : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) );
1550
1551         },
1552
1553         _intersectsWithSides: function(item) {
1554
1555                 var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
1556                         isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
1557                         verticalDirection = this._getDragVerticalDirection(),
1558                         horizontalDirection = this._getDragHorizontalDirection();
1559
1560                 if (this.floating && horizontalDirection) {
1561                         return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf));
1562                 } else {
1563                         return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf));
1564                 }
1565
1566         },
1567
1568         _getDragVerticalDirection: function() {
1569                 var delta = this.positionAbs.top - this.lastPositionAbs.top;
1570                 return delta !== 0 && (delta > 0 ? "down" : "up");
1571         },
1572
1573         _getDragHorizontalDirection: function() {
1574                 var delta = this.positionAbs.left - this.lastPositionAbs.left;
1575                 return delta !== 0 && (delta > 0 ? "right" : "left");
1576         },
1577
1578         refresh: function(event) {
1579                 this._refreshItems(event);
1580                 this.refreshPositions();
1581                 return this;
1582         },
1583
1584         _connectWith: function() {
1585                 var options = this.options;
1586                 return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;
1587         },
1588
1589         _getItemsAsjQuery: function(connected) {
1590
1591                 var i, j, cur, inst,
1592                         items = [],
1593                         queries = [],
1594                         connectWith = this._connectWith();
1595
1596                 if(connectWith && connected) {
1597                         for (i = connectWith.length - 1; i >= 0; i--){
1598                                 cur = $(connectWith[i]);
1599                                 for ( j = cur.length - 1; j >= 0; j--){
1600                                         inst = $.data(cur[j], this.widgetFullName);
1601                                         if(inst && inst !== this && !inst.options.disabled) {
1602                                                 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]);
1603                                         }
1604                                 }
1605                         }
1606                 }
1607
1608                 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]);
1609
1610                 for (i = queries.length - 1; i >= 0; i--){
1611                         queries[i][0].each(function() {
1612                                 items.push(this);
1613                         });
1614                 }
1615
1616                 return $(items);
1617
1618         },
1619
1620         _removeCurrentsFromItems: function() {
1621
1622                 var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
1623
1624                 this.items = $.grep(this.items, function (item) {
1625                         for (var j=0; j < list.length; j++) {
1626                                 if(list[j] === item.item[0]) {
1627                                         return false;
1628                                 }
1629                         }
1630                         return true;
1631                 });
1632
1633         },
1634
1635         _refreshItems: function(event) {
1636
1637                 this.items = [];
1638                 this.containers = [this];
1639
1640                 var i, j, cur, inst, targetData, _queries, item, queriesLength,
1641                         items = this.items,
1642                         queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],
1643                         connectWith = this._connectWith();
1644
1645                 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
1646                         for (i = connectWith.length - 1; i >= 0; i--){
1647                                 cur = $(connectWith[i]);
1648                                 for (j = cur.length - 1; j >= 0; j--){
1649                                         inst = $.data(cur[j], this.widgetFullName);
1650                                         if(inst && inst !== this && !inst.options.disabled) {
1651                                                 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
1652                                                 this.containers.push(inst);
1653                                         }
1654                                 }
1655                         }
1656                 }
1657
1658                 for (i = queries.length - 1; i >= 0; i--) {
1659                         targetData = queries[i][1];
1660                         _queries = queries[i][0];
1661
1662                         for (j=0, queriesLength = _queries.length; j < queriesLength; j++) {
1663                                 item = $(_queries[j]);
1664
1665                                 item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager)
1666
1667                                 items.push({
1668                                         item: item,
1669                                         instance: targetData,
1670                                         width: 0, height: 0,
1671                                         left: 0, top: 0
1672                                 });
1673                         }
1674                 }
1675
1676         },
1677
1678         refreshPositions: function(fast) {
1679
1680                 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
1681                 if(this.offsetParent && this.helper) {
1682                         this.offset.parent = this._getParentOffset();
1683                 }
1684
1685                 var i, item, t, p;
1686
1687                 for (i = this.items.length - 1; i >= 0; i--){
1688                         item = this.items[i];
1689
1690                         //We ignore calculating positions of all connected containers when we're not over them
1691                         if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {
1692                                 continue;
1693                         }
1694
1695                         t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
1696
1697                         if (!fast) {
1698                                 item.width = t.outerWidth();
1699                                 item.height = t.outerHeight();
1700                         }
1701
1702                         p = t.offset();
1703                         item.left = p.left;
1704                         item.top = p.top;
1705                 }
1706
1707                 if(this.options.custom && this.options.custom.refreshContainers) {
1708                         this.options.custom.refreshContainers.call(this);
1709                 } else {
1710                         for (i = this.containers.length - 1; i >= 0; i--){
1711                                 p = this.containers[i].element.offset();
1712                                 this.containers[i].containerCache.left = p.left;
1713                                 this.containers[i].containerCache.top = p.top;
1714                                 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
1715                                 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
1716                         }
1717                 }
1718
1719                 return this;
1720         },
1721
1722         _createPlaceholder: function(that) {
1723                 that = that || this;
1724                 var className,
1725                         o = that.options;
1726
1727                 if(!o.placeholder || o.placeholder.constructor === String) {
1728                         className = o.placeholder;
1729                         o.placeholder = {
1730                                 element: function() {
1731
1732                                         var nodeName = that.currentItem[0].nodeName.toLowerCase(),
1733                                                 element = $( "<" + nodeName + ">", that.document[0] )
1734                                                         .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
1735                                                         .removeClass("ui-sortable-helper");
1736
1737                                         if ( nodeName === "tr" ) {
1738                                                 that.currentItem.children().each(function() {
1739                                                         $( "<td>&#160;</td>", that.document[0] )
1740                                                                 .attr( "colspan", $( this ).attr( "colspan" ) || 1 )
1741                                                                 .appendTo( element );
1742                                                 });
1743                                         } else if ( nodeName === "img" ) {
1744                                                 element.attr( "src", that.currentItem.attr( "src" ) );
1745                                         }
1746
1747                                         if ( !className ) {
1748                                                 element.css( "visibility", "hidden" );
1749                                         }
1750
1751                                         return element;
1752                                 },
1753                                 update: function(container, p) {
1754
1755                                         // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
1756                                         // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
1757                                         if(className && !o.forcePlaceholderSize) {
1758                                                 return;
1759                                         }
1760
1761                                         //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
1762                                         if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); }
1763                                         if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); }
1764                                 }
1765                         };
1766                 }
1767
1768                 //Create the placeholder
1769                 that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
1770
1771                 //Append it after the actual current item
1772                 that.currentItem.after(that.placeholder);
1773
1774                 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
1775                 o.placeholder.update(that, that.placeholder);
1776
1777         },
1778
1779         _contactContainers: function(event) {
1780                 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating,
1781                         innermostContainer = null,
1782                         innermostIndex = null;
1783
1784                 // get innermost container that intersects with item
1785                 for (i = this.containers.length - 1; i >= 0; i--) {
1786
1787                         // never consider a container that's located within the item itself
1788                         if($.contains(this.currentItem[0], this.containers[i].element[0])) {
1789                                 continue;
1790                         }
1791
1792                         if(this._intersectsWith(this.containers[i].containerCache)) {
1793
1794                                 // if we've already found a container and it's more "inner" than this, then continue
1795                                 if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {
1796                                         continue;
1797                                 }
1798
1799                                 innermostContainer = this.containers[i];
1800                                 innermostIndex = i;
1801
1802                         } else {
1803                                 // container doesn't intersect. trigger "out" event if necessary
1804                                 if(this.containers[i].containerCache.over) {
1805                                         this.containers[i]._trigger("out", event, this._uiHash(this));
1806                                         this.containers[i].containerCache.over = 0;
1807                                 }
1808                         }
1809
1810                 }
1811
1812                 // if no intersecting containers found, return
1813                 if(!innermostContainer) {
1814                         return;
1815                 }
1816
1817                 // move the item into the container if it's not there already
1818                 if(this.containers.length === 1) {
1819                         if (!this.containers[innermostIndex].containerCache.over) {
1820                                 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
1821                                 this.containers[innermostIndex].containerCache.over = 1;
1822                         }
1823                 } else {
1824
1825                         //When entering a new container, we will find the item with the least distance and append our item near it
1826                         dist = 10000;
1827                         itemWithLeastDistance = null;
1828                         floating = innermostContainer.floating || isFloating(this.currentItem);
1829                         posProperty = floating ? "left" : "top";
1830                         sizeProperty = floating ? "width" : "height";
1831                         base = this.positionAbs[posProperty] + this.offset.click[posProperty];
1832                         for (j = this.items.length - 1; j >= 0; j--) {
1833                                 if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {
1834                                         continue;
1835                                 }
1836                                 if(this.items[j].item[0] === this.currentItem[0]) {
1837                                         continue;
1838                                 }
1839                                 if (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) {
1840                                         continue;
1841                                 }
1842                                 cur = this.items[j].item.offset()[posProperty];
1843                                 nearBottom = false;
1844                                 if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){
1845                                         nearBottom = true;
1846                                         cur += this.items[j][sizeProperty];
1847                                 }
1848
1849                                 if(Math.abs(cur - base) < dist) {
1850                                         dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
1851                                         this.direction = nearBottom ? "up": "down";
1852                                 }
1853                         }
1854
1855                         //Check if dropOnEmpty is enabled
1856                         if(!itemWithLeastDistance && !this.options.dropOnEmpty) {
1857                                 return;
1858                         }
1859
1860                         if(this.currentContainer === this.containers[innermostIndex]) {
1861                                 return;
1862                         }
1863
1864                         itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
1865                         this._trigger("change", event, this._uiHash());
1866                         this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
1867                         this.currentContainer = this.containers[innermostIndex];
1868
1869                         //Update the placeholder
1870                         this.options.placeholder.update(this.currentContainer, this.placeholder);
1871
1872                         this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
1873                         this.containers[innermostIndex].containerCache.over = 1;
1874                 }
1875
1876
1877         },
1878
1879         _createHelper: function(event) {
1880
1881                 var o = this.options,
1882                         helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem);
1883
1884                 //Add the helper to the DOM if that didn't happen already
1885                 if(!helper.parents("body").length) {
1886                         $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
1887                 }
1888
1889                 if(helper[0] === this.currentItem[0]) {
1890                         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") };
1891                 }
1892
1893                 if(!helper[0].style.width || o.forceHelperSize) {
1894                         helper.width(this.currentItem.width());
1895                 }
1896                 if(!helper[0].style.height || o.forceHelperSize) {
1897                         helper.height(this.currentItem.height());
1898                 }
1899
1900                 return helper;
1901
1902         },
1903
1904         _adjustOffsetFromHelper: function(obj) {
1905                 if (typeof obj === "string") {
1906                         obj = obj.split(" ");
1907                 }
1908                 if ($.isArray(obj)) {
1909                         obj = {left: +obj[0], top: +obj[1] || 0};
1910                 }
1911                 if ("left" in obj) {
1912                         this.offset.click.left = obj.left + this.margins.left;
1913                 }
1914                 if ("right" in obj) {
1915                         this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1916                 }
1917                 if ("top" in obj) {
1918                         this.offset.click.top = obj.top + this.margins.top;
1919                 }
1920                 if ("bottom" in obj) {
1921                         this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1922                 }
1923         },
1924
1925         _getParentOffset: function() {
1926
1927
1928                 //Get the offsetParent and cache its position
1929                 this.offsetParent = this.helper.offsetParent();
1930                 var po = this.offsetParent.offset();
1931
1932                 // This is a special case where we need to modify a offset calculated on start, since the following happened:
1933                 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1934                 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1935                 //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1936                 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
1937                         po.left += this.scrollParent.scrollLeft();
1938                         po.top += this.scrollParent.scrollTop();
1939                 }
1940
1941                 // This needs to be actually done for all browsers, since pageX/pageY includes this information
1942                 // with an ugly IE fix
1943                 if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
1944                         po = { top: 0, left: 0 };
1945                 }
1946
1947                 return {
1948                         top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1949                         left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1950                 };
1951
1952         },
1953
1954         _getRelativeOffset: function() {
1955
1956                 if(this.cssPosition === "relative") {
1957                         var p = this.currentItem.position();
1958                         return {
1959                                 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1960                                 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1961                         };
1962                 } else {
1963                         return { top: 0, left: 0 };
1964                 }
1965
1966         },
1967
1968         _cacheMargins: function() {
1969                 this.margins = {
1970                         left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
1971                         top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
1972                 };
1973         },
1974
1975         _cacheHelperProportions: function() {
1976                 this.helperProportions = {
1977                         width: this.helper.outerWidth(),
1978                         height: this.helper.outerHeight()
1979                 };
1980         },
1981
1982         _setContainment: function() {
1983
1984                 var ce, co, over,
1985                         o = this.options;
1986                 if(o.containment === "parent") {
1987                         o.containment = this.helper[0].parentNode;
1988                 }
1989                 if(o.containment === "document" || o.containment === "window") {
1990                         this.containment = [
1991                                 0 - this.offset.relative.left - this.offset.parent.left,
1992                                 0 - this.offset.relative.top - this.offset.parent.top,
1993                                 $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left,
1994                                 ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
1995                         ];
1996                 }
1997
1998                 if(!(/^(document|window|parent)$/).test(o.containment)) {
1999                         ce = $(o.containment)[0];
2000                         co = $(o.containment).offset();
2001                         over = ($(ce).css("overflow") !== "hidden");
2002
2003                         this.containment = [
2004                                 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
2005                                 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
2006                                 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,
2007                                 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
2008                         ];
2009                 }
2010
2011         },
2012
2013         _convertPositionTo: function(d, pos) {
2014
2015                 if(!pos) {
2016                         pos = this.position;
2017                 }
2018                 var mod = d === "absolute" ? 1 : -1,
2019                         scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
2020                         scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
2021
2022                 return {
2023                         top: (
2024                                 pos.top +                                                                                                                               // The absolute mouse position
2025                                 this.offset.relative.top * mod +                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
2026                                 this.offset.parent.top * mod -                                                                                  // The offsetParent's offset without borders (offset + border)
2027                                 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
2028                         ),
2029                         left: (
2030                                 pos.left +                                                                                                                              // The absolute mouse position
2031                                 this.offset.relative.left * mod +                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
2032                                 this.offset.parent.left * mod   -                                                                               // The offsetParent's offset without borders (offset + border)
2033                                 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
2034                         )
2035                 };
2036
2037         },
2038
2039         _generatePosition: function(event) {
2040
2041                 var top, left,
2042                         o = this.options,
2043                         pageX = event.pageX,
2044                         pageY = event.pageY,
2045                         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);
2046
2047                 // This is another very weird special case that only happens for relative elements:
2048                 // 1. If the css position is relative
2049                 // 2. and the scroll parent is the document or similar to the offset parent
2050                 // we have to refresh the relative offset during the scroll so there are no jumps
2051                 if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) {
2052                         this.offset.relative = this._getRelativeOffset();
2053                 }
2054
2055                 /*
2056                  * - Position constraining -
2057                  * Constrain the position to a mix of grid, containment.
2058                  */
2059
2060                 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
2061
2062                         if(this.containment) {
2063                                 if(event.pageX - this.offset.click.left < this.containment[0]) {
2064                                         pageX = this.containment[0] + this.offset.click.left;
2065                                 }
2066                                 if(event.pageY - this.offset.click.top < this.containment[1]) {
2067                                         pageY = this.containment[1] + this.offset.click.top;
2068                                 }
2069                                 if(event.pageX - this.offset.click.left > this.containment[2]) {
2070                                         pageX = this.containment[2] + this.offset.click.left;
2071                                 }
2072                                 if(event.pageY - this.offset.click.top > this.containment[3]) {
2073                                         pageY = this.containment[3] + this.offset.click.top;
2074                                 }
2075                         }
2076
2077                         if(o.grid) {
2078                                 top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
2079                                 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;
2080
2081                                 left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
2082                                 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;
2083                         }
2084
2085                 }
2086
2087                 return {
2088                         top: (
2089                                 pageY -                                                                                                                         // The absolute mouse position
2090                                 this.offset.click.top -                                                                                                 // Click offset (relative to the element)
2091                                 this.offset.relative.top        -                                                                                       // Only for relative positioned nodes: Relative offset from element to offset parent
2092                                 this.offset.parent.top +                                                                                                // The offsetParent's offset without borders (offset + border)
2093                                 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
2094                         ),
2095                         left: (
2096                                 pageX -                                                                                                                         // The absolute mouse position
2097                                 this.offset.click.left -                                                                                                // Click offset (relative to the element)
2098                                 this.offset.relative.left       -                                                                                       // Only for relative positioned nodes: Relative offset from element to offset parent
2099                                 this.offset.parent.left +                                                                                               // The offsetParent's offset without borders (offset + border)
2100                                 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
2101                         )
2102                 };
2103
2104         },
2105
2106         _rearrange: function(event, i, a, hardRefresh) {
2107
2108                 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));
2109
2110                 //Various things done here to improve the performance:
2111                 // 1. we create a setTimeout, that calls refreshPositions
2112                 // 2. on the instance, we have a counter variable, that get's higher after every append
2113                 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
2114                 // 4. this lets only the last addition to the timeout stack through
2115                 this.counter = this.counter ? ++this.counter : 1;
2116                 var counter = this.counter;
2117
2118                 this._delay(function() {
2119                         if(counter === this.counter) {
2120                                 this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
2121                         }
2122                 });
2123
2124         },
2125
2126         _clear: function(event, noPropagation) {
2127
2128                 this.reverting = false;
2129                 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
2130                 // everything else normalized again
2131                 var i,
2132                         delayedTriggers = [];
2133
2134                 // We first have to update the dom position of the actual currentItem
2135                 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
2136                 if(!this._noFinalSort && this.currentItem.parent().length) {
2137                         this.placeholder.before(this.currentItem);
2138                 }
2139                 this._noFinalSort = null;
2140
2141                 if(this.helper[0] === this.currentItem[0]) {
2142                         for(i in this._storedCSS) {
2143                                 if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
2144                                         this._storedCSS[i] = "";
2145                                 }
2146                         }
2147                         this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
2148                 } else {
2149                         this.currentItem.show();
2150                 }
2151
2152                 if(this.fromOutside && !noPropagation) {
2153                         delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
2154                 }
2155                 if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {
2156                         delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
2157                 }
2158
2159                 // Check if the items Container has Changed and trigger appropriate
2160                 // events.
2161                 if (this !== this.currentContainer) {
2162                         if(!noPropagation) {
2163                                 delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
2164                                 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.currentContainer));
2165                                 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.currentContainer));
2166                         }
2167                 }
2168
2169
2170                 //Post events to containers
2171                 for (i = this.containers.length - 1; i >= 0; i--){
2172                         if(!noPropagation) {
2173                                 delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
2174                         }
2175                         if(this.containers[i].containerCache.over) {
2176                                 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
2177                                 this.containers[i].containerCache.over = 0;
2178                         }
2179                 }
2180
2181                 //Do what was originally in plugins
2182                 if ( this.storedCursor ) {
2183                         this.document.find( "body" ).css( "cursor", this.storedCursor );
2184                         this.storedStylesheet.remove();
2185                 }
2186                 if(this._storedOpacity) {
2187                         this.helper.css("opacity", this._storedOpacity);
2188                 }
2189                 if(this._storedZIndex) {
2190                         this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex);
2191                 }
2192
2193                 this.dragging = false;
2194                 if(this.cancelHelperRemoval) {
2195                         if(!noPropagation) {
2196                                 this._trigger("beforeStop", event, this._uiHash());
2197                                 for (i=0; i < delayedTriggers.length; i++) {
2198                                         delayedTriggers[i].call(this, event);
2199                                 } //Trigger all delayed events
2200                                 this._trigger("stop", event, this._uiHash());
2201                         }
2202
2203                         this.fromOutside = false;
2204                         return false;
2205                 }
2206
2207                 if(!noPropagation) {
2208                         this._trigger("beforeStop", event, this._uiHash());
2209                 }
2210
2211                 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
2212                 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
2213
2214                 if(this.helper[0] !== this.currentItem[0]) {
2215                         this.helper.remove();
2216                 }
2217                 this.helper = null;
2218
2219                 if(!noPropagation) {
2220                         for (i=0; i < delayedTriggers.length; i++) {
2221                                 delayedTriggers[i].call(this, event);
2222                         } //Trigger all delayed events
2223                         this._trigger("stop", event, this._uiHash());
2224                 }
2225
2226                 this.fromOutside = false;
2227                 return true;
2228
2229         },
2230
2231         _trigger: function() {
2232                 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
2233                         this.cancel();
2234                 }
2235         },
2236
2237         _uiHash: function(_inst) {
2238                 var inst = _inst || this;
2239                 return {
2240                         helper: inst.helper,
2241                         placeholder: inst.placeholder || $([]),
2242                         position: inst.position,
2243                         originalPosition: inst.originalPosition,
2244                         offset: inst.positionAbs,
2245                         item: inst.currentItem,
2246                         sender: _inst ? _inst.element : null
2247                 };
2248         }
2249
2250 });
2251
2252 })(jQuery);
2253 (function( $, undefined ) {
2254
2255 var uid = 0,
2256         hideProps = {},
2257         showProps = {};
2258
2259 hideProps.height = hideProps.paddingTop = hideProps.paddingBottom =
2260         hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide";
2261 showProps.height = showProps.paddingTop = showProps.paddingBottom =
2262         showProps.borderTopWidth = showProps.borderBottomWidth = "show";
2263
2264 $.widget( "ui.accordion", {
2265         version: "1.10.3",
2266         options: {
2267                 active: 0,
2268                 animate: {},
2269                 collapsible: false,
2270                 event: "click",
2271                 header: "> li > :first-child,> :not(li):even",
2272                 heightStyle: "auto",
2273                 icons: {
2274                         activeHeader: "ui-icon-triangle-1-s",
2275                         header: "ui-icon-triangle-1-e"
2276                 },
2277
2278                 // callbacks
2279                 activate: null,
2280                 beforeActivate: null
2281         },
2282
2283         _create: function() {
2284                 var options = this.options;
2285                 this.prevShow = this.prevHide = $();
2286                 this.element.addClass( "ui-accordion ui-widget ui-helper-reset" )
2287                         // ARIA
2288                         .attr( "role", "tablist" );
2289
2290                 // don't allow collapsible: false and active: false / null
2291                 if ( !options.collapsible && (options.active === false || options.active == null) ) {
2292                         options.active = 0;
2293                 }
2294
2295                 this._processPanels();
2296                 // handle negative values
2297                 if ( options.active < 0 ) {
2298                         options.active += this.headers.length;
2299                 }
2300                 this._refresh();
2301         },
2302
2303         _getCreateEventData: function() {
2304                 return {
2305                         header: this.active,
2306                         panel: !this.active.length ? $() : this.active.next(),
2307                         content: !this.active.length ? $() : this.active.next()
2308                 };
2309         },
2310
2311         _createIcons: function() {
2312                 var icons = this.options.icons;
2313                 if ( icons ) {
2314                         $( "<span>" )
2315                                 .addClass( "ui-accordion-header-icon ui-icon " + icons.header )
2316                                 .prependTo( this.headers );
2317                         this.active.children( ".ui-accordion-header-icon" )
2318                                 .removeClass( icons.header )
2319                                 .addClass( icons.activeHeader );
2320                         this.headers.addClass( "ui-accordion-icons" );
2321                 }
2322         },
2323
2324         _destroyIcons: function() {
2325                 this.headers
2326                         .removeClass( "ui-accordion-icons" )
2327                         .children( ".ui-accordion-header-icon" )
2328                                 .remove();
2329         },
2330
2331         _destroy: function() {
2332                 var contents;
2333
2334                 // clean up main element
2335                 this.element
2336                         .removeClass( "ui-accordion ui-widget ui-helper-reset" )
2337                         .removeAttr( "role" );
2338
2339                 // clean up headers
2340                 this.headers
2341                         .removeClass( "ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
2342                         .removeAttr( "role" )
2343                         .removeAttr( "aria-selected" )
2344                         .removeAttr( "aria-controls" )
2345                         .removeAttr( "tabIndex" )
2346                         .each(function() {
2347                                 if ( /^ui-accordion/.test( this.id ) ) {
2348                                         this.removeAttribute( "id" );
2349                                 }
2350                         });
2351                 this._destroyIcons();
2352
2353                 // clean up content panels
2354                 contents = this.headers.next()
2355                         .css( "display", "" )
2356                         .removeAttr( "role" )
2357                         .removeAttr( "aria-expanded" )
2358                         .removeAttr( "aria-hidden" )
2359                         .removeAttr( "aria-labelledby" )
2360                         .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" )
2361                         .each(function() {
2362                                 if ( /^ui-accordion/.test( this.id ) ) {
2363                                         this.removeAttribute( "id" );
2364                                 }
2365                         });
2366                 if ( this.options.heightStyle !== "content" ) {
2367                         contents.css( "height", "" );
2368                 }
2369         },
2370
2371         _setOption: function( key, value ) {
2372                 if ( key === "active" ) {
2373                         // _activate() will handle invalid values and update this.options
2374                         this._activate( value );
2375                         return;
2376                 }
2377
2378                 if ( key === "event" ) {
2379                         if ( this.options.event ) {
2380                                 this._off( this.headers, this.options.event );
2381                         }
2382                         this._setupEvents( value );
2383                 }
2384
2385                 this._super( key, value );
2386
2387                 // setting collapsible: false while collapsed; open first panel
2388                 if ( key === "collapsible" && !value && this.options.active === false ) {
2389                         this._activate( 0 );
2390                 }
2391
2392                 if ( key === "icons" ) {
2393                         this._destroyIcons();
2394                         if ( value ) {
2395                                 this._createIcons();
2396                         }
2397                 }
2398
2399                 // #5332 - opacity doesn't cascade to positioned elements in IE
2400                 // so we need to add the disabled class to the headers and panels
2401                 if ( key === "disabled" ) {
2402                         this.headers.add( this.headers.next() )
2403                                 .toggleClass( "ui-state-disabled", !!value );
2404                 }
2405         },
2406
2407         _keydown: function( event ) {
2408                 /*jshint maxcomplexity:15*/
2409                 if ( event.altKey || event.ctrlKey ) {
2410                         return;
2411                 }
2412
2413                 var keyCode = $.ui.keyCode,
2414                         length = this.headers.length,
2415                         currentIndex = this.headers.index( event.target ),
2416                         toFocus = false;
2417
2418                 switch ( event.keyCode ) {
2419                         case keyCode.RIGHT:
2420                         case keyCode.DOWN:
2421                                 toFocus = this.headers[ ( currentIndex + 1 ) % length ];
2422                                 break;
2423                         case keyCode.LEFT:
2424                         case keyCode.UP:
2425                                 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
2426                                 break;
2427                         case keyCode.SPACE:
2428                         case keyCode.ENTER:
2429                                 this._eventHandler( event );
2430                                 break;
2431                         case keyCode.HOME:
2432                                 toFocus = this.headers[ 0 ];
2433                                 break;
2434                         case keyCode.END:
2435                                 toFocus = this.headers[ length - 1 ];
2436                                 break;
2437                 }
2438
2439                 if ( toFocus ) {
2440                         $( event.target ).attr( "tabIndex", -1 );
2441                         $( toFocus ).attr( "tabIndex", 0 );
2442                         toFocus.focus();
2443                         event.preventDefault();
2444                 }
2445         },
2446
2447         _panelKeyDown : function( event ) {
2448                 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
2449                         $( event.currentTarget ).prev().focus();
2450                 }
2451         },
2452
2453         refresh: function() {
2454                 var options = this.options;
2455                 this._processPanels();
2456
2457                 // was collapsed or no panel
2458                 if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) {
2459                         options.active = false;
2460                         this.active = $();
2461                 // active false only when collapsible is true
2462                 } else if ( options.active === false ) {
2463                         this._activate( 0 );
2464                 // was active, but active panel is gone
2465                 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
2466                         // all remaining panel are disabled
2467                         if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) {
2468                                 options.active = false;
2469                                 this.active = $();
2470                         // activate previous panel
2471                         } else {
2472                                 this._activate( Math.max( 0, options.active - 1 ) );
2473                         }
2474                 // was active, active panel still exists
2475                 } else {
2476                         // make sure active index is correct
2477                         options.active = this.headers.index( this.active );
2478                 }
2479
2480                 this._destroyIcons();
2481
2482                 this._refresh();
2483         },
2484
2485         _processPanels: function() {
2486                 this.headers = this.element.find( this.options.header )
2487                         .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" );
2488
2489                 this.headers.next()
2490                         .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )
2491                         .filter(":not(.ui-accordion-content-active)")
2492                         .hide();
2493         },
2494
2495         _refresh: function() {
2496                 var maxHeight,
2497                         options = this.options,
2498                         heightStyle = options.heightStyle,
2499                         parent = this.element.parent(),
2500                         accordionId = this.accordionId = "ui-accordion-" +
2501                                 (this.element.attr( "id" ) || ++uid);
2502
2503                 this.active = this._findActive( options.active )
2504                         .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" )
2505                         .removeClass( "ui-corner-all" );
2506                 this.active.next()
2507                         .addClass( "ui-accordion-content-active" )
2508                         .show();
2509
2510                 this.headers
2511                         .attr( "role", "tab" )
2512                         .each(function( i ) {
2513                                 var header = $( this ),
2514                                         headerId = header.attr( "id" ),
2515                                         panel = header.next(),
2516                                         panelId = panel.attr( "id" );
2517                                 if ( !headerId ) {
2518                                         headerId = accordionId + "-header-" + i;
2519                                         header.attr( "id", headerId );
2520                                 }
2521                                 if ( !panelId ) {
2522                                         panelId = accordionId + "-panel-" + i;
2523                                         panel.attr( "id", panelId );
2524                                 }
2525                                 header.attr( "aria-controls", panelId );
2526                                 panel.attr( "aria-labelledby", headerId );
2527                         })
2528                         .next()
2529                                 .attr( "role", "tabpanel" );
2530
2531                 this.headers
2532                         .not( this.active )
2533                         .attr({
2534                                 "aria-selected": "false",
2535                                 tabIndex: -1
2536                         })
2537                         .next()
2538                                 .attr({
2539                                         "aria-expanded": "false",
2540                                         "aria-hidden": "true"
2541                                 })
2542                                 .hide();
2543
2544                 // make sure at least one header is in the tab order
2545                 if ( !this.active.length ) {
2546                         this.headers.eq( 0 ).attr( "tabIndex", 0 );
2547                 } else {
2548                         this.active.attr({
2549                                 "aria-selected": "true",
2550                                 tabIndex: 0
2551                         })
2552                         .next()
2553                                 .attr({
2554                                         "aria-expanded": "true",
2555                                         "aria-hidden": "false"
2556                                 });
2557                 }
2558
2559                 this._createIcons();
2560
2561                 this._setupEvents( options.event );
2562
2563                 if ( heightStyle === "fill" ) {
2564                         maxHeight = parent.height();
2565                         this.element.siblings( ":visible" ).each(function() {
2566                                 var elem = $( this ),
2567                                         position = elem.css( "position" );
2568
2569                                 if ( position === "absolute" || position === "fixed" ) {
2570                                         return;
2571                                 }
2572                                 maxHeight -= elem.outerHeight( true );
2573                         });
2574
2575                         this.headers.each(function() {
2576                                 maxHeight -= $( this ).outerHeight( true );
2577                         });
2578
2579                         this.headers.next()
2580                                 .each(function() {
2581                                         $( this ).height( Math.max( 0, maxHeight -
2582                                                 $( this ).innerHeight() + $( this ).height() ) );
2583                                 })
2584                                 .css( "overflow", "auto" );
2585                 } else if ( heightStyle === "auto" ) {
2586                         maxHeight = 0;
2587                         this.headers.next()
2588                                 .each(function() {
2589                                         maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
2590                                 })
2591                                 .height( maxHeight );
2592                 }
2593         },
2594
2595         _activate: function( index ) {
2596                 var active = this._findActive( index )[ 0 ];
2597
2598                 // trying to activate the already active panel
2599                 if ( active === this.active[ 0 ] ) {
2600                         return;
2601                 }
2602
2603                 // trying to collapse, simulate a click on the currently active header
2604                 active = active || this.active[ 0 ];
2605
2606                 this._eventHandler({
2607                         target: active,
2608                         currentTarget: active,
2609                         preventDefault: $.noop
2610                 });
2611         },
2612
2613         _findActive: function( selector ) {
2614                 return typeof selector === "number" ? this.headers.eq( selector ) : $();
2615         },
2616
2617         _setupEvents: function( event ) {
2618                 var events = {
2619                         keydown: "_keydown"
2620                 };
2621                 if ( event ) {
2622                         $.each( event.split(" "), function( index, eventName ) {
2623                                 events[ eventName ] = "_eventHandler";
2624                         });
2625                 }
2626
2627                 this._off( this.headers.add( this.headers.next() ) );
2628                 this._on( this.headers, events );
2629                 this._on( this.headers.next(), { keydown: "_panelKeyDown" });
2630                 this._hoverable( this.headers );
2631                 this._focusable( this.headers );
2632         },
2633
2634         _eventHandler: function( event ) {
2635                 var options = this.options,
2636                         active = this.active,
2637                         clicked = $( event.currentTarget ),
2638                         clickedIsActive = clicked[ 0 ] === active[ 0 ],
2639                         collapsing = clickedIsActive && options.collapsible,
2640                         toShow = collapsing ? $() : clicked.next(),
2641                         toHide = active.next(),
2642                         eventData = {
2643                                 oldHeader: active,
2644                                 oldPanel: toHide,
2645                                 newHeader: collapsing ? $() : clicked,
2646                                 newPanel: toShow
2647                         };
2648
2649                 event.preventDefault();
2650
2651                 if (
2652                                 // click on active header, but not collapsible
2653                                 ( clickedIsActive && !options.collapsible ) ||
2654                                 // allow canceling activation
2655                                 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
2656                         return;
2657                 }
2658
2659                 options.active = collapsing ? false : this.headers.index( clicked );
2660
2661                 // when the call to ._toggle() comes after the class changes
2662                 // it causes a very odd bug in IE 8 (see #6720)
2663                 this.active = clickedIsActive ? $() : clicked;
2664                 this._toggle( eventData );
2665
2666                 // switch classes
2667                 // corner classes on the previously active header stay after the animation
2668                 active.removeClass( "ui-accordion-header-active ui-state-active" );
2669                 if ( options.icons ) {
2670                         active.children( ".ui-accordion-header-icon" )
2671                                 .removeClass( options.icons.activeHeader )
2672                                 .addClass( options.icons.header );
2673                 }
2674
2675                 if ( !clickedIsActive ) {
2676                         clicked
2677                                 .removeClass( "ui-corner-all" )
2678                                 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );
2679                         if ( options.icons ) {
2680                                 clicked.children( ".ui-accordion-header-icon" )
2681                                         .removeClass( options.icons.header )
2682                                         .addClass( options.icons.activeHeader );
2683                         }
2684
2685                         clicked
2686                                 .next()
2687                                 .addClass( "ui-accordion-content-active" );
2688                 }
2689         },
2690
2691         _toggle: function( data ) {
2692                 var toShow = data.newPanel,
2693                         toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
2694
2695                 // handle activating a panel during the animation for another activation
2696                 this.prevShow.add( this.prevHide ).stop( true, true );
2697                 this.prevShow = toShow;
2698                 this.prevHide = toHide;
2699
2700                 if ( this.options.animate ) {
2701                         this._animate( toShow, toHide, data );
2702                 } else {
2703                         toHide.hide();
2704                         toShow.show();
2705                         this._toggleComplete( data );
2706                 }
2707
2708                 toHide.attr({
2709                         "aria-expanded": "false",
2710                         "aria-hidden": "true"
2711                 });
2712                 toHide.prev().attr( "aria-selected", "false" );
2713                 // if we're switching panels, remove the old header from the tab order
2714                 // if we're opening from collapsed state, remove the previous header from the tab order
2715                 // if we're collapsing, then keep the collapsing header in the tab order
2716                 if ( toShow.length && toHide.length ) {
2717                         toHide.prev().attr( "tabIndex", -1 );
2718                 } else if ( toShow.length ) {
2719                         this.headers.filter(function() {
2720                                 return $( this ).attr( "tabIndex" ) === 0;
2721                         })
2722                         .attr( "tabIndex", -1 );
2723                 }
2724
2725                 toShow
2726                         .attr({
2727                                 "aria-expanded": "true",
2728                                 "aria-hidden": "false"
2729                         })
2730                         .prev()
2731                                 .attr({
2732                                         "aria-selected": "true",
2733                                         tabIndex: 0
2734                                 });
2735         },
2736
2737         _animate: function( toShow, toHide, data ) {
2738                 var total, easing, duration,
2739                         that = this,
2740                         adjust = 0,
2741                         down = toShow.length &&
2742                                 ( !toHide.length || ( toShow.index() < toHide.index() ) ),
2743                         animate = this.options.animate || {},
2744                         options = down && animate.down || animate,
2745                         complete = function() {
2746                                 that._toggleComplete( data );
2747                         };
2748
2749                 if ( typeof options === "number" ) {
2750                         duration = options;
2751                 }
2752                 if ( typeof options === "string" ) {
2753                         easing = options;
2754                 }
2755                 // fall back from options to animation in case of partial down settings
2756                 easing = easing || options.easing || animate.easing;
2757                 duration = duration || options.duration || animate.duration;
2758
2759                 if ( !toHide.length ) {
2760                         return toShow.animate( showProps, duration, easing, complete );
2761                 }
2762                 if ( !toShow.length ) {
2763                         return toHide.animate( hideProps, duration, easing, complete );
2764                 }
2765
2766                 total = toShow.show().outerHeight();
2767                 toHide.animate( hideProps, {
2768                         duration: duration,
2769                         easing: easing,
2770                         step: function( now, fx ) {
2771                                 fx.now = Math.round( now );
2772                         }
2773                 });
2774                 toShow
2775                         .hide()
2776                         .animate( showProps, {
2777                                 duration: duration,
2778                                 easing: easing,
2779                                 complete: complete,
2780                                 step: function( now, fx ) {
2781                                         fx.now = Math.round( now );
2782                                         if ( fx.prop !== "height" ) {
2783                                                 adjust += fx.now;
2784                                         } else if ( that.options.heightStyle !== "content" ) {
2785                                                 fx.now = Math.round( total - toHide.outerHeight() - adjust );
2786                                                 adjust = 0;
2787                                         }
2788                                 }
2789                         });
2790         },
2791
2792         _toggleComplete: function( data ) {
2793                 var toHide = data.oldPanel;
2794
2795                 toHide
2796                         .removeClass( "ui-accordion-content-active" )
2797                         .prev()
2798                                 .removeClass( "ui-corner-top" )
2799                                 .addClass( "ui-corner-all" );
2800
2801                 // Work around for rendering bug in IE (#5421)
2802                 if ( toHide.length ) {
2803                         toHide.parent()[0].className = toHide.parent()[0].className;
2804                 }
2805
2806                 this._trigger( "activate", null, data );
2807         }
2808 });
2809
2810 })( jQuery );
2811 (function( $, undefined ) {
2812
2813 var tabId = 0,
2814         rhash = /#.*$/;
2815
2816 function getNextTabId() {
2817         return ++tabId;
2818 }
2819
2820 function isLocal( anchor ) {
2821         return anchor.hash.length > 1 &&
2822                 decodeURIComponent( anchor.href.replace( rhash, "" ) ) ===
2823                         decodeURIComponent( location.href.replace( rhash, "" ) );
2824 }
2825
2826 $.widget( "ui.tabs", {
2827         version: "1.10.3",
2828         delay: 300,
2829         options: {
2830                 active: null,
2831                 collapsible: false,
2832                 event: "click",
2833                 heightStyle: "content",
2834                 hide: null,
2835                 show: null,
2836
2837                 // callbacks
2838                 activate: null,
2839                 beforeActivate: null,
2840                 beforeLoad: null,
2841                 load: null
2842         },
2843
2844         _create: function() {
2845                 var that = this,
2846                         options = this.options;
2847
2848                 this.running = false;
2849
2850                 this.element
2851                         .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
2852                         .toggleClass( "ui-tabs-collapsible", options.collapsible )
2853                         // Prevent users from focusing disabled tabs via click
2854                         .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
2855                                 if ( $( this ).is( ".ui-state-disabled" ) ) {
2856                                         event.preventDefault();
2857                                 }
2858                         })
2859                         // support: IE <9
2860                         // Preventing the default action in mousedown doesn't prevent IE
2861                         // from focusing the element, so if the anchor gets focused, blur.
2862                         // We don't have to worry about focusing the previously focused
2863                         // element since clicking on a non-focusable element should focus
2864                         // the body anyway.
2865                         .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
2866                                 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
2867                                         this.blur();
2868                                 }
2869                         });
2870
2871                 this._processTabs();
2872                 options.active = this._initialActive();
2873
2874                 // Take disabling tabs via class attribute from HTML
2875                 // into account and update option properly.
2876                 if ( $.isArray( options.disabled ) ) {
2877                         options.disabled = $.unique( options.disabled.concat(
2878                                 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
2879                                         return that.tabs.index( li );
2880                                 })
2881                         ) ).sort();
2882                 }
2883
2884                 // check for length avoids error when initializing empty list
2885                 if ( this.options.active !== false && this.anchors.length ) {
2886                         this.active = this._findActive( options.active );
2887                 } else {
2888                         this.active = $();
2889                 }
2890
2891                 this._refresh();
2892
2893                 if ( this.active.length ) {
2894                         this.load( options.active );
2895                 }
2896         },
2897
2898         _initialActive: function() {
2899                 var active = this.options.active,
2900                         collapsible = this.options.collapsible,
2901                         locationHash = location.hash.substring( 1 );
2902
2903                 if ( active === null ) {
2904                         // check the fragment identifier in the URL
2905                         if ( locationHash ) {
2906                                 this.tabs.each(function( i, tab ) {
2907                                         if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
2908                                                 active = i;
2909                                                 return false;
2910                                         }
2911                                 });
2912                         }
2913
2914                         // check for a tab marked active via a class
2915                         if ( active === null ) {
2916                                 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
2917                         }
2918
2919                         // no active tab, set to false
2920                         if ( active === null || active === -1 ) {
2921                                 active = this.tabs.length ? 0 : false;
2922                         }
2923                 }
2924
2925                 // handle numbers: negative, out of range
2926                 if ( active !== false ) {
2927                         active = this.tabs.index( this.tabs.eq( active ) );
2928                         if ( active === -1 ) {
2929                                 active = collapsible ? false : 0;
2930                         }
2931                 }
2932
2933                 // don't allow collapsible: false and active: false
2934                 if ( !collapsible && active === false && this.anchors.length ) {
2935                         active = 0;
2936                 }
2937
2938                 return active;
2939         },
2940
2941         _getCreateEventData: function() {
2942                 return {
2943                         tab: this.active,
2944                         panel: !this.active.length ? $() : this._getPanelForTab( this.active )
2945                 };
2946         },
2947
2948         _tabKeydown: function( event ) {
2949                 /*jshint maxcomplexity:15*/
2950                 var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
2951                         selectedIndex = this.tabs.index( focusedTab ),
2952                         goingForward = true;
2953
2954                 if ( this._handlePageNav( event ) ) {
2955                         return;
2956                 }
2957
2958                 switch ( event.keyCode ) {
2959                         case $.ui.keyCode.RIGHT:
2960                         case $.ui.keyCode.DOWN:
2961                                 selectedIndex++;
2962                                 break;
2963                         case $.ui.keyCode.UP:
2964                         case $.ui.keyCode.LEFT:
2965                                 goingForward = false;
2966                                 selectedIndex--;
2967                                 break;
2968                         case $.ui.keyCode.END:
2969                                 selectedIndex = this.anchors.length - 1;
2970                                 break;
2971                         case $.ui.keyCode.HOME:
2972                                 selectedIndex = 0;
2973                                 break;
2974                         case $.ui.keyCode.SPACE:
2975                                 // Activate only, no collapsing
2976                                 event.preventDefault();
2977                                 clearTimeout( this.activating );
2978                                 this._activate( selectedIndex );
2979                                 return;
2980                         case $.ui.keyCode.ENTER:
2981                                 // Toggle (cancel delayed activation, allow collapsing)
2982                                 event.preventDefault();
2983                                 clearTimeout( this.activating );
2984                                 // Determine if we should collapse or activate
2985                                 this._activate( selectedIndex === this.options.active ? false : selectedIndex );
2986                                 return;
2987                         default:
2988                                 return;
2989                 }
2990
2991                 // Focus the appropriate tab, based on which key was pressed
2992                 event.preventDefault();
2993                 clearTimeout( this.activating );
2994                 selectedIndex = this._focusNextTab( selectedIndex, goingForward );
2995
2996                 // Navigating with control key will prevent automatic activation
2997                 if ( !event.ctrlKey ) {
2998                         // Update aria-selected immediately so that AT think the tab is already selected.
2999                         // Otherwise AT may confuse the user by stating that they need to activate the tab,
3000                         // but the tab will already be activated by the time the announcement finishes.
3001                         focusedTab.attr( "aria-selected", "false" );
3002                         this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
3003
3004                         this.activating = this._delay(function() {
3005                                 this.option( "active", selectedIndex );
3006                         }, this.delay );
3007                 }
3008         },
3009
3010         _panelKeydown: function( event ) {
3011                 if ( this._handlePageNav( event ) ) {
3012                         return;
3013                 }
3014
3015                 // Ctrl+up moves focus to the current tab
3016                 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
3017                         event.preventDefault();
3018                         this.active.focus();
3019                 }
3020         },
3021
3022         // Alt+page up/down moves focus to the previous/next tab (and activates)
3023         _handlePageNav: function( event ) {
3024                 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
3025                         this._activate( this._focusNextTab( this.options.active - 1, false ) );
3026                         return true;
3027                 }
3028                 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
3029                         this._activate( this._focusNextTab( this.options.active + 1, true ) );
3030                         return true;
3031                 }
3032         },
3033
3034         _findNextTab: function( index, goingForward ) {
3035                 var lastTabIndex = this.tabs.length - 1;
3036
3037                 function constrain() {
3038                         if ( index > lastTabIndex ) {
3039                                 index = 0;
3040                         }
3041                         if ( index < 0 ) {
3042                                 index = lastTabIndex;
3043                         }
3044                         return index;
3045                 }
3046
3047                 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
3048                         index = goingForward ? index + 1 : index - 1;
3049                 }
3050
3051                 return index;
3052         },
3053
3054         _focusNextTab: function( index, goingForward ) {
3055                 index = this._findNextTab( index, goingForward );
3056                 this.tabs.eq( index ).focus();
3057                 return index;
3058         },
3059
3060         _setOption: function( key, value ) {
3061                 if ( key === "active" ) {
3062                         // _activate() will handle invalid values and update this.options
3063                         this._activate( value );
3064                         return;
3065                 }
3066
3067                 if ( key === "disabled" ) {
3068                         // don't use the widget factory's disabled handling
3069                         this._setupDisabled( value );
3070                         return;
3071                 }
3072
3073                 this._super( key, value);
3074
3075                 if ( key === "collapsible" ) {
3076                         this.element.toggleClass( "ui-tabs-collapsible", value );
3077                         // Setting collapsible: false while collapsed; open first panel
3078                         if ( !value && this.options.active === false ) {
3079                                 this._activate( 0 );
3080                         }
3081                 }
3082
3083                 if ( key === "event" ) {
3084                         this._setupEvents( value );
3085                 }
3086
3087                 if ( key === "heightStyle" ) {
3088                         this._setupHeightStyle( value );
3089                 }
3090         },
3091
3092         _tabId: function( tab ) {
3093                 return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();
3094         },
3095
3096         _sanitizeSelector: function( hash ) {
3097                 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
3098         },
3099
3100         refresh: function() {
3101                 var options = this.options,
3102                         lis = this.tablist.children( ":has(a[href])" );
3103
3104                 // get disabled tabs from class attribute from HTML
3105                 // this will get converted to a boolean if needed in _refresh()
3106                 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
3107                         return lis.index( tab );
3108                 });
3109
3110                 this._processTabs();
3111
3112                 // was collapsed or no tabs
3113                 if ( options.active === false || !this.anchors.length ) {
3114                         options.active = false;
3115                         this.active = $();
3116                 // was active, but active tab is gone
3117                 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
3118                         // all remaining tabs are disabled
3119                         if ( this.tabs.length === options.disabled.length ) {
3120                                 options.active = false;
3121                                 this.active = $();
3122                         // activate previous tab
3123                         } else {
3124                                 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
3125                         }
3126                 // was active, active tab still exists
3127                 } else {
3128                         // make sure active index is correct
3129                         options.active = this.tabs.index( this.active );
3130                 }
3131
3132                 this._refresh();
3133         },
3134
3135         _refresh: function() {
3136                 this._setupDisabled( this.options.disabled );
3137                 this._setupEvents( this.options.event );
3138                 this._setupHeightStyle( this.options.heightStyle );
3139
3140                 this.tabs.not( this.active ).attr({
3141                         "aria-selected": "false",
3142                         tabIndex: -1
3143                 });
3144                 this.panels.not( this._getPanelForTab( this.active ) )
3145                         .hide()
3146                         .attr({
3147                                 "aria-expanded": "false",
3148                                 "aria-hidden": "true"
3149                         });
3150
3151                 // Make sure one tab is in the tab order
3152                 if ( !this.active.length ) {
3153                         this.tabs.eq( 0 ).attr( "tabIndex", 0 );
3154                 } else {
3155                         this.active
3156                                 .addClass( "ui-tabs-active ui-state-active" )
3157                                 .attr({
3158                                         "aria-selected": "true",
3159                                         tabIndex: 0
3160                                 });
3161                         this._getPanelForTab( this.active )
3162                                 .show()
3163                                 .attr({
3164                                         "aria-expanded": "true",
3165                                         "aria-hidden": "false"
3166                                 });
3167                 }
3168         },
3169
3170         _processTabs: function() {
3171                 var that = this;
3172
3173                 this.tablist = this._getList()
3174                         .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
3175                         .attr( "role", "tablist" );
3176
3177                 this.tabs = this.tablist.find( "> li:has(a[href])" )
3178                         .addClass( "ui-state-default ui-corner-top" )
3179                         .attr({
3180                                 role: "tab",
3181                                 tabIndex: -1
3182                         });
3183
3184                 this.anchors = this.tabs.map(function() {
3185                                 return $( "a", this )[ 0 ];
3186                         })
3187                         .addClass( "ui-tabs-anchor" )
3188                         .attr({
3189                                 role: "presentation",
3190                                 tabIndex: -1
3191                         });
3192
3193                 this.panels = $();
3194
3195                 this.anchors.each(function( i, anchor ) {
3196                         var selector, panel, panelId,
3197                                 anchorId = $( anchor ).uniqueId().attr( "id" ),
3198                                 tab = $( anchor ).closest( "li" ),
3199                                 originalAriaControls = tab.attr( "aria-controls" );
3200
3201                         // inline tab
3202                         if ( isLocal( anchor ) ) {
3203                                 selector = anchor.hash;
3204                                 panel = that.element.find( that._sanitizeSelector( selector ) );
3205                         // remote tab
3206                         } else {
3207                                 panelId = that._tabId( tab );
3208                                 selector = "#" + panelId;
3209                                 panel = that.element.find( selector );
3210                                 if ( !panel.length ) {
3211                                         panel = that._createPanel( panelId );
3212                                         panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
3213                                 }
3214                                 panel.attr( "aria-live", "polite" );
3215                         }
3216
3217                         if ( panel.length) {
3218                                 that.panels = that.panels.add( panel );
3219                         }
3220                         if ( originalAriaControls ) {
3221                                 tab.data( "ui-tabs-aria-controls", originalAriaControls );
3222                         }
3223                         tab.attr({
3224                                 "aria-controls": selector.substring( 1 ),
3225                                 "aria-labelledby": anchorId
3226                         });
3227                         panel.attr( "aria-labelledby", anchorId );
3228                 });
3229
3230                 this.panels
3231                         .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
3232                         .attr( "role", "tabpanel" );
3233         },
3234
3235         // allow overriding how to find the list for rare usage scenarios (#7715)
3236         _getList: function() {
3237                 return this.element.find( "ol,ul" ).eq( 0 );
3238         },
3239
3240         _createPanel: function( id ) {
3241                 return $( "<div>" )
3242                         .attr( "id", id )
3243                         .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
3244                         .data( "ui-tabs-destroy", true );
3245         },
3246
3247         _setupDisabled: function( disabled ) {
3248                 if ( $.isArray( disabled ) ) {
3249                         if ( !disabled.length ) {
3250                                 disabled = false;
3251                         } else if ( disabled.length === this.anchors.length ) {
3252                                 disabled = true;
3253                         }
3254                 }
3255
3256                 // disable tabs
3257                 for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
3258                         if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
3259                                 $( li )
3260                                         .addClass( "ui-state-disabled" )
3261                                         .attr( "aria-disabled", "true" );
3262                         } else {
3263                                 $( li )
3264                                         .removeClass( "ui-state-disabled" )
3265                                         .removeAttr( "aria-disabled" );
3266                         }
3267                 }
3268
3269                 this.options.disabled = disabled;
3270         },
3271
3272         _setupEvents: function( event ) {
3273                 var events = {
3274                         click: function( event ) {
3275                                 event.preventDefault();
3276                         }
3277                 };
3278                 if ( event ) {
3279                         $.each( event.split(" "), function( index, eventName ) {
3280                                 events[ eventName ] = "_eventHandler";
3281                         });
3282                 }
3283
3284                 this._off( this.anchors.add( this.tabs ).add( this.panels ) );
3285                 this._on( this.anchors, events );
3286                 this._on( this.tabs, { keydown: "_tabKeydown" } );
3287                 this._on( this.panels, { keydown: "_panelKeydown" } );
3288
3289                 this._focusable( this.tabs );
3290                 this._hoverable( this.tabs );
3291         },
3292
3293         _setupHeightStyle: function( heightStyle ) {
3294                 var maxHeight,
3295                         parent = this.element.parent();
3296
3297                 if ( heightStyle === "fill" ) {
3298                         maxHeight = parent.height();
3299                         maxHeight -= this.element.outerHeight() - this.element.height();
3300
3301                         this.element.siblings( ":visible" ).each(function() {
3302                                 var elem = $( this ),
3303                                         position = elem.css( "position" );
3304
3305                                 if ( position === "absolute" || position === "fixed" ) {
3306                                         return;
3307                                 }
3308                                 maxHeight -= elem.outerHeight( true );
3309                         });
3310
3311                         this.element.children().not( this.panels ).each(function() {
3312                                 maxHeight -= $( this ).outerHeight( true );
3313                         });
3314
3315                         this.panels.each(function() {
3316                                 $( this ).height( Math.max( 0, maxHeight -
3317                                         $( this ).innerHeight() + $( this ).height() ) );
3318                         })
3319                         .css( "overflow", "auto" );
3320                 } else if ( heightStyle === "auto" ) {
3321                         maxHeight = 0;
3322                         this.panels.each(function() {
3323                                 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
3324                         }).height( maxHeight );
3325                 }
3326         },
3327
3328         _eventHandler: function( event ) {
3329                 var options = this.options,
3330                         active = this.active,
3331                         anchor = $( event.currentTarget ),
3332                         tab = anchor.closest( "li" ),
3333                         clickedIsActive = tab[ 0 ] === active[ 0 ],
3334                         collapsing = clickedIsActive && options.collapsible,
3335                         toShow = collapsing ? $() : this._getPanelForTab( tab ),
3336                         toHide = !active.length ? $() : this._getPanelForTab( active ),
3337                         eventData = {
3338                                 oldTab: active,
3339                                 oldPanel: toHide,
3340                                 newTab: collapsing ? $() : tab,
3341                                 newPanel: toShow
3342                         };
3343
3344                 event.preventDefault();
3345
3346                 if ( tab.hasClass( "ui-state-disabled" ) ||
3347                                 // tab is already loading
3348                                 tab.hasClass( "ui-tabs-loading" ) ||
3349                                 // can't switch durning an animation
3350                                 this.running ||
3351                                 // click on active header, but not collapsible
3352                                 ( clickedIsActive && !options.collapsible ) ||
3353                                 // allow canceling activation
3354                                 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
3355                         return;
3356                 }
3357
3358                 options.active = collapsing ? false : this.tabs.index( tab );
3359
3360                 this.active = clickedIsActive ? $() : tab;
3361                 if ( this.xhr ) {
3362                         this.xhr.abort();
3363                 }
3364
3365                 if ( !toHide.length && !toShow.length ) {
3366                         $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
3367                 }
3368
3369                 if ( toShow.length ) {
3370                         this.load( this.tabs.index( tab ), event );
3371                 }
3372                 this._toggle( event, eventData );
3373         },
3374
3375         // handles show/hide for selecting tabs
3376         _toggle: function( event, eventData ) {
3377                 var that = this,
3378                         toShow = eventData.newPanel,
3379                         toHide = eventData.oldPanel;
3380
3381                 this.running = true;
3382
3383                 function complete() {
3384                         that.running = false;
3385                         that._trigger( "activate", event, eventData );
3386                 }
3387
3388                 function show() {
3389                         eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
3390
3391                         if ( toShow.length && that.options.show ) {
3392                                 that._show( toShow, that.options.show, complete );
3393                         } else {
3394                                 toShow.show();
3395                                 complete();
3396                         }
3397                 }
3398
3399                 // start out by hiding, then showing, then completing
3400                 if ( toHide.length && this.options.hide ) {
3401                         this._hide( toHide, this.options.hide, function() {
3402                                 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
3403                                 show();
3404                         });
3405                 } else {
3406                         eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
3407                         toHide.hide();
3408                         show();
3409                 }
3410
3411                 toHide.attr({
3412                         "aria-expanded": "false",
3413                         "aria-hidden": "true"
3414                 });
3415                 eventData.oldTab.attr( "aria-selected", "false" );
3416                 // If we're switching tabs, remove the old tab from the tab order.
3417                 // If we're opening from collapsed state, remove the previous tab from the tab order.
3418                 // If we're collapsing, then keep the collapsing tab in the tab order.
3419                 if ( toShow.length && toHide.length ) {
3420                         eventData.oldTab.attr( "tabIndex", -1 );
3421                 } else if ( toShow.length ) {
3422                         this.tabs.filter(function() {
3423                                 return $( this ).attr( "tabIndex" ) === 0;
3424                         })
3425                         .attr( "tabIndex", -1 );
3426                 }
3427
3428                 toShow.attr({
3429                         "aria-expanded": "true",
3430                         "aria-hidden": "false"
3431                 });
3432                 eventData.newTab.attr({
3433                         "aria-selected": "true",
3434                         tabIndex: 0
3435                 });
3436         },
3437
3438         _activate: function( index ) {
3439                 var anchor,
3440                         active = this._findActive( index );
3441
3442                 // trying to activate the already active panel
3443                 if ( active[ 0 ] === this.active[ 0 ] ) {
3444                         return;
3445                 }
3446
3447                 // trying to collapse, simulate a click on the current active header
3448                 if ( !active.length ) {
3449                         active = this.active;
3450                 }
3451
3452                 anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
3453                 this._eventHandler({
3454                         target: anchor,
3455                         currentTarget: anchor,
3456                         preventDefault: $.noop
3457                 });
3458         },
3459
3460         _findActive: function( index ) {
3461                 return index === false ? $() : this.tabs.eq( index );
3462         },
3463
3464         _getIndex: function( index ) {
3465                 // meta-function to give users option to provide a href string instead of a numerical index.
3466                 if ( typeof index === "string" ) {
3467                         index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
3468                 }
3469
3470                 return index;
3471         },
3472
3473         _destroy: function() {
3474                 if ( this.xhr ) {
3475                         this.xhr.abort();
3476                 }
3477
3478                 this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
3479
3480                 this.tablist
3481                         .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
3482                         .removeAttr( "role" );
3483
3484                 this.anchors
3485                         .removeClass( "ui-tabs-anchor" )
3486                         .removeAttr( "role" )
3487                         .removeAttr( "tabIndex" )
3488                         .removeUniqueId();
3489
3490                 this.tabs.add( this.panels ).each(function() {
3491                         if ( $.data( this, "ui-tabs-destroy" ) ) {
3492                                 $( this ).remove();
3493                         } else {
3494                                 $( this )
3495                                         .removeClass( "ui-state-default ui-state-active ui-state-disabled " +
3496                                                 "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
3497                                         .removeAttr( "tabIndex" )
3498                                         .removeAttr( "aria-live" )
3499                                         .removeAttr( "aria-busy" )
3500                                         .removeAttr( "aria-selected" )
3501                                         .removeAttr( "aria-labelledby" )
3502                                         .removeAttr( "aria-hidden" )
3503                                         .removeAttr( "aria-expanded" )
3504                                         .removeAttr( "role" );
3505                         }
3506                 });
3507
3508                 this.tabs.each(function() {
3509                         var li = $( this ),
3510                                 prev = li.data( "ui-tabs-aria-controls" );
3511                         if ( prev ) {
3512                                 li
3513                                         .attr( "aria-controls", prev )
3514                                         .removeData( "ui-tabs-aria-controls" );
3515                         } else {
3516                                 li.removeAttr( "aria-controls" );
3517                         }
3518                 });
3519
3520                 this.panels.show();
3521
3522                 if ( this.options.heightStyle !== "content" ) {
3523                         this.panels.css( "height", "" );
3524                 }
3525         },
3526
3527         enable: function( index ) {
3528                 var disabled = this.options.disabled;
3529                 if ( disabled === false ) {
3530                         return;
3531                 }
3532
3533                 if ( index === undefined ) {
3534                         disabled = false;
3535                 } else {
3536                         index = this._getIndex( index );
3537                         if ( $.isArray( disabled ) ) {
3538                                 disabled = $.map( disabled, function( num ) {
3539                                         return num !== index ? num : null;
3540                                 });
3541                         } else {
3542                                 disabled = $.map( this.tabs, function( li, num ) {
3543                                         return num !== index ? num : null;
3544                                 });
3545                         }
3546                 }
3547                 this._setupDisabled( disabled );
3548         },
3549
3550         disable: function( index ) {
3551                 var disabled = this.options.disabled;
3552                 if ( disabled === true ) {
3553                         return;
3554                 }
3555
3556                 if ( index === undefined ) {
3557                         disabled = true;
3558                 } else {
3559                         index = this._getIndex( index );
3560                         if ( $.inArray( index, disabled ) !== -1 ) {
3561                                 return;
3562                         }
3563                         if ( $.isArray( disabled ) ) {
3564                                 disabled = $.merge( [ index ], disabled ).sort();
3565                         } else {
3566                                 disabled = [ index ];
3567                         }
3568                 }
3569                 this._setupDisabled( disabled );
3570         },
3571
3572         load: function( index, event ) {
3573                 index = this._getIndex( index );
3574                 var that = this,
3575                         tab = this.tabs.eq( index ),
3576                         anchor = tab.find( ".ui-tabs-anchor" ),
3577                         panel = this._getPanelForTab( tab ),
3578                         eventData = {
3579                                 tab: tab,
3580                                 panel: panel
3581                         };
3582
3583                 // not remote
3584                 if ( isLocal( anchor[ 0 ] ) ) {
3585                         return;
3586                 }
3587
3588                 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
3589
3590                 // support: jQuery <1.8
3591                 // jQuery <1.8 returns false if the request is canceled in beforeSend,
3592                 // but as of 1.8, $.ajax() always returns a jqXHR object.
3593                 if ( this.xhr && this.xhr.statusText !== "canceled" ) {
3594                         tab.addClass( "ui-tabs-loading" );
3595                         panel.attr( "aria-busy", "true" );
3596
3597                         this.xhr
3598                                 .success(function( response ) {
3599                                         // support: jQuery <1.8
3600                                         // http://bugs.jquery.com/ticket/11778
3601                                         setTimeout(function() {
3602                                                 panel.html( response );
3603                                                 that._trigger( "load", event, eventData );
3604                                         }, 1 );
3605                                 })
3606                                 .complete(function( jqXHR, status ) {
3607                                         // support: jQuery <1.8
3608                                         // http://bugs.jquery.com/ticket/11778
3609                                         setTimeout(function() {
3610                                                 if ( status === "abort" ) {
3611                                                         that.panels.stop( false, true );
3612                                                 }
3613
3614                                                 tab.removeClass( "ui-tabs-loading" );
3615                                                 panel.removeAttr( "aria-busy" );
3616
3617                                                 if ( jqXHR === that.xhr ) {
3618                                                         delete that.xhr;
3619                                                 }
3620                                         }, 1 );
3621                                 });
3622                 }
3623         },
3624
3625         _ajaxSettings: function( anchor, event, eventData ) {
3626                 var that = this;
3627                 return {
3628                         url: anchor.attr( "href" ),
3629                         beforeSend: function( jqXHR, settings ) {
3630                                 return that._trigger( "beforeLoad", event,
3631                                         $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );
3632                         }
3633                 };
3634         },
3635
3636         _getPanelForTab: function( tab ) {
3637                 var id = $( tab ).attr( "aria-controls" );
3638                 return this.element.find( this._sanitizeSelector( "#" + id ) );
3639         }
3640 });
3641
3642 })( jQuery );