Prototype 'Accordion' Script

Saturday 16th May, 2009

A friend of mine was having trouble finding a simple to use effective accordion script to use on his website. After having a look around the web myself I found it really was difficult to track down a really basic yet useful script to achieve this effect.

Obviously there are some great implementations using script libraries such as jQuery, but I decided to write my own script for this a little proof of concept. (So bare in mind, this is far from complete).

There are several what you might call 'limitations' to this script at the moment. The user must explicitly set the height of each content area - not so useful for dynamic content. Also, the 'accordionStep' setting must be perfectly divisible by the height of each element, or they will not close up properly. However these are relatively simple things I may add in the future.

So here we go - for each 'accordion' element we need both a head area and a content area:

HTML

<div id="header1" onclick="runAccordion(this.id, 100)">&nbsp;</div>
<div id="content1" class="acc_content">&nbsp;</div>

Each header/content area should be numbered individually (header1 controls content1, header2 controls content2 etc).

The content area also needs some basic style attributes attached:

Style

.acc_content { height:0px; overflow:hidden; }

Each header also needs an onclick function - runAccordion(this.id).

Finally, the javascript - the two variables at the top can be modifed to change the speed of the animation.

Script

var elementCount = 3;  // this must be set to the amount of accordion elements on the page
var frameRate = 10;   // these two settings control the speed of the animation
var animationSpeed = 10;
var heights = new Array(300,400,100);   // you must set the height of each accordion content area in order here

function runAccordion(id) {
 idNo = id.substring(6);
 element = document.getElementById("content"+idNo);
 elemHeight = element.style.height.replace("px", "");
 curElemNo = 0;
 for(i=1;i<=elementCount;i++) {
  curElement = document.getElementById("content"+i);
  curElemHeight = curElement.style.height.replace("px", "");
  if (curElemHeight > 0 && i != idNo) {
    curElemNo = i;
  }
 }

 if (elemHeight == 0 || elemHeight == null) {
  document.getElementById("content"+idNo).style.height = "0px";
  reelDown(idNo, heights[idNo-1], 0, curElemNo);
  
 } else {
  document.getElementById("content"+idNo).style.height = heights[idNo-1]+"px";
  reelUp(idNo, 0, heights[idNo-1]);
 }
 
}
function reelUp(id, target, current) {

 elemId = id; targetHeight = target; currentHeight = (current-animationSpeed);
 if(current > target) {
  element = document.getElementById("content"+elemId);
  elemHeight = element.style.height.replace("px", "");
  document.getElementById("content"+elemId).style.height = currentHeight+"px";
  setTimeout("reelUp(elemId, targetHeight, currentHeight)", frameRate);
 }
}

function reelDown(id, target, current, element) {
 
 elemId = id; targetHeight = target; currentHeight = (current+animationSpeed);
 curElement = element;
 if(current < target) {
  element = document.getElementById("content"+elemId);
  if (curElement != 0 && curElement != null) {
   element2 = document.getElementById("content"+curElement);
   elemHeight2 = element2.style.height.replace("px", "");
   closeSpeed = heights[parseInt(curElement)-1] / animationSpeed;
   document.getElementById("content"+curElement).style.height = (elemHeight2-closeSpeed)+"px";
  }
  document.getElementById("content"+elemId).style.height = currentHeight+"px";
  
  setTimeout("reelDown(elemId, targetHeight, currentHeight, curElement)", frameRate);
 }
}

Its not perfect by a long shot (in fact it causes some nasty slow down in IE when the animating DIV starts going off the bottom of the visible browser area and thus causing the scoll area to increase), but its a nice little proof of concept.

Comments

Please login to comment on this page

back