For a new version of the robotics team history page at /history, I was creating a pure-javascript (for reasons I will not enumerate here), cross-browser (for reasons I need not enumerate here) application to display information about the team in a certain year when that year was clicked. Most of the code was relatively simple (the cross-browser part remains to be done), since I just had to get the information from the document structure and then re-output it, with some of it hidden and modified in an appropriate fashion.

The most difficult part was blessing my application with fades. When I clicked on a year, I wanted to see a short (~1 second) transition in which the current year faded out, and when it was gone, the next year faded in. I chose not to use scriptaculous, which is built on prototype, because the combination is well over 200KB and would dwarf my 15-20KB application. Scriptaculous was overkill (an in my opinion, is overkill for almost anything). As usual, the complete code is displayed at the bottom.

The key was the style.opacity element of HTML elements in Javascript. This does exactly what it should do – set element.style.opacity to be 1.0 for 100% opacity, set it to be 0.0 for a transparent element. Anything else is, according to my science teacher, ‘translucent’. Now the only things remaining are getting the elements to be on top of each other (with absolute positioning, this is pretty easy), and making the fades gradual using setTimeout.

The setTimeout() is actually pretty tricky. The problem is that a function like this:

  1. function doFadeIn(element,increment,timeout) {
  2.     var current=element.style.opacity;
  3.     if(current==null || current=="") current=0.0;
  4.     if(current<1.0) {
  5.         element.style.opacity=parseFloat(increment)+parseFloat(current);
  6.         element.style.display="block";
  7.         setTimeout("doFadeIn(element,"+increment+","+timeout+")",timeout);
  8.     } else {
  9.         element.style.opacity=1.0;
  10.     }
  11. }

Will totally screw up, since ‘element’ is not of global scope. So, you need to make a global variable _in_element that will store the element during the transition.

And now the code. I don’t vouch that this actually works on any browser except Firefox (I know, for example, that it does not work on Internet Explorer). You’ll note that I did something very ugly – I set the ’showElement’ to delay its action for 500 milliseconds. This was a cheap hack, and should have been done in the ‘displayYear’ function.

Cross-browser update: it now works on everything except Internet Explorer. Apparently IE uses the ‘filter’ CSS property instead of ‘opacity’.

  1. var _element;
  2. var _out_element;
  3. var _in_element;
  4.  
  5. function hideElement(element,effect) {
  6.     if(effect==null) effect=true;
  7.     if(element!=null) {
  8.         if(effect && element.style.display!="none") {
  9.             element.style.display="block";
  10.             element.style.position="absolute";
  11.             element.style.opacity=1.0;
  12.             doFadeOut(element);
  13.         } else
  14.             element.style.display="none";
  15.     }
  16. }
  17.  
  18. function showElement(element,effect) {
  19.     if(effect==null) effect=true;
  20.     if(element!=null) {
  21.         element.style.postition="absolute";
  22.         if(effect) {
  23.             _element=element;
  24.             setTimeout("doFadeIn(_element)",500);
  25.         } else
  26.             element.style.display="block";
  27.     }
  28. }
  29.  
  30. function doFadeIn(element,increment,timeout) {
  31.     _in_element=element;
  32.     if(increment==null) increment=0.05;
  33.     if(timeout==null) timeout=15;
  34.     var current=element.style.opacity;
  35.     if(current==null || current=="") current=0.0;
  36.     if(current<1.0) {
  37.         element.style.opacity=parseFloat(increment)+parseFloat(current);
  38.         element.style.display="block";
  39.         setTimeout("doFadeIn(_in_element,"+increment+","+timeout+")",timeout);
  40.     } else {
  41.         element.style.opacity=1.0;
  42.     }
  43. }
  44.  
  45. function doFadeOut(element,increment,timeout) {
  46.     _out_element=element;
  47.     if(increment==null) increment=0.05;
  48.     if(timeout==null) timeout=25;
  49.     var current=element.style.opacity;
  50.     if(current==null || current=="") current="1.0";
  51.     if(current>"0.0") {
  52.         element.style.opacity=current-increment;
  53.         setTimeout("doFadeOut(_out_element,"+increment+","+timeout+")",timeout);
  54.     } else {
  55.         element.style.display="none";
  56.     }
  57. }
  58.  
  59. var AIDA=new function() {
  60.  
  61.         //some stuff here
  62.  
  63.         this.displayYear=function(yr,effect) {
  64.             for(var i=minyear;i<=maxyear;i++)
  65.                 if(years[i]!=null && i!=yr) {
  66.                     hideElement(document.getElementById("AIDA-year-"+i),effect);
  67.                 }
  68.             if(document.getElementById("AIDA-year-"+yr).style.display!="none" || !effect)
  69.                 showElement(document.getElementById("AIDA-year-"+yr),effect);
  70.         }
  71. }

Related posts: