Feature

by Joe Gillespie — Jan 1, 2003

Scripting the Box

In the November issue, I showed how to achieve rollover effects using just style sheets and no JavaScript. This time, I'm pulling out all the stops, no holds barred.

CSS plus JavaScript makes a very potent mix indeed. With JavaScript, you can change CSS box properties in real time. You can make boxes come and go, change sizes, positions, colours - just about anything - and it's not too difficult.

If you have ever delved into Dynamic HTML, you are probably very aware how browser differences can mess up your best-laid plans and that the so-called 'browser sniffing' techniques are more than likely to fail.

The trick behind using CSS and JavaScript doesn't depend on testing which browser is being used. For regular JavaScript rollovers, we would test for document.images - any browser that supports this feature regardless of what type or version.

if(document.images) { // do the image swap thing! }

To filter out browsers that can't handle scripted CSS, we can simply do this:-

if(document.getElementById) { // you can script the box } else { // it's not going to work so... return false; }

This basic construct isn't going to make old browsers magically handle CSS scripting, but it stops them from throwing up error messages. Just make sure that getElementById is typed exactly like this, it is case sensitive.

Before we can manipulate a CSS box from a script, the box object is first assigned to a variable, just as you would assign any other variable.

var mybox = document.getElementById("boxname");

Now we can refer to the box using that variable and can assign properties to 'mybox.style'.

mybox.style.visibility = "hidden"; // to hide mybox.style.visibility = "visible"; // to show

or

mybox.style.width = "0"; // hides the box because it has no width.

or you can try

mybox.style.backgroundColor = "yellow";

Using this technique, you can address any valid property of a CSS box, but the ability to show or hide a box is especially useful and that is what I'm going to concentrate on for now.

Example 11

I hate instruction manuals. They throw too much information at you all at once and finding the bits you really need to know takes quite a lot of digging. An interactive manual lets you explore the product little by little and leads you down to as much detail as you want. The controls on a digital camera are typical.

This example makes use of the ability to hide or show a complete text box, well, a series of alternative text boxes actually. There are lots of ways to trigger the text box change - text links, image button links, etc, but for this example, I use an image map. Instead of the image map taking you off to another linked location , as it would do in a regular navbar, I'm going to make use of the onmouseover and onclick events to call a JavaScript function to show appropriate text. As we don't want the clicks to take the reader away from the current page, the link just points to a dummy JavaScript function that does nothing at all.

function nothing() { }

Each camera control has a hotspot on the image map. Passing the cursor over a hotspot, calls the function show(n) where n is a number assigned of the hotspot.

Each of the fourteen hotspots mouseovers (0 to 13) makes one text box visible and hides all the others. One hotspot, the Display button, toggles the visibility of the LCD image with an onclick event calling the showpic() function. The complete show(n) function looks like this:-

function show(n) { if (document.getElementById) { var text0 = document.getElementById("t0"); var text1 = document.getElementById("t1"); var text2 = document.getElementById("t2"); var text3 = document.getElementById("t3"); var text4 = document.getElementById("t4"); var text5 = document.getElementById("t5"); var text6 = document.getElementById("t6"); var text7 = document.getElementById("t7"); var text8 = document.getElementById("t8"); var text9 = document.getElementById("t9"); var text10 = document.getElementById("t10"); var text11 = document.getElementById("t11"); var text12 = document.getElementById("t12"); var text13 = document.getElementById("t13"); for(i=0;i<=13;i++) // hide all text boxes { eval("text"+i).style.visibility = "hidden"; } // then show the one we want eval("text"+n).style.visibility = "visible"; } else { // the browser sucks return false; } }

eval("text"+n) is the way to join, or concatenate, a string "text" and a number n. First, all the boxes are assigned to variables, then we make sure that they are all hidden in the for() loop. Finally, the text box appropriate to the camera control is made visible.

eval("text"+n).style.visibility = "visible";

I've tried to keep this example fairly simple for clarity, but it would be possible to add more onclick() events - to make the flash gun pop up, the mode lever to change position and the text boxes themselves could have further links to other sections of the manual. The sky's the limit!

Example 12

This one's a wee bit more complicated, but if you break it down into smaller chunks, it uses exactly the same techniques as the previous example.

This page is a CSS implementation of frames. You remember frames? Yuck! Framed sites were once very popular but then people discovered that the disadvantages outweighed the advantages. Using static and changeable CSS boxes achieves the same effect bypassing most of the nasty aspects of frames - complexity, difficult to search and index, juggling with different HTML files.

The page works like a slide show. There are only seven 'slides' but you could have as many as you like and they can contain text, pictures, Flash movies, whatever you like.

In addition to swapping the text boxes, here, I'm going to make some images appear, too, and they are in separate boxes from the text, so, some slides (not all) are actually making two boxes appear simultaneously.

Slide six has a 'build' of bullet points that become visible in sequence as they might in a PowerPoint presentation. I was tempted to introduce some 'wipe' effects too, but I'll save that for another time.

Instead of using an image map, this time it just a simple text link in a navbar nailed to the bottom of the browser window. This time, they are linked to a function called slide(n), where n is the number of the slide required. There is also a next and previous button, but you'll have to examine the source to see how those work.

The basic script is very similar to Example 11

// this function displays the slides function slide(n) { // first, make sure the browser is capable if (document.getElementById) { // assign the text boxes to variables var text1 = document.getElementById("t1"); var text2 = document.getElementById("t2"); var text3 = document.getElementById("t3"); var text4 = document.getElementById("t4"); var text5 = document.getElementById("t5"); var text6 = document.getElementById("t6"); var text7 = document.getElementById("t7"); // assign the picture boxes to variables var pic1 = document.getElementById("p1"); var pic2 = document.getElementById("p2"); var pic3 = document.getElementById("p3"); var pic4 = document.getElementById("p4"); // hide all text boxes for(i=1;i<=7;i++) { eval("text"+i).style.visibility = "hidden"; } // then show the one we want eval("text"+n).style.visibility = "visible"; // display the appropriate pictures pic1.style.visibility = picvis[n][0]; pic2.style.visibility = picvis[n][1]; pic3.style.visibility = picvis[n][2]; pic4.style.visibility = picvis[n][3]; // keep track of which slide we are at currentslide=n; // slide 6 is a special case with timed bullets // so we call the bullets() function // to display them sequentially if(n==6) { bullets(true); } else { bullets(false); } } else // its an old browser { return false; } }

The text and image boxes are assigned to variables, the text boxes are all hidden in a for() loop. Then text box n is made visible.

The visibility of the picture boxes is a little more complicated. I've used an array picvis[] to hold the visibility state of the pictures for each slide. Whether a picture is visible or not is determined by the appropriate element of the arrays.

var picvis = new Array(); picvis[1]=["hidden","hidden","hidden","hidden"]; picvis[2]=["hidden","visible","hidden","hidden"]; picvis[3]=["hidden","visible","hidden","visible"]; picvis[4]=["hidden","visible","visible","visible"]; picvis[5]=["visible","visible","visible","visible"]; picvis[6]=["visible","visible","visible","visible"]; picvis[7]=["visible","visible","visible","visible"];

This is effectively a two dimensional array. [n] is the number of the slide and the number following [0] picks up the visibility from the array element. Note, JavaScript array elements start counting at zero, not one.

pic1.style.visibility = picvis[n][0]; pic2.style.visibility = picvis[n][1]; pic3.style.visibility = picvis[n][2]; pic4.style.visibility = picvis[n][3];

For instance, pic3.style.visibility = picvis[2][3]; refers to picvis[2]=["hidden","visible","hidden","hidden"]; making the fourth picture of slide 2 invisible.

As there are only four pictures for seven slides, all pictures are visible for the last three slides.

Sequencing the bullet points on slide six involves setting up a looped timer to introduce a delay between each line. Timers in JavaScript are not very intuitive and a little difficult to understand. It's a bit like planting flowers in the garden to come up at different dates in the future. The loop completes almost instantly but sets up events in the future when the pictures will become visible. These times are at one-second intervals but by changing the variable secs, you can make the delay any length you like.

// if t is true, a delay is introduced between // each visible bullet point // if false, there is no delay and the bullets are hidden function bullets(t) // runs through lines 1 to max { index=1; s=t; if(t) { delay=secs*1000; } else { delay=0; } for (i=0;i<=max;i++) { time=setTimeout('showit(s)',delay*i); } clearTimeout(time); }

So, the function showit(s) is called seven (max) times at one-second (delay) intervals. The value of s can either be true or false making the image visible or hidden. index counts the bullets.

function showit(s) { if(index>0&&index<=max) { if (document.getElementById) { var bullet1=document.getElementById("b1"); var bullet2=document.getElementById("b2"); var bullet3=document.getElementById("b3"); var bullet4=document.getElementById("b4"); var bullet5=document.getElementById("b5"); var bullet6=document.getElementById("b6"); var bullet7=document.getElementById("b7"); if(s) { eval("bullet"+index).style.visibility="visible"; } else { eval("bullet"+index).style.visibility="hidden"; } index++; } else { return false; } } }

Have a look at the source to see the whole script and how the bits fit together.

There are lots of good techniques going on in there. The ability to keep some items on a page constant and for others to change opens up many possibilities. Feel free to experiment and adapt these scripts as you wish.

Del.icio.us Digg Technorati Blinklist Furl reddit Design Float