Lazy Load with Plain JavaScript

No Comments

I was looking for a solution to load a large number of images on one page.
The problem, however, was the loading speed on a client side where 200-300
thumbnails would take forever to load in a browser.

I did some research and found a few techniques such as “JavaScript Paging” and “Lazy Load” to handle so many images on one page.
The idea is not to load all of them at once. However, my favorite technique I chose “Lazy Load” required some additional components like Prototype or JQuery libraries to be used. With those third party frameworks, it is quite easy to implement the solution but more difficult
to customize and control the code. Moreover, the resources used by a client when loading heavy
libraries, especially Prototype, to use a tiny bit of their code do not seem to be the best idea.

So, I came up with my own “Lazy Load” solution which uses a few lines of plain old JavaScript.
The demo of the Lazy Load
is here (http://vunet.us/demo/lazyload/).

Code explanation

Let’s say we populate the global JavaScript array with image paths like this

var imgSrcMap = new Array();
imgSrcMap[0] = "lazyloadimages/N08422-1-lr-1.jpg";
imgSrcMap[1] = "lazyloadimages/N08422-2-lr-1.jpg";

and so on… We can do it with any server side page in ASP or PHP looping through
all images in a folder or database.

When the page is loaded, we initialize the function which draws all images but the source
of each image would be a tiny 1×1 pixel image for every image we draw:

var imageMap = new Array();
function loadImageTables(){
var table = document.createElement("table");
var defaultCell = document.createElement("TD");
defaultCell.className = "imageContainerCell";
defaultImg = document.createElement("img");
defaultImg.src="lazyloadimages/grey.gif";
defaultImg.border = "0";
defaultImg.width = "80";
defaultImg.height = "80";
defaultCell.appendChild(defaultImg);
for(var i=0; i<imgSrcMap.length;i++){
if(i==0||i%4==0){//4 thumbs per row
var row = table.insertRow(table.rows.length);
}
var cell = defaultCell.cloneNode(true);
cell.onmouseover = hoverImgCell;
cell.onmouseout = outImgCell;
row.appendChild(cell);
imageMap[i] = cell;//store reference to image
}
var container = document.getElementById("imageContainer");
if(container){ container.appendChild(table); }
checkImages();//load initial viewport
}

In the code above I create a new array imageMap which stores the reference to the cell for quick access to image source swap (but this is later). To make things nicer I added onmouseover and onmouseout events to change the background color of the cell we are in. Feel free to ignore this functionality.

The last function checkImages() is where the soup is being cooked. It is invoked on load as we saw above and on window scrolling and resizing:


window.onscroll = checkImages;
window.onresize = checkImages;

Finally, let’s take a close look at what the function is doing:


function checkImages() {
var viewportSize = document.body.scrollTop + document.body.clientHeight;
for (var i = imageMap.length; i > 0; i–){
var index = i-1;
var el = imageMap[index];
if (viewportSize > el.offsetTop){
loadImage(index);
imageMap.splice(index,1);//delete to avoid looping over
imgSrcMap.splice(index,1);//delete to match array above
}
}
}

First, we find the size of the Viewport (the distance from the very top of the page to the bottom of your browser including scrolled distance). Then we loop through imageMap array to check if the cell is within the Viewport, i.e. visible on screen. If so, we must show the actual true source of the image which is done in this function:


function loadImage(i) {
if(imageMap[i].firstChild.src != imgSrcMap[i]){
imageMap[i].firstChild.src = imgSrcMap[i];
}
}

We simply swap the old 1×1 pixel with the real one. The true image is now loaded.
To avoid looping through the same elements of array of images which are already loaded,
we remove all loaded images from array as the last step in function checkImages().

I hope this is helpful. Please check Lazy Load with Plain JavaScript demo page and feel free to steal the code from there by viewing the page source.