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
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.
| Attachment | Size |
|---|---|
| jquery.collapsible-v.2.1.2.js | 1.35 KB |
| jquery.collapsible-v.1.2.js | 968 bytes |




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
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?
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
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
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!
4:29 am
makyaj yapma
Thanks for this plug-in
1:40 pm
Ella Harrow
Thanks i was looking for this for my site.
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
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! :-)
3:37 pm
emichan
Yes, haha, I meant legend - not label. :)
12:12 pm
Luis Monroy
This is great information. Thanks so much for sharing. Its really gonna help me out!
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?
4:02 pm
mikesir87
Do you have a demo URL in which I can check out?
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.
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.
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
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
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 ?
2:26 pm
mikesir87
What browser are you using? Do you have a demo or any screenshots?
3:15 pm
Vamshi
When you collapse it the table inside the fieldset becomes:
3:17 pm
Vamshi
I am using Firefox , it works in IE 8 though
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