@@ -96,16 +96,16 @@ $.widget( "ui.tabs", {
9696 this . lis . removeClass ( "ui-tabs-selected ui-state-active" ) ;
9797 // check for length avoids error when initializing empty list
9898 if ( o . active >= 0 && this . anchors . length ) {
99- var tab = self . anchors [ o . active ] ,
100- panel = self . element . find ( self . _sanitizeSelector ( $ ( tab ) . attr ( "aria-controls" ) ) ) ;
99+ this . active = this . _findActive ( o . active ) ;
100+ var panel = self . element . find ( self . _sanitizeSelector ( this . active . attr ( "aria-controls" ) ) ) ;
101101
102102 panel . removeClass ( "ui-tabs-hide" ) ;
103103
104104 this . lis . eq ( o . active ) . addClass ( "ui-tabs-selected ui-state-active" ) ;
105105
106106 // seems to be expected behavior that the activate callback is fired
107107 self . element . queue ( "tabs" , function ( ) {
108- self . _trigger ( "activate" , null , self . _ui ( tab , panel [ 0 ] ) ) ;
108+ self . _trigger ( "activate" , null , self . _ui ( self . active [ 0 ] , panel [ 0 ] ) ) ;
109109 } ) ;
110110
111111 this . load ( o . active ) ;
@@ -120,10 +120,9 @@ $.widget( "ui.tabs", {
120120
121121 _setOption : function ( key , value ) {
122122 if ( key == "active" ) {
123- if ( this . options . collapsible && value == this . options . active ) {
124- return ;
125- }
126- this . select ( value ) ;
123+ // _activate() will handle invalid values and update this.option
124+ this . _activate ( value ) ;
125+ return
127126 } else {
128127 this . options [ key ] = value ;
129128 this . refresh ( ) ;
@@ -350,10 +349,10 @@ $.widget( "ui.tabs", {
350349 event . preventDefault ( ) ;
351350 var self = this ,
352351 o = this . options ,
353- el = event . currentTarget ,
354- $li = $ ( el ) . closest ( "li" ) ,
352+ clicked = $ ( event . currentTarget ) ,
353+ $li = clicked . closest ( "li" ) ,
355354 $hide = self . panels . filter ( ":not(.ui-tabs-hide)" ) ,
356- $show = self . element . find ( self . _sanitizeSelector ( $ ( el ) . attr ( "aria-controls" ) ) ) ;
355+ $show = self . element . find ( self . _sanitizeSelector ( clicked . attr ( "aria-controls" ) ) ) ;
357356
358357 // tab is already selected, but not collapsible
359358 if ( ( $li . hasClass ( "ui-tabs-selected" ) && ! o . collapsible ) ||
@@ -364,12 +363,14 @@ $.widget( "ui.tabs", {
364363 // tab is already loading
365364 $li . hasClass ( "ui-state-processing" ) ||
366365 // allow canceling by beforeActivate event
367- self . _trigger ( "beforeActivate" , event , self . _ui ( el , $show [ 0 ] ) ) === false ) {
368- el . blur ( ) ;
366+ self . _trigger ( "beforeActivate" , event , self . _ui ( clicked [ 0 ] , $show [ 0 ] ) ) === false ) {
367+ clicked [ 0 ] . blur ( ) ;
369368 return ;
370369 }
371370
372- o . active = self . anchors . index ( el ) ;
371+ o . active = self . anchors . index ( clicked ) ;
372+
373+ self . active = clicked ;
373374
374375 if ( self . xhr ) {
375376 self . xhr . abort ( ) ;
@@ -379,30 +380,31 @@ $.widget( "ui.tabs", {
379380 if ( o . collapsible ) {
380381 if ( $li . hasClass ( "ui-tabs-selected" ) ) {
381382 o . active = - 1 ;
383+ self . active = null ;
382384
383385 if ( o . cookie ) {
384386 self . _cookie ( o . active , o . cookie ) ;
385387 }
386388
387389 self . element . queue ( "tabs" , function ( ) {
388- self . _hideTab ( el , $hide ) ;
390+ self . _hideTab ( clicked , $hide ) ;
389391 } ) . dequeue ( "tabs" ) ;
390392
391- el . blur ( ) ;
393+ clicked [ 0 ] . blur ( ) ;
392394 return ;
393395 } else if ( ! $hide . length ) {
394396 if ( o . cookie ) {
395397 self . _cookie ( o . active , o . cookie ) ;
396398 }
397399
398400 self . element . queue ( "tabs" , function ( ) {
399- self . _showTab ( el , $show , event ) ;
401+ self . _showTab ( clicked , $show , event ) ;
400402 } ) ;
401403
402404 // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
403- self . load ( self . anchors . index ( el ) ) ;
405+ self . load ( self . anchors . index ( clicked ) ) ;
404406
405- el . blur ( ) ;
407+ clicked [ 0 ] . blur ( ) ;
406408 return ;
407409 }
408410 }
@@ -415,14 +417,14 @@ $.widget( "ui.tabs", {
415417 if ( $show . length ) {
416418 if ( $hide . length ) {
417419 self . element . queue ( "tabs" , function ( ) {
418- self . _hideTab ( el , $hide ) ;
420+ self . _hideTab ( clicked , $hide ) ;
419421 } ) ;
420422 }
421423 self . element . queue ( "tabs" , function ( ) {
422- self . _showTab ( el , $show , event ) ;
424+ self . _showTab ( clicked , $show , event ) ;
423425 } ) ;
424426
425- self . load ( self . anchors . index ( el ) ) ;
427+ self . load ( self . anchors . index ( clicked ) ) ;
426428 } else {
427429 throw "jQuery UI Tabs: Mismatching fragment identifier." ;
428430 }
@@ -432,8 +434,31 @@ $.widget( "ui.tabs", {
432434 // in modern browsers; blur() removes focus from address bar in Firefox
433435 // which can become a usability
434436 if ( $ . browser . msie ) {
435- el . blur ( ) ;
437+ clicked [ 0 ] . blur ( ) ;
438+ }
439+ } ,
440+
441+ _activate : function ( index ) {
442+ var active = this . _findActive ( index ) [ 0 ] ;
443+
444+ // trying to activate the already active panel
445+ if ( this . active && active === this . active [ 0 ] ) {
446+ return ;
436447 }
448+
449+ // trying to collapse, simulate a click on the current active header
450+ active = active || this . active ;
451+
452+ this . _eventHandler ( {
453+ target : active ,
454+ currentTarget : active ,
455+ preventDefault : $ . noop
456+ } ) ;
457+ } ,
458+
459+ _findActive : function ( selector ) {
460+ return typeof selector === "number" ? this . anchors . eq ( selector ) :
461+ typeof selector === "string" ? this . anchors . filter ( "[href$='" + selector + "']" ) : $ ( ) ;
437462 } ,
438463
439464 _getIndex : function ( index ) {
@@ -539,19 +564,6 @@ $.widget( "ui.tabs", {
539564 return this ;
540565 } ,
541566
542- select : function ( index ) {
543- index = this . _getIndex ( index ) ;
544- if ( index == - 1 ) {
545- if ( this . options . collapsible && this . options . active != - 1 ) {
546- index = this . options . active ;
547- } else {
548- return this ;
549- }
550- }
551- this . anchors . eq ( index ) . trigger ( this . options . event + ".tabs" ) ;
552- return this ;
553- } ,
554-
555567 load : function ( index ) {
556568 index = this . _getIndex ( index ) ;
557569 var self = this ,
@@ -834,7 +846,7 @@ if ( $.uiBackCompat !== false ) {
834846 // If selected tab was removed focus tab to the right or
835847 // in case the last tab was removed the tab to the left.
836848 if ( $li . hasClass ( "ui-tabs-selected" ) && this . anchors . length > 1 ) {
837- this . select ( index + ( index + 1 < this . anchors . length ? 1 : - 1 ) ) ;
849+ this . _activate ( index + ( index + 1 < this . anchors . length ? 1 : - 1 ) ) ;
838850 }
839851
840852 o . disabled = $ . map (
@@ -947,6 +959,21 @@ if ( $.uiBackCompat !== false ) {
947959 }
948960 } ;
949961 } ( jQuery , jQuery . ui . tabs . prototype ) ) ;
962+
963+ // select method
964+ ( function ( $ , prototype ) {
965+ prototype . select = function ( index ) {
966+ index = this . _getIndex ( index ) ;
967+ if ( index == - 1 ) {
968+ if ( this . options . collapsible && this . options . selected != - 1 ) {
969+ index = this . options . selected ;
970+ } else {
971+ return ;
972+ }
973+ }
974+ this . anchors . eq ( index ) . trigger ( this . options . event + ".tabs" ) ;
975+ } ;
976+ } ( jQuery , jQuery . ui . tabs . prototype ) ) ;
950977}
951978
952979} ) ( jQuery ) ;
0 commit comments