An image gallery: Extra credit

  1. A new random image
  2. An image gallery

If you’re following this directly from the handout, the answers (or possible answers) are revealed directly beneath the questions. So if you want to try it yourself, don’t read too quickly.

Random integers

One of the important lessons of programming is to write code that you understand. This often means making functions with informative names that both describe the code and make the code easier. In the section “Random image”, Math.floor(Math.random()*maximum) is not immediately obvious as a random integer generator. How would you write a function called "random" that returned a random integer (a) between 0 and a parameter given to the function, and (b) between a minimum and a maximum? This function might look like, in use, “var randomInteger = random(4)” to provide a random integer between 0 and 3. Or it might look like “var randomInteger = random(4, 1) to provide a random integer between 1 and 4, or “var randomInteger = random(4, 3) to provide a random integer between 3 and 6.

Possible answer:

function random(range, floor) {

var randomInteger = Math.floor(Math.random()*range);

if (floor) {

randomInteger += floor;

}

return randomInteger;

}

It will return a random number from 0 to the first parameter; if you give it a second parameter, that number will be added to the initial random number. So, random(3) will produce a number from 0 to 2, but random(3, 1) will produce a number from 1 to 3.

Once you’ve added it to gallery.js, you can test it using “javascript:window.alert(random(4))”.

Randomly change from the current image.

For the purpose of the randomImage function—choose a random image when the visitor first comes to the page—we want the random list to include the default image in the <img> tag. But what if you were using this random function to switch to a new random image? You wouldn’t want the current image to be one of the choices. How would you rewrite randomImage to never return the current image?

Possible answer: I can think of two possibilities. The first one (and the safest) is to construct a new list from the old one, that excludes any links whose href attribute is the same as the current img tag’s src attribute. This solution is a bit tricky, because it requires looking up the for loop in the JavaScript documentation and it requires looking up how to add an item to an array.

//a safe random image excluding the current image

function randomImage() {

var aList = document.getElementById("images").getElementsByTagName('A');

currentImage = document.getElementById("frame");

var usableImages = new Array();

for (var aIndex=0;aIndex<aList.length;aIndex++) {

var a = aList[aIndex];

if (a.href != currentImage.src) {

usableImages.push(a);

}

}

if (usableImages) {

var aChoice = Math.floor(Math.random()*usableImages.length);

switchImage(usableImages[aChoice]);

}

}

Another possibility is to keep calling randomImage() until we get a random a tag whose href doesn’t match the src of the current img. There’s nothing new in this solution, but it does involve a trick that we haven’t covered yet.

//a fast random image excluding the current image

function randomImage() {

var aList = document.getElementById("images").getElementsByTagName('A');

if (aList.length > 1) {

currentImage = document.getElementById("frame");

var aChoice = Math.floor(Math.random()*aList.length);

//if the choice is the same as the current one, don't use it

if (aList[aChoice].href == currentImage.src) {

randomImage();

} else {

switchImage(aList[aChoice]);

}

}

}

This uses recursion—randomImage is calling itself. Recursion can be a very useful tool for programming, especially when dealing with lists of items. In this case it’s probably a bit dangerous. We’re checking that there are multiple <a> tags before recursing, because otherwise it would recurse forever, with each recursion choosing the only image in the list, realizing it’s the same as the current image, and recursing. Eventually the browser will recognize that something’s wrong and cancel the script.

Control the slide show

We used javascript: URLs in the URL bar to advance the slide show while we were testing it. Those URLs work just as well inside of the page. You can make an “advance” link to “javascript:gallery.advance();". Do that. And then, write a new method for SlideShow that moves backwards, and provide a link to that as well.

this.retreat = function() {

this.currentSlide--;

if (this.currentSlide < 0) {

this.currentSlide = this.slides.length-1;

}

this.slide(this.currentSlide);

}

Test it using “javascript:gallery.retreat()” and when it works, add it as a link on the page.

Then, add another button to turn automatic sliding on or off. Add a property called “paused” which, when true, causes “advance” to not advance the slides. Create a method called “pause” which sets that property to true, and another method, “play”, which sets that property to false.

For extra extra credit, use only a single link to switch between pause and play. The pause method will change that link to read “Resume slide show” and call gallery.play(), where the play method will change the link to read “Pause slide show” and call gallery.pause().

  1. A new random image
  2. An image gallery