Making an animated collapsible panel using Javascript

(Click here to view demo )

With the advent of Web 2.0 javascript is getting more importance than ever. It is the actual tool that makes much of the functionality needed for next generation webapps possible. With the advent of high speed internet and AJAX , the trend of making 'desktop-like' web applications has definitely picked up.Today there are many javascript toolkits and libraries offering fancy UI controls. So the question arises , why should I write my own ? I am no guru of javascript or basically anything. But I can very confidently say, when we use something ready-made we often don’t care for what lies inside. It is this knowledge that helps in achieving something distinct and even using the ready-made stuff more effectively!

Planning the Collapsible Panel Control

Our Collapsible panel will be a simple one, to start with. It will basically be a table with two rows. First row will show the title and second row shows the content. The second row will contain a tag that will actually host the content. There will a small icon to top-left, clicking on which it will collapse vertically. Collapsing action of control will be slow and will show progressive fading (opacity). When the user clicks on the icon again, the content will restore itself in the same manner. Now, ours will not be a resizable control. So it makes lot of sense to give it some predefined height. All controls on a page will have same height , which looks descent. Our panel will only be collapsible in vertical direction and will be fixed (non draggable). At this point there is lot of temptation to put additional features (like horizontal collapse action, drag-drop, variable height ....etc), but these are not really essential for making a descent control. Though it seems very easy to pack these functionalities into the control, there is a lot of code that requires to be written and written carefully. This will be made clear later on in this article. But one serious feature that cannot be ignored is, our collapsible panel should behave and work in all major browsers in the same way. So I would like to make a basic, but descent control which works on all major browsers (right now FireFox and IE).
 

Giving the proper looks

Our collapsible panel should look great, for people to use it. I am not the best of UI designers, but still I'll try my skills. I have made a separate CSS class, for each element and put it into a *.css file. The

widgetTable

class applies to the table as whole and gives it the dotted borders. The most important part of this class is width , which is specified in percentage. The

widgetTitle

, specifies two important properties, first is predefinied height and second is background image that gives the title bar its look. In the class

widgetTDContent

which is for the cell that will show the content, height is set to 0 pixel. This cell will contain a <DIV> tag which will host the actual content. Also note that widgetTDContent has no background color set. Most important is the

widgetDIV

class.It is here were height is hardcode as 180 pixels and overflow set to hidden.This will prevent ugly scroll bars showing up if the content size is more than the content area. Rest all styles are self explainatory. Click here for the StyleSheet.css file.

The Javascript

The is the most important part which gives life to our panel. If you are new to javascript then you might expect something complex here. The answer is yes and no.The javascript code to collapse and showing the panel is simple.Let us have a look at it.
var iHeight = 180 ;
var collapseStep = 10 ;
var aniSpeed = 2;

function minimisepanel(objDiv)
{
	var t =  parseInt( YAHOO.util.Dom.getStyle(objDiv,'height')); 
	YAHOO.util.Dom.setStyle(objDiv, 'opacity',t/iHeight);
	if(t>0)
	{	t=t-collapseStep ;
		if(t<=0){YAHOO.util.Dom.setStyle(objDiv, 'display','none');}
		YAHOO.util.Dom.setStyle(objDiv, 'height',t + 'px');
		setTimeout( "minimisepanel('"+objDiv+"');",aniSpeed);
	}
}

function maximisepanel(objDiv)
{
	YAHOO.util.Dom.setStyle(objDiv, 'display','block')
	var t = parseInt( YAHOO.util.Dom.getStyle(objDiv, 'height'));
	YAHOO.util.Dom.setStyle(objDiv, 'opacity',t/iHeight );
	if(t<=(iHeight-collapseStep))
	{	t=t+collapseStep ;
		YAHOO.util.Dom.setStyle(objDiv, 'height',t+'px');
		setTimeout( "maximisepanel('"+objDiv+"');",aniSpeed);
	}
}


function ShowHide(objID,imgref)
{
	if (YAHOO.util.Dom.getStyle(objID, 'display')=='block')
	{
	minimisepanel(objID);
	imgref.src="images/downarr.gif";
	return
	}
	
	maximisepanel(objID);
	imgref.src="images/uparr.gif";
}
Let us first see the function minimisepanel . In this function we first get height of the <DIV> tag to a temporary variable. Then it is decremented by collapseStep , which is 10 here . If after decrementing ,the height is equal to zero we , we make the <DIV> tag invisible or else me make it more translucent, by decreasing opacity , giving it a fading effect. The minimisepanel function is called recursively using setTimeout method in javascript , after time period specified by aniSpeed. The mazimisepanel function is similar. The showHide function takes the reference of image element and the <DIV> tag. Basically it toggles the behaviour by testing display property of <DIV> tag. If display was 'block' means grid is visible so minimise it ,else maximise it. Not here that it also changes the top-left icon.The javascript file can be downloaded from here .This function is called as follows:
<TABLE id=Table1 class="widgetTable" cellSpacing=0 cellPadding=0>
<TR><TD  class="widgetTitle">
<IMG onclick="ShowHide('mydiv',this)" src="images/uparr.gif" 
align=baseline valign="center">  <STRONG>Lonavala</STRONG></TD></TR>
<TR><TD class="widgetTdCotent"> 
<DIV  id="mydiv" class="widgetDIV"
<img src="images/kalra.jpg" align="left">	
The popular hill station near Mumbai.Lonavala is around 3 hours drive from 
Mumbai.Favourite destination of Mumbaikars to escape the city rush on weekends.
</DIV>
</TD></TR>
</TABLE>
So far so good.The above script does not look much complex. Notice the functions setStyle()and getStyle(). For setting height we could have used document.getElementById(el).style.whatever .. But , this doesn’t work when styles are defined in a *.css file.There is a workaround for this, here.There is one more problem, opacity.The way of setting this property is different in different browsers and browser versions.As stated above, making our panel work in IE and FireFox is our goal. It wont hurt if it worked well with other browsers as well. With newer versions of browsers coming up all the time and with different in DOMs , writing javascript that runs in most of them is not a simple task. At this point it makes a lot of sense, to use a popular javascript library. There are many advantages of using a library. Which one to use and to what extent , should depent on your need. Here , I have used the Yahoo! UI library available under BSD license for style modification functions and opacity handling. We are only using two functions from this library.You can also use readmade functions avaible on web , if you like. The question one might ask is , Yahoo UI library gives much pretty much what we want. So why not use it insetad of creating the panel ! The answer is, no library can offer 100% customization. Also at times they can add unnessary overhead , for simple tasks, like ours.The third reason is to learn how and why such libraries are made.

Doing More

So , our animated collapsible panel is ready for use. I have a demo running on my site here .You can use it in many different ways.So far we made a basic collapsible panel with little javascript . We also used third party libraries and understood their importance. What we have made actually works very well. In articles to come we will try to make it a 'true component' by using object oriented programming in javascript and understand its advantages. Then we will try some adventures with event handling for the improved control. Hope you enjoyed reading the article. Please send in your comments, suggestions and my mistakes.


Copyright (c) 2007-2017 Ashish Patil . Please read FAQ for more details.

comments powered by Disqus