Logo
 

Collapsible Fieldsets jQuery plugin - Drupal Style

Drupal does a great job in using collapsible fieldsets.  But, wouldn't it be great to be able to use this jQuery feature on other sites?  Well, here's your plugin.  In this tutorial, we will build a simple page, and then enable the collapsible fieldset on it.


Well, let's get started. First, let's make a simple HTML page to start with.

	

Collapsible Fieldset - jQuery plugin

Cannot collapse me

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam in nisi magna. Pellentesque volutpat, enim et faucibus placerat, est lacus rutrum ante, sollicitudin lobortis massa sapien eget urna. Curabitur ac risus eget turpis blandit scelerisque. Nulla egestas mollis velit quis mattis. Morbi id dui venenatis nisi tincidunt tempor. Morbi libero erat, suscipit quis dictum nec, mattis quis lectus.

Can Collapse Me!

"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga.."

1914 translation by H. Rackham

"On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain."

You'll notice that the first fieldset has no class, while the second one has a class of collapsible. We will be using this later on. You'll also want to go ahead and include the javascript source file for jQuery.

The jQuery plugin

Now, let's take a look at the actual plugin. What makes it work? How's it do it? Well, let's find out!

$.fn.collapse = function() {
	return this.each(function() {
		$(this).find("legend").addClass('collapsible').click(function() {
			if ($(this).parent().hasClass('collapsed'))
				$(this).parent().removeClass('collapsed').addClass('collapsible');
	
			$(this).removeClass('collapsed');
	
			$(this).parent().children().not('legend').toggle("slow", function() {
			 
				 if ($(this).is(":visible"))
					$(this).parent().find("legend").addClass('collapsible');
				 else
					$(this).parent().addClass('collapsed').find("legend").addClass('collapsed');
			 });
		});
	});
};

Alright...jQuery makes it super easy to create your own functions, and add them right into the framework. The only thing that is required is the next line. This line of code ensures the ability for jQuery to chain together many functions. It allows you to do something like this:

$("p").css("color", "#0000FF").find("a").slideUp();

Now, I'm not sure why you would want to do a function like that, but you can if you include that line of code.

The third line of code selects the fieldset's legend, adds the class collapsible to it, and then creates the onclick function. Let's take a look at that...

if ($(this).parent().hasClass('collapsed'))
	$(this).parent().removeClass('collapsed').addClass('collapsible');

$(this).removeClass('collapsed');

This part of the code checks to see if the parent (the fieldset) is currently in the collapsed state. If so, go ahead and add the 'collapsible' class. Now, why are we doing this? This ensures that the fieldset borders will be shown (if you style it to do so) DURING the animation, and not just have them appear once it's done.

$(this).parent().children().not('legend').toggle("slow", function() {
 
	 if ($(this).is(":visible"))
		$(this).parent().find("legend").addClass('collapsible');
	 else
		$(this).parent().addClass('collapsed').find("legend").addClass('collapsed');
 });

This section of the code selects the fieldset, then its children, selects everything that is not the label, and then toggles it (does the animation of opening or closing). Now, if you notice that you are using an element not contained in this set, feel free to add it! Once the toggle is complete, the callback function is called to ensure the fieldset and legend are in their proper states. Pretty simple, huh?

The CSS

Now that we have our page and plugin, lets add some styling to it. I'm going to keep this VERY basic, but feel free to do whatever you want.

fieldset, fieldset.collapsible {
        padding: 10px;
        border: 1px solid black;
        border-bottom-width: 1px;
        border-left-width: 1px;
        border-right-width: 1px;
        margin-bottom: 1em;
}
fieldset.collapsed {
        border-bottom-width: 0;
        border-left-width: 0;
        border-right-width: 0;
        margin-bottom: 0;
        margin-left: 3px;
}

legend.collapsible {
        color: blue;
}
legend.collapsed {
        color:green;
}

Putting it all together

Now that we have the HTML, the plugin, and the CSS, let's put it all together, and make this thing work! All you have to do now is select the elements you want to collapse, and make them work! Here's a sample...

  

Now that you have your page, put it to work! Test it out! Let me know how it goes! Of course, this plugin currently doesn't have any configurable options. Feel free to let me know what you might want! I'll try to implement them as quickly as I can! Thanks!


UPDATE: Version 1.1 (and 2.1) have been released. The only change is the fieldset is now toggled using .not('label'), rather than .filter( ELEMENTS ). This will allow you to place anything you want in the fieldset, without having to limit to these elements. Thanks emichan for the tip!

UPDATE: I've added another version of the plugin below (v2.1). It allows you to initiate the fieldsets, and have certain ones closed. In order to do so, use something like this... (I've got the first line starting open, and the second line being closed. Just change the class for the fieldset).

	$(document).ready(function() {
		$("fieldset.collapsible").collapse();
		$("fieldset.collapsibleClosed").collapse( { closed : true } );
	});

UPDATE: Version 2.1.2 fixes an issue when nested fieldsets are used.

AttachmentSize
jquery.collapsible-v.2.1.2.js1.35 KB
jquery.collapsible-v.1.2.js968 bytes

Anonymous's picture
Nov 5, 2009
6:34 pm
Anthony

This demo works great however when I add this code to my JSP and I use the collapsible.js from above then I am getting a strange behavior. When the fieldset is open and I clik on the legend, it closes, reopens and then closes again. When I click on the closed fieldset it opens, closes and then reopens. Have you ever encountered this behavior? any ideas? Is the link to the collapsible.js file above pointing to the same file used in the demo?
Thank you,
Tony

mikesir87's picture
Nov 5, 2009
6:41 pm
mikesir87

@Tony I have never seen this happen before, and I've used it on several of my sites. The collapsible.js file has the same source code as the one in the demo. Are you sure you're only including the js file once? If you have it more than once, it could be triggering the click event a few times. What browser are you experiencing this in?

Anonymous's picture
Nov 6, 2009
5:13 pm
Anthony

Hi Michael,
I love your collapsible fieldsets. I have some that I wish to be initially closed upon pageload. Is this possible? Could you show how to implement this?
Thank you so much!
--Mike

Anonymous's picture
Nov 6, 2009
5:15 pm
Anthony

hi Michael,
Yes, I corrected that issue. I had somehow added the function three times to each fieldset. Doh! I'm not sure how but I have corrected it now and it works beautifully!
Is it possible to have the fieldset display closed initially?
Thank you,
Mike Anthony

mikesir87's picture
Nov 6, 2009
8:07 pm
mikesir87

Anthony,
I've made a revised version, and posted it as another attachment. It's the file labeled v2. At the end of the tutorial, I posted a little update on how to use it. The demo has also been updated to show this. If you want, I can extend this tutorial (probably make another one) that explains how I added the ability for options. Just let me know!
Thanks!

Anonymous's picture
Nov 21, 2009
4:29 am
makyaj yapma

Thanks for this plug-in

Anonymous's picture
Nov 23, 2009
1:40 pm
Ella Harrow

Thanks i was looking for this for my site.

Anonymous's picture
Nov 23, 2009
3:29 pm
emichan

Hi, thanks for posting this. Just a quick suggestion. Instead of

$(this).parent().children().filter("p,img,table,ul,div, /
span,h1,h2,h3,h4,h5").toggle("slow");

why not use

$(this).parent().children().not("label").toggle("slow");

?

It will save having to anticipate all of the possible tags one could put inside a fieldset.

HTH, Emi

mikesir87's picture
Nov 23, 2009
3:33 pm
mikesir87

Great suggestion! I'll update the scripts. However, I'll change it to $(this).parent().children().not('legend') Thanks for the tip though! :-)

Anonymous's picture
Dec 6, 2009
3:37 pm
emichan

Yes, haha, I meant legend - not label. :)

Anonymous's picture
Dec 2, 2009
12:12 pm
Luis Monroy

This is great information. Thanks so much for sharing. Its really gonna help me out!

Anonymous's picture
Jan 31, 2010
3:36 pm
spoetnik

Great plugin. Got it working, but found one glitch.
When i would like to have an easyslider (http://cssglobe.com/post/5780/easy-slider-17-numeric-navigation-jquery-s...) in a default collapsed fieldset, the slider stays 'display:none' This doesn't get update by the Collapsible Fieldset plugin.
Any suggestions?

mikesir87's picture
Jan 31, 2010
4:02 pm
mikesir87

Do you have a demo URL in which I can check out?

Anonymous's picture
Feb 1, 2010
12:15 pm
Lord Matt

I was able to get the initiated as closed to work by changing line 35 to

obj.children().not('legend').css('display', 'none');

As it stood it refused to start hidden.

However mixed text (not in anything else) images and form elements all seemed to become block elements or something including the a element which appeared to take up 100% of width and as you can imagine this looked messy.

The same thing happened while the fieldset was hiding the layout would deform.

I don't have a demo (actually I do but it is tucked behind a whole heap of security and is under development).

In the end I tired of ugly forms and removed everything so I could focus on getting everything else working. I'd love to have the time to get to the bottom of what was going on though.

mikesir87's picture
Feb 1, 2010
12:42 pm
mikesir87

Ahhh... I see. You are correct. I recently made the change on line 26, but didn't do it where you noticed. I've updated the script here, as well as the jQuery plugin repository.

For it to work correctly though, you will need to have some sort of wrapping element around it all (whether a div, span, p, etc.). Plain text will still appear (if not wrapped in anything), and I'm not too sure of a way around that (unless it creates an entirely new fieldset and legend, but that seems unnecessary). Let me know if you think of anything.

Anonymous's picture
Mar 2, 2010
2:03 pm
Vamshi

First of all Great Plugin! and thanks for sharing it!

I found a problem with this plugin,let me explain it as follows:

What if you have multiple field sets in one fieldset .

Parent1
Child1
Child2
Child3

When I collapse/un-collapse the child the parent collapses.

How can I avoid that ? Any thoughts

mikesir87's picture
Mar 2, 2010
2:38 pm
mikesir87

@Vamshi - nice catch! I've posted an updated version of the plugin, which should resolve the issue. Let me know if it works. It's version *.2

Anonymous's picture
Mar 3, 2010
2:20 pm
Vamshi

Awesome ! It works Gr8!

But when i collapse and un-collapse a fieldset the fields in it become distorted, and when i refresh it they will become normal.

Do you know what is causing it ?

mikesir87's picture
Mar 3, 2010
2:26 pm
mikesir87

What browser are you using? Do you have a demo or any screenshots?

Anonymous's picture
Mar 3, 2010
3:15 pm
Vamshi

When you collapse it the table inside the fieldset becomes:

When you un-collapse it the table inside the fieldset becomes:

I think that "block" thing is causing the problem

Anonymous's picture
Mar 3, 2010
3:17 pm
Vamshi

I am using Firefox , it works in IE 8 though

mikesir87's picture
Mar 3, 2010
4:09 pm
mikesir87

Well, the style="block" comes from jQuery itself because it is being shown again. I'm not too sure how to resolve this issue, as this is built-in into jQuery. There appear to be other people that are wondering this, looking at the API page for slideDown (http://api.jquery.com/slideDown/).

Post new comment

The content of this field is kept private and will not be shown publicly. If you have a Gravatar account, your avatar will be used.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
  • Syntax highlight code surrounded by the {syntaxhighlighter OPTIONS}...{/syntaxhighlighter} tags.

More information about formatting options

Search

Popular content

Twitter

RT @slashdot Cisco Introduces a 322 Tbit/sec. Router http://bit.ly/bUuB6v WOW!
58 followers

Places I Recommend