From 7a6dd71f8cf04d19c938f0678c0f2a2586ed65c5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Scott=20Gonz=C3=A1lez?= Date: Tue, 25 Jan 2011 00:52:42 -0500 Subject: [PATCH] Accordion: Allow canceling the beforeActivate event. Fixes #6896 - Accordion: Allow canceling the beforeActivate event. --- tests/unit/accordion/accordion_deprecated.js | 8 ++- tests/unit/accordion/accordion_events.js | 34 ++++++++++- ui/jquery.ui.accordion.js | 59 +++++++++++++------- 3 files changed, 79 insertions(+), 22 deletions(-) diff --git a/tests/unit/accordion/accordion_deprecated.js b/tests/unit/accordion/accordion_deprecated.js index 6f1c30562..07974e75e 100644 --- a/tests/unit/accordion/accordion_deprecated.js +++ b/tests/unit/accordion/accordion_deprecated.js @@ -228,7 +228,7 @@ test( "{ navigation: true, navigationFilter: content }", function() { module( "accordion (deprecated) - changestart/change events", accordionSetupTeardown() ); test( "changestart", function() { - expect( 20 ); + expect( 26 ); var ac = $( "#list1" ).accordion({ active: false, collapsible: true @@ -243,8 +243,10 @@ test( "changestart", function() { strictEqual( ui.newHeader[ 0 ], headers[ 0 ] ); equals( ui.newContent.size(), 1 ); strictEqual( ui.newContent[ 0 ], content[ 0 ] ); + state( ac, 0, 0, 0 ); }); ac.accordion( "option", "active", 0 ); + state( ac, 1, 0, 0 ); ac.one( "accordionchangestart", function( event, ui ) { equals( ui.oldHeader.size(), 1 ); @@ -255,8 +257,10 @@ test( "changestart", function() { strictEqual( ui.newHeader[ 0 ], headers[ 1 ] ); equals( ui.newContent.size(), 1 ); strictEqual( ui.newContent[ 0 ], content[ 1 ] ); + state( ac, 1, 0, 0 ); }); headers.eq( 1 ).click(); + state( ac, 0, 1, 0 ); ac.one( "accordionchangestart", function( event, ui ) { equals( ui.oldHeader.size(), 1 ); @@ -265,8 +269,10 @@ test( "changestart", function() { strictEqual( ui.oldContent[ 0 ], content[ 1 ] ); equals( ui.newHeader.size(), 0 ); equals( ui.newContent.size(), 0 ); + state( ac, 0, 1, 0 ); }); ac.accordion( "option", "active", false ); + state( ac, 0, 0, 0 ); }); test( "change", function() { diff --git a/tests/unit/accordion/accordion_events.js b/tests/unit/accordion/accordion_events.js index fd7391387..0b9f14706 100644 --- a/tests/unit/accordion/accordion_events.js +++ b/tests/unit/accordion/accordion_events.js @@ -3,7 +3,7 @@ module( "accordion: events", accordionSetupTeardown() ); test( "beforeActivate", function() { - expect( 20 ); + expect( 42 ); var ac = $( "#list1" ).accordion({ active: false, collapsible: true @@ -18,8 +18,10 @@ test( "beforeActivate", function() { strictEqual( ui.newHeader[ 0 ], headers[ 0 ] ); equals( ui.newContent.size(), 1 ); strictEqual( ui.newContent[ 0 ], content[ 0 ] ); + state( ac, 0, 0, 0 ); }); ac.accordion( "option", "active", 0 ); + state( ac, 1, 0, 0 ); ac.one( "accordionbeforeactivate", function( event, ui ) { equals( ui.oldHeader.size(), 1 ); @@ -30,8 +32,10 @@ test( "beforeActivate", function() { strictEqual( ui.newHeader[ 0 ], headers[ 1 ] ); equals( ui.newContent.size(), 1 ); strictEqual( ui.newContent[ 0 ], content[ 1 ] ); + state( ac, 1, 0, 0 ); }); headers.eq( 1 ).click(); + state( ac, 0, 1, 0 ); ac.one( "accordionbeforeactivate", function( event, ui ) { equals( ui.oldHeader.size(), 1 ); @@ -40,8 +44,36 @@ test( "beforeActivate", function() { strictEqual( ui.oldContent[ 0 ], content[ 1 ] ); equals( ui.newHeader.size(), 0 ); equals( ui.newContent.size(), 0 ); + state( ac, 0, 1, 0 ); }); ac.accordion( "option", "active", false ); + state( ac, 0, 0, 0 ); + + ac.one( "accordionbeforeactivate", function( event, ui ) { + equals( ui.oldHeader.size(), 0 ); + equals( ui.oldContent.size(), 0 ); + equals( ui.newHeader.size(), 1 ); + strictEqual( ui.newHeader[ 0 ], headers[ 1 ] ); + equals( ui.newContent.size(), 1 ); + strictEqual( ui.newContent[ 0 ], content[ 1 ] ); + event.preventDefault(); + state( ac, 0, 0, 0 ); + }); + ac.accordion( "option", "active", 1 ); + state( ac, 0, 0, 0 ); + + ac.one( "accordionbeforeactivate", function( event, ui ) { + equals( ui.oldHeader.size(), 0 ); + equals( ui.oldContent.size(), 0 ); + equals( ui.newHeader.size(), 1 ); + strictEqual( ui.newHeader[ 0 ], headers[ 2 ] ); + equals( ui.newContent.size(), 1 ); + strictEqual( ui.newContent[ 0 ], content[ 2 ] ); + event.preventDefault(); + state( ac, 0, 0, 0 ); + }); + headers.eq( 2 ).click(); + state( ac, 0, 0, 0 ); }); test( "activate", function() { diff --git a/ui/jquery.ui.accordion.js b/ui/jquery.ui.accordion.js index cd6a2ce93..85a47ddfb 100644 --- a/ui/jquery.ui.accordion.js +++ b/ui/jquery.ui.accordion.js @@ -284,6 +284,17 @@ $.widget( "ui.accordion", { return; } + // allow the activation to be canceled + var eventData = { + oldHeader: this.active, + oldContent: this.active.next(), + newHeader: $(), + newContent: $() + }; + if ( this._trigger( "beforeActivate", null, eventData ) === false ) { + return; + } + this.active .removeClass( "ui-state-active ui-corner-top" ) .addClass( "ui-state-default ui-corner-all" ) @@ -294,24 +305,34 @@ $.widget( "ui.accordion", { var toHide = this.active.next(), data = { options: this.options, - newHeader: $( [] ), + newHeader: $(), oldHeader: this.active, - newContent: $( [] ), + newContent: $(), oldContent: toHide }, - toShow = ( this.active = $( [] ) ); + toShow = ( this.active = $() ); this._toggle( toShow, toHide, data ); }, // TODO: add tests/docs for negative values in 2.0 (#6854) _findActive: function( selector ) { - return typeof selector === "number" ? this.headers.eq( selector ) : $( [] ); + return typeof selector === "number" ? this.headers.eq( selector ) : $(); }, _eventHandler: function( event ) { var options = this.options, + active = this.active, clicked = $( event.currentTarget ), - clickedIsActive = clicked[0] === this.active[0]; + clickedIsActive = clicked[ 0 ] === active[ 0 ], + collapsing = clickedIsActive && options.collapsible, + toShow = clicked.next(), + toHide = active.next(), + eventData = { + oldHeader: active, + oldContent: toHide, + newHeader: collapsing ? $() : clicked, + newContent: collapsing ? $() : toShow + }; event.preventDefault(); @@ -324,26 +345,26 @@ $.widget( "ui.accordion", { return; } - options.active = options.collapsible && clickedIsActive ? - false : - this.headers.index( clicked ); + // allow the activation to be canceled + if ( this._trigger( "beforeActivate", null, eventData ) === false ) { + return; + } + + options.active = collapsing ? false : this.headers.index( clicked ); // find elements to show and hide - var active = this.active, - toShow = clicked.next(), - toHide = this.active.next(), - data = { + var data = { options: options, - newHeader: clickedIsActive && options.collapsible ? $([]) : clicked, - oldHeader: this.active, - newContent: clickedIsActive && options.collapsible ? $([]) : toShow, + newHeader: collapsing ? $() : clicked, + oldHeader: active, + newContent: collapsing ? $() : toShow, oldContent: toHide }, - down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] ); + down = this.headers.index( active[0] ) > this.headers.index( clicked[0] ); // when the call to ._toggle() comes after the class changes // it causes a very odd bug in IE 8 (see #6720) - this.active = clickedIsActive ? $([]) : clicked; + this.active = clickedIsActive ? $() : clicked; this._toggle( toShow, toHide, data, clickedIsActive, down ); // switch classes @@ -381,8 +402,6 @@ $.widget( "ui.accordion", { return self._completed.apply( self, arguments ); }; - self._trigger( "beforeActivate", null, self.data ); - // count elements to animate self.running = toHide.size() === 0 ? toShow.size() : toHide.size(); @@ -391,7 +410,7 @@ $.widget( "ui.accordion", { if ( options.collapsible && clickedIsActive ) { animOptions = { - toShow: $( [] ), + toShow: $(), toHide: toHide, complete: complete, down: down, -- 2.39.5