reptile7's JavaScript blog
Tuesday, October 04, 2011
 
The Image Parade, Part 3
Blog Entry #228

In today's post we will take up HTML Goodies' "JavaScript Tutorial: Build Your Own Image Viewer with Scrollbar", which builds on the "Web Developer Tutorial: Build Your Own Image Scrollbar" we've been discussing in the last two entries. As demonstrated in the previous post, the latter tutorial codes an image scrollbar positioned under a large img placeholder whose image sits unchanged while a series of images is loaded into the scrollbar's thumbnail img placeholders. "Build Your Own Image Viewer with Scrollbar" augments the "Build Your Own Image Scrollbar" code with a set of functions and array data that turns the scrollbar into a 'remote control' vis-à-vis the large img placeholder: upon mousing over a given scrollbar image, the new code
(1) loads that image into the large img placeholder,
(2-3) displays a caption and description for the new large image, and
(4-5) assigns new alt and title attribute values for the large img placeholder.

No demo is provided for the "Image Viewer" tutorial. However, tutorial commenter George has posted here a preliminary demo combining the tutorial code with his own set of images and has even put the image viewer into practice here.

A bigger table

The "Image Viewer" tutorial adds two new rows to the scrollbar display table.
(1) The row holding the large image is preceded by a row that will hold a caption for the large image.

#imageTitleCell { text-align: center; font-weight: bold; font-size: 18pt; color: silver; background-color: maroon; }
...
<tr><td colspan="6" id="imageTitleCell">Grasslands</td></tr>


(2) The row holding the large image is followed by a row that will hold a description for the large image.

#imageDescriptionCell { text-align: left; padding-right: 100px; padding-left: 100px; color: white; background-color: maroon; }
...
<tr><td colspan="6" id="imageDescriptionCell">This is the description for the first image. Here will be where we give details on the image that is currently being viewed.</td></tr>


For referencing purposes, the first-row caption cell, the third-row description cell, and the now-second-row large img placeholder have been given ids set to imageTitleCell, imageDescriptionCell, and imageLarge, respectively.

Here's a screen shot of what we've got so far:

[The pre-scroll image viewer table]

A 2-D array

The "Image Scrollbar" tutorial orders the scrollbar image file names via a conventional array; interestingly, the "Image Viewer" tutorial uses a two-dimensional array to organize the image file names, captions for the large images, and descriptions for the large images. The following code sets up a parent imageData array having ten elements, each of which is itself an array having three elements:

var imageData = new Array(10);
createTwoDimensionalArray(3);

function createTwoDimensionalArray(arraySize) {
    for (i = 0; i < imageData.length; ++i)
        imageData[i] = new Array(arraySize); }


The child arrays are populated with image data via normal assignment statements:

// Image file name data
imageData[0][0] = "image1.png";
imageData[1][0] = "image2.png";
imageData[2][0] = "image3.png";
imageData[3][0] = "image4.png";
...
// Image caption data
imageData[0][1] = "Grasslands";
imageData[1][1] = "Tree Canopy";
imageData[2][1] = "In the Clouds";
imageData[3][1] = "Sunflower Bud";
...
// Image description data
imageData[0][2] = "This is the description for the first image. Here will be where we give details on the image that is currently being viewed.";
imageData[1][2] = "This is the description for the second image...";
imageData[2][2] = "This is the description for the third image...";
imageData[3][2] = "This is the description for the fourth image...";
...


Each child array thus contains the file name/caption/description data for a given image; we could alternatively write:

imageData[0] = ["image1.png", "Grasslands", "This is the description for the first image..."];
imageData[1] = ["image2.png", "Tree Canopy", "This is the description for the second image..."];
imageData[2] = ["image3.png", "In the Clouds", "This is the description for the third image..."];
imageData[3] = ["image4.png", "Sunflower Bud", "This is the description for the fourth image..."];
...


The Storing the Data: Creating a Two-Dimensional Array section at the top of the tutorial's second page makes a respectable stab at explaining two-dimensional arrays, likening them to spreadsheets (the author doesn't use this term, but that's the gist of the discussion). The Multi-dimensional arrays section in the Mozilla JavaScript Guide is quite skeletal.

Little image to big image

A new handleThumbOnMouseOver( ) function connects the various parts of the image viewer code. The handleThumbOnMouseOver( ) function is called by mousing over a thumbnail placeholder in the scrollbar; it accepts a single imageIndex argument that is used to access a particular imageData[imageIndex] child array. handleThumbOnMouseOver( ) has no commands of its own: rather, it comprises a set of calls to other functions that manipulate the first three rows of the display table.

The handleThumbOnMouseOver( ) function is initially registered with the thumbnail placeholders via the element attribute approach (see the Register me section of Blog Entry #220), e.g.:

#scrollThumb2 { border: 1px solid; height: 100px; width: 100px; }
...
<img id="scrollThumb2" src="image2.png" onmouseover="handleThumbOnMouseOver(1);" />


So, without doing any scrolling at all, mousing over the scrollThumb2 placeholder triggers handleThumbOnMouseOver( ) and passes thereto 1, which is assigned to imageIndex.

// For a thumbnail mouseover event
function handleThumbOnMouseOver(imageIndex) { ... }


handleThumbOnMouseOver( ) first calls the changeImage( ) function

changeImage("imageLarge", imageData[imageIndex][0]);

- that would be the same changeImage( ) we saw in the "Image Scrollbar" tutorial

function changeImage(ImageToChange, MyImagePath) {
    document.getElementById(ImageToChange).setAttribute("src", MyImagePath); }


- and passes thereto imageLarge and imageData[1][0] in order to load the image2.png image into the large img placeholder.

Subsequently handleThumbOnMouseOver( ) calls twice a new changeCellText( ) function.

changeCellText("imageTitleCell", imageData[imageIndex][1]);
changeCellText("imageDescriptionCell", imageData[imageIndex][2]);


The changeCellText( ) function assigns myCellData to the innerHTML of an id=cellId element:

function changeCellText(cellId, myCellData) {
    document.getElementById(cellId).innerHTML = myCellData; }


The first call to changeCellText( ) thus writes Tree Canopy (imageData[1][1]) to the first-row imageTitleCell cell and then the second call writes This is the description for the second image... (imageData[1][2]) to the third-row imageDescriptionCell cell.

Lastly, handleThumbOnMouseOver( ) places calls to new changeImageAlt( ) and changeImageTitle( ) functions.

changeImageAlt("imageLarge", imageData[imageIndex][1] + " - " + imageData[imageIndex][2]);
changeImageTitle("imageLarge", imageData[imageIndex][1] + " - " + imageData[imageIndex][2]);


imageLarge and Tree Canopy - This is the description for the second image... are passed to both functions; the latter argument is respectively assigned by changeImageAlt( ) and changeImageTitle( ) to the alt and title attributes of the large img placeholder:

function changeImageAlt(ImageToChange, imageData) {
    document.getElementById(ImageToChange).setAttribute("alt", imageData); }
function changeImageTitle(ImageToChange, imageData) {
    document.getElementById(ImageToChange).setAttribute("title", imageData); }


And when scrolling is under way? Every time a new image is loaded into a thumbnail placeholder, the placeholder's mouseover behavior must be updated. The author deploys yet another new function, changeImageOnMouseOver( ), to register the handleThumbOnMouseOver( ) function with the thumbnail placeholders on the fly:

function changeImageOnMouseOver(ImageToChange, imageIndex) {
    document.getElementById(ImageToChange).setAttribute("onmouseover", "handleThumbOnMouseOver(" + imageIndex + ");"); }


In the scrollImages( ) function, each changeImage( ) call is accordingly paired with a corresponding changeImageOnMouseOver( ) call:

currentIndex = imageIndexLast;
changeImage("scrollThumb4", imageData[currentIndex][0]); /* Changes the scrollThumb4 image */
changeImageOnMouseOver("scrollThumb4", currentIndex); /* Updates the scrollThumb4 mouseover behavior */
currentIndex = imageIndexLast - 1;
window.setTimeout("changeImage('scrollThumb3', imageData[" + currentIndex + "][0]);", 25);
window.setTimeout("changeImageOnMouseOver('scrollThumb3', " + currentIndex + ");", 25);
...


Preloading again

This time around the "Image Viewer" tutorial's The JavaScript Scrollbar Code section includes the image-preloading function (modified slightly as per the 2-D array) that appears in the source of the current "Image Scrollbar" tutorial demo page:

<body onload="javascript:preloadThumbnails( );">
...
function preloadThumbnails( ) {
    imageObject = new Image( );
    for (i = 0; i < imageData.length; ++i)
        imageObject.src = imageData[i][0]; }


As noted in the previous entry, the effect of this code is browser-dependent: with some browsers all ten imageData[i][0] images will be cached whereas other browsers will only retain the final imageData[9][0] image.

Commenter George's first-generation demo and worked-up image viewer, cited at the outset of the post, both deploy the preloadThumbnails( ) code as-is. George declares that his image viewer looks and works great! It could well be that the preloading thing is a non-issue if you're a broadband user, as George is likely to be, I don't know for certain. But what I can state with certainty is that if you're a slowpoke dial-up user such as myself, and if you're using an only-imageData[9][0]-is-cached browser such as Firefox or Opera, then the image viewer's scrolling will be problematic - specifically, the imageData[4][0]-imageData[8][0] images will load sporadically if at all - until preloadThumbnails( ) is rewritten so that all of the images are concurrently cached.

I'll offer an alternate coding for the image viewer and a demo of my own in the following post.

reptile7

Comments: Post a Comment

<< Home

Powered by Blogger

Actually, reptile7's JavaScript blog is powered by Café La Llave. ;-)