blob: 8bdb8467e958237f0fc4c3f3fd33414ca432a385 [file] [log] [blame]
srikanth116e6e82014-08-19 07:22:37 -07001/*! jQuery UI - v1.10.2 - 2013-04-05
2* http://jqueryui.com
3* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.tabs.js
4* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */
5
6(function( $, undefined ) {
7
8var 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.2",
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
123function 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
144function 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
175if ( !$( "<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
222if ( !$.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)
231if ( $( "<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 the proxy pattern 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
318var 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
829var tabId = 0,
830 rhash = /#.*$/;
831
832function getNextTabId() {
833 return ++tabId;
834}
835
836function isLocal( anchor ) {
837 return anchor.hash.length > 1 &&
838 decodeURIComponent( anchor.href.replace( rhash, "" ) ) ===
839 decodeURIComponent( location.href.replace( rhash, "" ) );
840}
841
842$.widget( "ui.tabs", {
843 version: "1.10.2",
844 delay: 300,
845 options: {
846 active: null,
847 collapsible: false,
848 event: "click",
849 heightStyle: "content",
850 hide: null,
851 show: null,
852
853 // callbacks
854 activate: null,
855 beforeActivate: null,
856 beforeLoad: null,
857 load: null
858 },
859
860 _create: function() {
861 var that = this,
862 options = this.options;
863
864 this.running = false;
865
866 this.element
867 .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
868 .toggleClass( "ui-tabs-collapsible", options.collapsible )
869 // Prevent users from focusing disabled tabs via click
870 .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
871 if ( $( this ).is( ".ui-state-disabled" ) ) {
872 event.preventDefault();
873 }
874 })
875 // support: IE <9
876 // Preventing the default action in mousedown doesn't prevent IE
877 // from focusing the element, so if the anchor gets focused, blur.
878 // We don't have to worry about focusing the previously focused
879 // element since clicking on a non-focusable element should focus
880 // the body anyway.
881 .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
882 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
883 this.blur();
884 }
885 });
886
887 this._processTabs();
888 options.active = this._initialActive();
889
890 // Take disabling tabs via class attribute from HTML
891 // into account and update option properly.
892 if ( $.isArray( options.disabled ) ) {
893 options.disabled = $.unique( options.disabled.concat(
894 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
895 return that.tabs.index( li );
896 })
897 ) ).sort();
898 }
899
900 // check for length avoids error when initializing empty list
901 if ( this.options.active !== false && this.anchors.length ) {
902 this.active = this._findActive( options.active );
903 } else {
904 this.active = $();
905 }
906
907 this._refresh();
908
909 if ( this.active.length ) {
910 this.load( options.active );
911 }
912 },
913
914 _initialActive: function() {
915 var active = this.options.active,
916 collapsible = this.options.collapsible,
917 locationHash = location.hash.substring( 1 );
918
919 if ( active === null ) {
920 // check the fragment identifier in the URL
921 if ( locationHash ) {
922 this.tabs.each(function( i, tab ) {
923 if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
924 active = i;
925 return false;
926 }
927 });
928 }
929
930 // check for a tab marked active via a class
931 if ( active === null ) {
932 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
933 }
934
935 // no active tab, set to false
936 if ( active === null || active === -1 ) {
937 active = this.tabs.length ? 0 : false;
938 }
939 }
940
941 // handle numbers: negative, out of range
942 if ( active !== false ) {
943 active = this.tabs.index( this.tabs.eq( active ) );
944 if ( active === -1 ) {
945 active = collapsible ? false : 0;
946 }
947 }
948
949 // don't allow collapsible: false and active: false
950 if ( !collapsible && active === false && this.anchors.length ) {
951 active = 0;
952 }
953
954 return active;
955 },
956
957 _getCreateEventData: function() {
958 return {
959 tab: this.active,
960 panel: !this.active.length ? $() : this._getPanelForTab( this.active )
961 };
962 },
963
964 _tabKeydown: function( event ) {
965 /*jshint maxcomplexity:15*/
966 var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
967 selectedIndex = this.tabs.index( focusedTab ),
968 goingForward = true;
969
970 if ( this._handlePageNav( event ) ) {
971 return;
972 }
973
974 switch ( event.keyCode ) {
975 case $.ui.keyCode.RIGHT:
976 case $.ui.keyCode.DOWN:
977 selectedIndex++;
978 break;
979 case $.ui.keyCode.UP:
980 case $.ui.keyCode.LEFT:
981 goingForward = false;
982 selectedIndex--;
983 break;
984 case $.ui.keyCode.END:
985 selectedIndex = this.anchors.length - 1;
986 break;
987 case $.ui.keyCode.HOME:
988 selectedIndex = 0;
989 break;
990 case $.ui.keyCode.SPACE:
991 // Activate only, no collapsing
992 event.preventDefault();
993 clearTimeout( this.activating );
994 this._activate( selectedIndex );
995 return;
996 case $.ui.keyCode.ENTER:
997 // Toggle (cancel delayed activation, allow collapsing)
998 event.preventDefault();
999 clearTimeout( this.activating );
1000 // Determine if we should collapse or activate
1001 this._activate( selectedIndex === this.options.active ? false : selectedIndex );
1002 return;
1003 default:
1004 return;
1005 }
1006
1007 // Focus the appropriate tab, based on which key was pressed
1008 event.preventDefault();
1009 clearTimeout( this.activating );
1010 selectedIndex = this._focusNextTab( selectedIndex, goingForward );
1011
1012 // Navigating with control key will prevent automatic activation
1013 if ( !event.ctrlKey ) {
1014 // Update aria-selected immediately so that AT think the tab is already selected.
1015 // Otherwise AT may confuse the user by stating that they need to activate the tab,
1016 // but the tab will already be activated by the time the announcement finishes.
1017 focusedTab.attr( "aria-selected", "false" );
1018 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
1019
1020 this.activating = this._delay(function() {
1021 this.option( "active", selectedIndex );
1022 }, this.delay );
1023 }
1024 },
1025
1026 _panelKeydown: function( event ) {
1027 if ( this._handlePageNav( event ) ) {
1028 return;
1029 }
1030
1031 // Ctrl+up moves focus to the current tab
1032 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
1033 event.preventDefault();
1034 this.active.focus();
1035 }
1036 },
1037
1038 // Alt+page up/down moves focus to the previous/next tab (and activates)
1039 _handlePageNav: function( event ) {
1040 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
1041 this._activate( this._focusNextTab( this.options.active - 1, false ) );
1042 return true;
1043 }
1044 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
1045 this._activate( this._focusNextTab( this.options.active + 1, true ) );
1046 return true;
1047 }
1048 },
1049
1050 _findNextTab: function( index, goingForward ) {
1051 var lastTabIndex = this.tabs.length - 1;
1052
1053 function constrain() {
1054 if ( index > lastTabIndex ) {
1055 index = 0;
1056 }
1057 if ( index < 0 ) {
1058 index = lastTabIndex;
1059 }
1060 return index;
1061 }
1062
1063 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
1064 index = goingForward ? index + 1 : index - 1;
1065 }
1066
1067 return index;
1068 },
1069
1070 _focusNextTab: function( index, goingForward ) {
1071 index = this._findNextTab( index, goingForward );
1072 this.tabs.eq( index ).focus();
1073 return index;
1074 },
1075
1076 _setOption: function( key, value ) {
1077 if ( key === "active" ) {
1078 // _activate() will handle invalid values and update this.options
1079 this._activate( value );
1080 return;
1081 }
1082
1083 if ( key === "disabled" ) {
1084 // don't use the widget factory's disabled handling
1085 this._setupDisabled( value );
1086 return;
1087 }
1088
1089 this._super( key, value);
1090
1091 if ( key === "collapsible" ) {
1092 this.element.toggleClass( "ui-tabs-collapsible", value );
1093 // Setting collapsible: false while collapsed; open first panel
1094 if ( !value && this.options.active === false ) {
1095 this._activate( 0 );
1096 }
1097 }
1098
1099 if ( key === "event" ) {
1100 this._setupEvents( value );
1101 }
1102
1103 if ( key === "heightStyle" ) {
1104 this._setupHeightStyle( value );
1105 }
1106 },
1107
1108 _tabId: function( tab ) {
1109 return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();
1110 },
1111
1112 _sanitizeSelector: function( hash ) {
1113 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
1114 },
1115
1116 refresh: function() {
1117 var options = this.options,
1118 lis = this.tablist.children( ":has(a[href])" );
1119
1120 // get disabled tabs from class attribute from HTML
1121 // this will get converted to a boolean if needed in _refresh()
1122 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
1123 return lis.index( tab );
1124 });
1125
1126 this._processTabs();
1127
1128 // was collapsed or no tabs
1129 if ( options.active === false || !this.anchors.length ) {
1130 options.active = false;
1131 this.active = $();
1132 // was active, but active tab is gone
1133 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
1134 // all remaining tabs are disabled
1135 if ( this.tabs.length === options.disabled.length ) {
1136 options.active = false;
1137 this.active = $();
1138 // activate previous tab
1139 } else {
1140 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
1141 }
1142 // was active, active tab still exists
1143 } else {
1144 // make sure active index is correct
1145 options.active = this.tabs.index( this.active );
1146 }
1147
1148 this._refresh();
1149 },
1150
1151 _refresh: function() {
1152 this._setupDisabled( this.options.disabled );
1153 this._setupEvents( this.options.event );
1154 this._setupHeightStyle( this.options.heightStyle );
1155
1156 this.tabs.not( this.active ).attr({
1157 "aria-selected": "false",
1158 tabIndex: -1
1159 });
1160 this.panels.not( this._getPanelForTab( this.active ) )
1161 .hide()
1162 .attr({
1163 "aria-expanded": "false",
1164 "aria-hidden": "true"
1165 });
1166
1167 // Make sure one tab is in the tab order
1168 if ( !this.active.length ) {
1169 this.tabs.eq( 0 ).attr( "tabIndex", 0 );
1170 } else {
1171 this.active
1172 .addClass( "ui-tabs-active ui-state-active" )
1173 .attr({
1174 "aria-selected": "true",
1175 tabIndex: 0
1176 });
1177 this._getPanelForTab( this.active )
1178 .show()
1179 .attr({
1180 "aria-expanded": "true",
1181 "aria-hidden": "false"
1182 });
1183 }
1184 },
1185
1186 _processTabs: function() {
1187 var that = this;
1188
1189 this.tablist = this._getList()
1190 .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
1191 .attr( "role", "tablist" );
1192
1193 this.tabs = this.tablist.find( "> li:has(a[href])" )
1194 .addClass( "ui-state-default ui-corner-top" )
1195 .attr({
1196 role: "tab",
1197 tabIndex: -1
1198 });
1199
1200 this.anchors = this.tabs.map(function() {
1201 return $( "a", this )[ 0 ];
1202 })
1203 .addClass( "ui-tabs-anchor" )
1204 .attr({
1205 role: "presentation",
1206 tabIndex: -1
1207 });
1208
1209 this.panels = $();
1210
1211 this.anchors.each(function( i, anchor ) {
1212 var selector, panel, panelId,
1213 anchorId = $( anchor ).uniqueId().attr( "id" ),
1214 tab = $( anchor ).closest( "li" ),
1215 originalAriaControls = tab.attr( "aria-controls" );
1216
1217 // inline tab
1218 if ( isLocal( anchor ) ) {
1219 selector = anchor.hash;
1220 panel = that.element.find( that._sanitizeSelector( selector ) );
1221 // remote tab
1222 } else {
1223 panelId = that._tabId( tab );
1224 selector = "#" + panelId;
1225 panel = that.element.find( selector );
1226 if ( !panel.length ) {
1227 panel = that._createPanel( panelId );
1228 panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
1229 }
1230 panel.attr( "aria-live", "polite" );
1231 }
1232
1233 if ( panel.length) {
1234 that.panels = that.panels.add( panel );
1235 }
1236 if ( originalAriaControls ) {
1237 tab.data( "ui-tabs-aria-controls", originalAriaControls );
1238 }
1239 tab.attr({
1240 "aria-controls": selector.substring( 1 ),
1241 "aria-labelledby": anchorId
1242 });
1243 panel.attr( "aria-labelledby", anchorId );
1244 });
1245
1246 this.panels
1247 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
1248 .attr( "role", "tabpanel" );
1249 },
1250
1251 // allow overriding how to find the list for rare usage scenarios (#7715)
1252 _getList: function() {
1253 return this.element.find( "ol,ul" ).eq( 0 );
1254 },
1255
1256 _createPanel: function( id ) {
1257 return $( "<div>" )
1258 .attr( "id", id )
1259 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
1260 .data( "ui-tabs-destroy", true );
1261 },
1262
1263 _setupDisabled: function( disabled ) {
1264 if ( $.isArray( disabled ) ) {
1265 if ( !disabled.length ) {
1266 disabled = false;
1267 } else if ( disabled.length === this.anchors.length ) {
1268 disabled = true;
1269 }
1270 }
1271
1272 // disable tabs
1273 for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
1274 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
1275 $( li )
1276 .addClass( "ui-state-disabled" )
1277 .attr( "aria-disabled", "true" );
1278 } else {
1279 $( li )
1280 .removeClass( "ui-state-disabled" )
1281 .removeAttr( "aria-disabled" );
1282 }
1283 }
1284
1285 this.options.disabled = disabled;
1286 },
1287
1288 _setupEvents: function( event ) {
1289 var events = {
1290 click: function( event ) {
1291 event.preventDefault();
1292 }
1293 };
1294 if ( event ) {
1295 $.each( event.split(" "), function( index, eventName ) {
1296 events[ eventName ] = "_eventHandler";
1297 });
1298 }
1299
1300 this._off( this.anchors.add( this.tabs ).add( this.panels ) );
1301 this._on( this.anchors, events );
1302 this._on( this.tabs, { keydown: "_tabKeydown" } );
1303 this._on( this.panels, { keydown: "_panelKeydown" } );
1304
1305 this._focusable( this.tabs );
1306 this._hoverable( this.tabs );
1307 },
1308
1309 _setupHeightStyle: function( heightStyle ) {
1310 var maxHeight,
1311 parent = this.element.parent();
1312
1313 if ( heightStyle === "fill" ) {
1314 maxHeight = parent.height();
1315 maxHeight -= this.element.outerHeight() - this.element.height();
1316
1317 this.element.siblings( ":visible" ).each(function() {
1318 var elem = $( this ),
1319 position = elem.css( "position" );
1320
1321 if ( position === "absolute" || position === "fixed" ) {
1322 return;
1323 }
1324 maxHeight -= elem.outerHeight( true );
1325 });
1326
1327 this.element.children().not( this.panels ).each(function() {
1328 maxHeight -= $( this ).outerHeight( true );
1329 });
1330
1331 this.panels.each(function() {
1332 $( this ).height( Math.max( 0, maxHeight -
1333 $( this ).innerHeight() + $( this ).height() ) );
1334 })
1335 .css( "overflow", "auto" );
1336 } else if ( heightStyle === "auto" ) {
1337 maxHeight = 0;
1338 this.panels.each(function() {
1339 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
1340 }).height( maxHeight );
1341 }
1342 },
1343
1344 _eventHandler: function( event ) {
1345 var options = this.options,
1346 active = this.active,
1347 anchor = $( event.currentTarget ),
1348 tab = anchor.closest( "li" ),
1349 clickedIsActive = tab[ 0 ] === active[ 0 ],
1350 collapsing = clickedIsActive && options.collapsible,
1351 toShow = collapsing ? $() : this._getPanelForTab( tab ),
1352 toHide = !active.length ? $() : this._getPanelForTab( active ),
1353 eventData = {
1354 oldTab: active,
1355 oldPanel: toHide,
1356 newTab: collapsing ? $() : tab,
1357 newPanel: toShow
1358 };
1359
1360 event.preventDefault();
1361
1362 if ( tab.hasClass( "ui-state-disabled" ) ||
1363 // tab is already loading
1364 tab.hasClass( "ui-tabs-loading" ) ||
1365 // can't switch durning an animation
1366 this.running ||
1367 // click on active header, but not collapsible
1368 ( clickedIsActive && !options.collapsible ) ||
1369 // allow canceling activation
1370 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
1371 return;
1372 }
1373
1374 options.active = collapsing ? false : this.tabs.index( tab );
1375
1376 this.active = clickedIsActive ? $() : tab;
1377 if ( this.xhr ) {
1378 this.xhr.abort();
1379 }
1380
1381 if ( !toHide.length && !toShow.length ) {
1382 $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
1383 }
1384
1385 if ( toShow.length ) {
1386 this.load( this.tabs.index( tab ), event );
1387 }
1388 this._toggle( event, eventData );
1389 },
1390
1391 // handles show/hide for selecting tabs
1392 _toggle: function( event, eventData ) {
1393 var that = this,
1394 toShow = eventData.newPanel,
1395 toHide = eventData.oldPanel;
1396
1397 this.running = true;
1398
1399 function complete() {
1400 that.running = false;
1401 that._trigger( "activate", event, eventData );
1402 }
1403
1404 function show() {
1405 eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
1406
1407 if ( toShow.length && that.options.show ) {
1408 that._show( toShow, that.options.show, complete );
1409 } else {
1410 toShow.show();
1411 complete();
1412 }
1413 }
1414
1415 // start out by hiding, then showing, then completing
1416 if ( toHide.length && this.options.hide ) {
1417 this._hide( toHide, this.options.hide, function() {
1418 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
1419 show();
1420 });
1421 } else {
1422 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
1423 toHide.hide();
1424 show();
1425 }
1426
1427 toHide.attr({
1428 "aria-expanded": "false",
1429 "aria-hidden": "true"
1430 });
1431 eventData.oldTab.attr( "aria-selected", "false" );
1432 // If we're switching tabs, remove the old tab from the tab order.
1433 // If we're opening from collapsed state, remove the previous tab from the tab order.
1434 // If we're collapsing, then keep the collapsing tab in the tab order.
1435 if ( toShow.length && toHide.length ) {
1436 eventData.oldTab.attr( "tabIndex", -1 );
1437 } else if ( toShow.length ) {
1438 this.tabs.filter(function() {
1439 return $( this ).attr( "tabIndex" ) === 0;
1440 })
1441 .attr( "tabIndex", -1 );
1442 }
1443
1444 toShow.attr({
1445 "aria-expanded": "true",
1446 "aria-hidden": "false"
1447 });
1448 eventData.newTab.attr({
1449 "aria-selected": "true",
1450 tabIndex: 0
1451 });
1452 },
1453
1454 _activate: function( index ) {
1455 var anchor,
1456 active = this._findActive( index );
1457
1458 // trying to activate the already active panel
1459 if ( active[ 0 ] === this.active[ 0 ] ) {
1460 return;
1461 }
1462
1463 // trying to collapse, simulate a click on the current active header
1464 if ( !active.length ) {
1465 active = this.active;
1466 }
1467
1468 anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
1469 this._eventHandler({
1470 target: anchor,
1471 currentTarget: anchor,
1472 preventDefault: $.noop
1473 });
1474 },
1475
1476 _findActive: function( index ) {
1477 return index === false ? $() : this.tabs.eq( index );
1478 },
1479
1480 _getIndex: function( index ) {
1481 // meta-function to give users option to provide a href string instead of a numerical index.
1482 if ( typeof index === "string" ) {
1483 index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
1484 }
1485
1486 return index;
1487 },
1488
1489 _destroy: function() {
1490 if ( this.xhr ) {
1491 this.xhr.abort();
1492 }
1493
1494 this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
1495
1496 this.tablist
1497 .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
1498 .removeAttr( "role" );
1499
1500 this.anchors
1501 .removeClass( "ui-tabs-anchor" )
1502 .removeAttr( "role" )
1503 .removeAttr( "tabIndex" )
1504 .removeUniqueId();
1505
1506 this.tabs.add( this.panels ).each(function() {
1507 if ( $.data( this, "ui-tabs-destroy" ) ) {
1508 $( this ).remove();
1509 } else {
1510 $( this )
1511 .removeClass( "ui-state-default ui-state-active ui-state-disabled " +
1512 "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
1513 .removeAttr( "tabIndex" )
1514 .removeAttr( "aria-live" )
1515 .removeAttr( "aria-busy" )
1516 .removeAttr( "aria-selected" )
1517 .removeAttr( "aria-labelledby" )
1518 .removeAttr( "aria-hidden" )
1519 .removeAttr( "aria-expanded" )
1520 .removeAttr( "role" );
1521 }
1522 });
1523
1524 this.tabs.each(function() {
1525 var li = $( this ),
1526 prev = li.data( "ui-tabs-aria-controls" );
1527 if ( prev ) {
1528 li
1529 .attr( "aria-controls", prev )
1530 .removeData( "ui-tabs-aria-controls" );
1531 } else {
1532 li.removeAttr( "aria-controls" );
1533 }
1534 });
1535
1536 this.panels.show();
1537
1538 if ( this.options.heightStyle !== "content" ) {
1539 this.panels.css( "height", "" );
1540 }
1541 },
1542
1543 enable: function( index ) {
1544 var disabled = this.options.disabled;
1545 if ( disabled === false ) {
1546 return;
1547 }
1548
1549 if ( index === undefined ) {
1550 disabled = false;
1551 } else {
1552 index = this._getIndex( index );
1553 if ( $.isArray( disabled ) ) {
1554 disabled = $.map( disabled, function( num ) {
1555 return num !== index ? num : null;
1556 });
1557 } else {
1558 disabled = $.map( this.tabs, function( li, num ) {
1559 return num !== index ? num : null;
1560 });
1561 }
1562 }
1563 this._setupDisabled( disabled );
1564 },
1565
1566 disable: function( index ) {
1567 var disabled = this.options.disabled;
1568 if ( disabled === true ) {
1569 return;
1570 }
1571
1572 if ( index === undefined ) {
1573 disabled = true;
1574 } else {
1575 index = this._getIndex( index );
1576 if ( $.inArray( index, disabled ) !== -1 ) {
1577 return;
1578 }
1579 if ( $.isArray( disabled ) ) {
1580 disabled = $.merge( [ index ], disabled ).sort();
1581 } else {
1582 disabled = [ index ];
1583 }
1584 }
1585 this._setupDisabled( disabled );
1586 },
1587
1588 load: function( index, event ) {
1589 index = this._getIndex( index );
1590 var that = this,
1591 tab = this.tabs.eq( index ),
1592 anchor = tab.find( ".ui-tabs-anchor" ),
1593 panel = this._getPanelForTab( tab ),
1594 eventData = {
1595 tab: tab,
1596 panel: panel
1597 };
1598
1599 // not remote
1600 if ( isLocal( anchor[ 0 ] ) ) {
1601 return;
1602 }
1603
1604 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
1605
1606 // support: jQuery <1.8
1607 // jQuery <1.8 returns false if the request is canceled in beforeSend,
1608 // but as of 1.8, $.ajax() always returns a jqXHR object.
1609 if ( this.xhr && this.xhr.statusText !== "canceled" ) {
1610 tab.addClass( "ui-tabs-loading" );
1611 panel.attr( "aria-busy", "true" );
1612
1613 this.xhr
1614 .success(function( response ) {
1615 // support: jQuery <1.8
1616 // http://bugs.jquery.com/ticket/11778
1617 setTimeout(function() {
1618 panel.html( response );
1619 that._trigger( "load", event, eventData );
1620 }, 1 );
1621 })
1622 .complete(function( jqXHR, status ) {
1623 // support: jQuery <1.8
1624 // http://bugs.jquery.com/ticket/11778
1625 setTimeout(function() {
1626 if ( status === "abort" ) {
1627 that.panels.stop( false, true );
1628 }
1629
1630 tab.removeClass( "ui-tabs-loading" );
1631 panel.removeAttr( "aria-busy" );
1632
1633 if ( jqXHR === that.xhr ) {
1634 delete that.xhr;
1635 }
1636 }, 1 );
1637 });
1638 }
1639 },
1640
1641 _ajaxSettings: function( anchor, event, eventData ) {
1642 var that = this;
1643 return {
1644 url: anchor.attr( "href" ),
1645 beforeSend: function( jqXHR, settings ) {
1646 return that._trigger( "beforeLoad", event,
1647 $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );
1648 }
1649 };
1650 },
1651
1652 _getPanelForTab: function( tab ) {
1653 var id = $( tab ).attr( "aria-controls" );
1654 return this.element.find( this._sanitizeSelector( "#" + id ) );
1655 }
1656});
1657
1658})( jQuery );