Simple Tabbed Menu

Photo Gallery Using javaScript

I have always liked the Couloir website and the photo gallery that they have. The photo gallery is very interesting because as you go from picture to picture a "curtain" slides down to cover the previous picture only to slide back up after the next picture has been loaded. I had always figured that the gallery was written in PHP (and maybe it is) but, one day I saw a similar motion on a menu script that as you clicked new menu items dropped down or rolled back up. When I saw that I got to thinking that maybe I could do the same kind of gallery that I like so much on the Couloir website only with javaScript.

The first thing I had to figure out was how in the hell did they get that curtain to slide down like that? The thing that I struggled with for a while was how was the HTML written? Because when you think about, a webpage that would yield the kind of effects that you see on the Couloir site has to involve javaScript and style sheets all working together. Thats when I had my first big breakthrough.

I figured out that in order to have the slide down effect there would have to be two div's - one within the other. The first div would have as it's background the first picture that I would display and would be the exact same with as the picture, in this case 750 x 563. The second div would be solid black in color and would start out having no height. Only when I would click on a button or link to go to the next picture would I have to figure out a way for the div to grow, and eventually grow large enough to be the exact same size as the first div, and then shrink back to nothing. Here is the general layout:

	
<div id ="background">
  <div id = "foreground">
    .....
  </div>
</div>
		

Then I added a link with a arrow shaped background image so you can go from one picture to the next. Here you will notice that the href attribute has a javaScript call which basically does nothing and that I only added because after I got everything working I found that my javaScript functions were calling the directories holding the webpage would spontaniously open them. The real function is called by the onclick attribute of the link

<a href = "javascript:next();" id = "next" 
 onclick = "processClick(1, 1); return false;">
  <span>CSS2</span>
</a>
		

The processClick function takes three arguments: a dir - direction (1 being down and -1 being up) - a num - number - which is the number of the photograph in the sequence and an inticator string - nextImg - which lets the function know it is supposed to go to the next or previous picture:

	
function processClick(dir, num, nextImg){
  var cont = document.getElementById('foreground');
  var direction = dir;
	
  clearInterval(cont.timer);
  if(nextImg == "next" || nextImg == "prev"){
    if( dir == 1){
      cont.timer = setInterval(
        "slide(1, " + (num) + ", '" + nextImg + "')",
        timer);
    }else{
	  cont.timer = setInterval(
        "slide(-1, " + (num) + ", '" + nextImg + "')", 
        timer);
    }
  }	
}
		

The function starts out creating a reference to the foreground div which is the div that will be "grown" and "shrunk" accordingly to give it the sliding effect. Then there is the clearInterval fucntion call which is a window object function and is used to clear any timeouts that might been set prviously. Then there is the if - else staements which are used to firgure out if the div is sliding up or down and if the picture to be displayed is the next or previous picture. Finally, inside the if/else block is the setInterval functions which is used to add a delay to a function and is called recursivaly until the clearInterval function is called. The same values that I passed to the processClick function are being passed to the slide function - there is probably a better way to do this, but this is really just a rough draft of an idea that I had and tried to put a quick example together, I am sure I will - and I hope you will do the same - be re-vising this example many, many times before I get it exactly the way that I like it.

On to the slide function, the function that does all the work which means that it will contain much more code than the processClick function:

	
function slide(direction, num, nextImg){
  var cont = document.getElementById('foreground');
  var dist;
  var currentHeight = 
    document.getElementById('foreground').offsetHeight;
  var next = document.getElementById('next');
  var prev = document.getElementById('prev');
  var picCount = 11;

  loader.style.visibility = "hidden";

  if(overlay.style.height.replace('px', '') > 0){
    dist = (Math.round(currentHeight / speed ));
  }

  if( direction == 1){
    dist = (Math.round((563 - currentHeight) / speed));
  }
  else if( direction == -1){
    dist = (Math.round(currentHeight / speed ));
  }
	
  if(dist <= 1){
    dist = 1;
  }
  cont.style.height = currentHeight + (dist * direction) + 'px';

  if((cont.offsetHeight < 1) && (direction == -1)){ 
    /* clearInterval and stop slide */	
    clearInterval(cont.timer);
    if((num) > picCount || (num) < 1){
      num = 1;
      next.onclick = function(){processClick(1, 1, 'next'); 
	    return false;};
      prev.onclick = function(){processClick(1, 1, 'prev'); 
	    return false;};
    }else{
      next.onclick = function(){processClick(1, num, 'next'); 
	    return false;};
      prev.onclick = function(){processClick(1, num, 'prev'); 
	    return false;};
    }
  }else if(currentHeight > (561) && direction == 1){ 
    //Detect when images is completely covered and reverse slide
    image = new Image(750, 563);

    if(nextImg == "next"){
      if(num + 1 > picCount){
        num = 1;
        image.src = 'images/img_' + (num) + '.jpg';
        document.getElementById('background').style.
		  backgroundImage = "url('" + image.src + "')";
        processClick(-1, num, 'next');
      }else{
        image.src = 'images/img_' + (num + 1) + '.jpg';
        document.getElementById('background').style.
		  backgroundImage = "url('" + image.src + "')";
        processClick(-1, (num + 1), 'next');
        loader.style.visibility = "visible";
      }
    }else if(nextImg == "prev"){
      if(num - 1 < 1){
        num = picCount;
        image.src = 'images/img_' + (num) + '.jpg';
        document.getElementById('background').style.
		  backgroundImage = "url('" + image.src + "')";
        processClick(-1, num, "prev");
      }else{
        image.src = 'images/img_' + (num - 1) + '.jpg';
        document.getElementById('background').style.
		  backgroundImage = "url('" + image.src + "')";
        processClick(-1, (num - 1), "prev");
        loader.style.visibility = "visible";
      }
    }
  }
}
		

Like verything in life this is a work in progress but the current version of this example can be found here.

Posted on May 28, 2008