Getting 2nd click to close accordion element

I’ve modified the Filament Group’s jQuery Collapsible plugin so it would close any open elements when an new one is clicked to open. I’m using this plugin instead of the standard jQuery accordion because of how it handles accessibility issues.

But now, when a user clicks an already ‘open’ element to close it, the element closes momentarily & then opens again. Not the desired behavior. It appears that the ‘else’ statement that handles this is being incorrectly interpreted (or rather, I’m passing the wrong data).

here’s the section of the code before modification:

//events
collapsibleHeading	
	.bind('collapse', function(){
		$(this)
			.addClass('collapsible-heading-collapsed')
			.find('.collapsible-heading-status').text('Show ');
								
		collapsibleContent.slideUp(function(){
			$(this).addClass('collapsible-content-collapsed').removeAttr('style').attr('aria-hidden',true);
		});
	})
	.bind('expand', function(){
		$(this)
			.removeClass('collapsible-heading-collapsed')
			.find('.collapsible-heading-status').text('Hide ');
								
		collapsibleContent
			.slideDown(function(){
				$(this).removeClass('collapsible-content-collapsed').removeAttr('style').attr('aria-hidden',false);
			});
	})
	.click(function(){ 
		if( $(this).is('.collapsible-heading-collapsed') ){
			$(this).trigger('expand'); 
		}	
		else {
			$(this).trigger('collapse'); 
		}
		return false;
	})
	.trigger('collapse');

and after:

//events
collapsibleHeading	
	.bind('collapse', function(){
		$(this)
			.addClass('collapsible-heading-collapsed')
			.find('.collapsible-heading-status').text('Show ');
								
		collapsibleContent.slideUp(function(){
			$(this).addClass('collapsible-content-collapsed').removeAttr('style').attr('aria-hidden',true);
		});
	})
	.bind('expand', function(){
		$(this)
			.removeClass('collapsible-heading-collapsed')
			.find('.collapsible-heading-status').text('Hide ');
								
		collapsibleContent
			.slideDown(function(){
				$(this).removeClass('collapsible-content-collapsed').removeAttr('style').attr('aria-hidden',false);
			});
	})
	.click(function(){ //next 3 lines added by me to close expanded item when new item selected
		var collapseAll = $('.collapsible-heading');
		for (var i = 0; i < collapseAll.length; i++);
		collapseAll.trigger('collapse');
		{
			if( $(this).is('.collapsible-heading-collapsed') ){
				$(this).trigger('expand'); 
			}	
			else {
				$(this).trigger('collapse'); 
			}
			return false;
		}
	})
	.trigger('collapse');

and the html:

  <div id="faq">
    <h5 class="accordion">Details</h5>
    <ul>
      <li>purple-flower.tif purple-flower.tif purple-flower.tif</li>
      <li>flower-photos.zip flower-photos.zip flower-photos.zip</li>
    </ul>
    <h5 class="accordion">Details 2</h5>
    <ul>
      <li>purple-flower.tif</li>
      <li>flower-photos.zip</li>
    </ul>
    <h5 class="accordion">Details 3</h5>
    <ul>
      <li>purple-flower.tif</li>
      <li>flower-photos.zip</li>
    </ul>
  </div>

I know, why haven’t I asked this on the jQuery forum? I have, but the fact is, you guys are much more responsive & helpful.

Oh yeah, here’s the page where I’m trying to get this to work.

Thanks,

–cz

That was it – here’s the revised script (affected section only):

.click(function(){
	if( $(this).is('.collapsible-heading-collapsed') ){
	//next 3 lines added by me to close expanded item when new item selected
	var collapseAll = $('.collapsible-heading');
	for (var i = 0; i < collapseAll.length; i++);
	collapseAll.trigger('collapse');
		$(this).trigger('expand'); 
	}	
	else {
		$(this).trigger('collapse'); 
	}
	return false;
})
.trigger('collapse');

Thanks for the advice.

–cz

I can’t read jQuery, but there was an accordion script written in the JSLIve course. What they did there was make a collapseAll function, which was only called from inside the expand function.

So collapseAll had its own loop through all the elements and applied the collapse function to everything it looped though, and expand would first call collapseAll before doing what it did (in this case, they used both a class for collapse and a class for expand, instead of just adding and removing a collapse class).

If this makes sense as straight JS, it looks like this:
(html has a single ul with a class of “accordion” with the headers inside the li’s… and the li’s are getting the expand/collapsed classes… main Object is called Accordion):


collapse: function(fold) {
  //removes class of expanded;
  //adds class of collapsed;
},

collapseAll: function(accordion) {
  //gets a collection of li's called "folds";
  //loops through the "folds[i]";
  Accordion.collapse(folds[i]);
},

expand: function(fold) {
  Accordion.collapseAll(fold.parentNode); //everything collapsed now
  //removes class of collapsed on the item clicked;
  //adds class of expanded on the item clicked;
}

I think you can do exactly the same thing… so it’s just a matter of shuffling your functions around.