Showing Images on MouseOver

Hi there,

I went in search on how to show images by mousing over text. I found this tutorial: http://www.wallpaperama.com/forums/how-to-show-picture-on-mouseover-with-javascript-tutorial-t6984.html

It worked, except I cannot figure out how to do multiple images. Could someone please help me to do multiple images with the code this tutorial provides?

Thank you!!

First of all let’s update the code so that it uses better techniques that have been learned.

The code before:


<!-- 
function ShowPicture(id,Source) { 
if (Source=="1"){ 
if (document.layers) document.layers[''+id+''].visibility = "show" 
else if (document.all) document.all[''+id+''].style.visibility = "visible" 
else if (document.getElementById) document.getElementById(''+id+'').style.visibility = "visible" 
} 
else 
if (Source=="0"){ 
if (document.layers) document.layers[''+id+''].visibility = "hide" 
else if (document.all) document.all[''+id+''].style.visibility = "hidden" 
else if (document.getElementById) document.getElementById(''+id+'').style.visibility = "hidden" 
} 
} 
//--> 

Those HTML comment markers are for browsers earlier than Netscape 2, which don’t know how to do scripting. Yes, that’s ancient.
They are not needed these days, especially when you place your script in an external script file.

The Source variable with a value of 0 or 1 is not all that appropriate to determine whether the function should show or hide. Instead of that, the code can be split off in to two different functions, one to show and the other to hide, along with some support functions to help compartmentalise ancient browser compatibility.

Also, using ‘’+id+‘’ was an old fashoned way to convert a number to a string, which is not needed here either. If you do need to convert a number to a string, there are much more appropriate ways to do so, involving functions like parseInt.


function getById(id) {
    if (document.getElementById) {
        return document.getElementById(id);
    } else if (document.all) {
        return document.all[id];
    } else if (document.layers) {
        return document.layers[id];
    }
}
function setStyle(elem, prop, style, layerStyle) {
    if (!elem) {
        return;
    }
    if (elem.style) {
        elem.style[prop] = style;
    } else if (document.layers) {
        elem[prop] = layerStyle || style;
    }
}
function showPicture(id) { 
    var elem = getById(id);
    setStyle(elem, 'visibility', 'visible', 'show');
} 
function hidePicture(id) { 
    var elem = getById(id);
    setStyle(elem, 'visibility', 'hidden', 'hide');
} 

And now we don’t need to pass the id value to the function either, because that can be obtained directly from the link href itself. This also means that we can remove the inline event attributes and perform that task from the script itself too.

We can also give the style declaration more meaningful name than just Style too.


.image { 
    position: absolute; 
    border: solid 1px #CCC; 
    padding: 5px; 
} 


<a id="show" href="#show1">Hover Here To Show Image</a> 
<div id="show1" class="image"><img src="http://www.wallpaperama.com/post-images/forums/200901/11-880-aaaa.jpg"></div>


...
function showPicture() {
    var elem = getById(this.href.split('#')[1]);
    setStyle(elem, 'visibility', 'visible', 'show');
} 
function hidePicture() { 
    var elem = getById(this.href.split('#')[1]);
    setStyle(elem, 'visibility', 'hidden', 'hide');
} 
var link = getById('show');
link.onmouseover = showPicture;
link.onmouseout = hidePicture;

So that’s keeping most of the historical stuff in there, and bringing it forward to make use of modern techniques that still work back in ancient times.

How that code would be done today is by keeping the HTML code the same, but using the style not to hide the image at the start, but only when the style is applied to the element by the script. Doing things that way around allows non-scripting people to still see the content of the page.
We also load scripts from the end of the body, just before the </body> tag which allows them to easily access elements of the page on an as-needed basis.


.image { 
    position: absolute; 
    border: solid 1px #CCC; 
    padding: 5px; 
} 


<a id="show" href="#show1">Hover Here To Show Image</a> 
<div id="show1" class="image"><img src="http://www.wallpaperama.com/post-images/forums/200901/11-880-aaaa.jpg"></div>
...
<script src="script.js"></script>

Now we hide the image as the page is loading, but triggering the onmouseout event of the link.
We can get rid of the getById function, and just use getElementById to gain a reference to an element on the page.
We can also use the now standardised style property of an element, to work with style attributes on page elements.


function showPicture() {
    var id = this.href.split('#')[1],
        elem = document.getElementById(id);
    elem.style.visibility = 'visible';
}
function hidePicture() {
    var id = this.href.split('#')[1],
        elem = document.getElementById(id);
    elem.style.visibility = 'hidden';
}
var link = document.getElementById('show');
link.onmouseover = showPicture;
link.onmouseout = hidePicture;
link.onmouseout();

We could even remove the two functions, and instead use just one function to setup the link to the image, and then handle the mouse over and out.


function toggleLinkedImage(link) {
    var id = link.href.split('#')[1],
        elem = document.getElementById(id);
    link.onmouseover = function () {
        elem.style.visibility = 'visible';
    };
    link.onmouseout = function () {
        elem.style.visibility = 'hidden';
    };
    link.onmouseout();
}
var link = document.getElementById('show');
toggleLinkedImage(link);

We can also protect this code from being affected by other code, by encapsulating it in a self executing wrapper. This not only protects the global namespace from our code, but it also protects our code from significant troubles that other code can cause.


(function (window, document, undefined) {
    function toggleLinkedImage(link) {
        var id = link.href.split('#')[1],
            elem = document.getElementById(id);
        link.onmouseover = function () {
            elem.style.visibility = 'visible';
        };
        link.onmouseout = function () {
            elem.style.visibility = 'hidden';
        };
        link.onmouseout();
    }
    var link = document.getElementById('show');
    toggleLinkedImage(link);
}(this, this.document));
&#8203;

But that’s just for one image. How do we deal with multiple images? I’ll cover that next.

With this next part, I presume that you want to hover on a link to show different images all in the same location.

With that sort of system, we tend to use a container to hold the image, and then just replace the contents of that container with a copy of the image.


.image { 
    position: absolute; 
    border: solid 1px #CCC; 
    padding: 5px; 
}&#8203;


<ul id="linkedImages">
    <li><a id="show" href="#">Hover Here To Show Image 1 <img src="http://www.wallpaperama.com/wallpapers/aquarium/wallpaper/aquarium/sample/10696/aquarium-wallpaper.jpg"></a></li>
    <li><a href="#">Hover Here To Show Image 2 <img src="http://www.wallpaperama.com/wallpapers/automobile/wallpaper/car/sample/18508/car-wallpaper.jpg"></a></li>
    <li><a href="#">Hover Here To Show Image 3 <img src="http://www.wallpaperama.com/wallpapers/aquarium/wallpaper/salt-water-aquarium/sample/43428/salt-water-aquarium-wallpaper.jpg"></a></li>
    <li><a href="#">Hover Here To Show Image 4 <img src="http://www.wallpaperama.com/wallpapers/celebrity/wallpaper/victoria-justice/sample/59640/victoria-justice-wallpaper.jpg"></a></li>
</ul>
<div id="container" class="image"></div>&#8203;

The links can all be easily accessed by looking through the links within the element identified as linkedImages. The images are a part of the link too, so that they can be easily found. They are also hidden by the scripting too, which means that they won’t get in the way of things.


var container = document.getElementById('container'),
    links = document.querySelectorAll('#linkedImages a'),
    i;
for (i = 0; i < links.length; i += 1) {
    toggleLinkedImage(links[i], container);
}

The toggleLinkedImage function sets things up similarly to when dealing with a single image, and clears the container before putting a copy of the image in the container.


function toggleLinkedImage(link, container) {
    var img = link.querySelector('img');
    link.onmouseover = function () {
        var newImage = img.cloneNode(true);
        newImage.style.display = '';
        clear(container);
        container.appendChild(newImage);
    };
    link.onmouseout = function () {
        img.style.display = 'none';
        clear(container);
    };
    link.onmouseout();
}

And lastly we have a function to help us empty the contents of an element, which is used with the container.


function clear(elem) {
    while (elem.hasChildNodes()) {
        elem.removeChild(elem.firstChild);
    }
}

So the full javascript for this example is:


(function (window, document, undefined) {
    function clear(elem) {
        while (elem.hasChildNodes()) {
            elem.removeChild(elem.firstChild);
        }
    }
    function toggleLinkedImage(link, container) {
        var img = link.querySelector('img');
        link.onmouseover = function () {
            var newImage = img.cloneNode(true);
            newImage.style.display = '';
            clear(container);
            container.appendChild(newImage);
        };
        link.onmouseout = function () {
            clear(container);
            img.style.display = 'none';
        };
        link.onmouseout();
    }
    var container = document.getElementById('container'),
        links = document.querySelectorAll('#linkedImages a'),
        i;
    for (i = 0; i < links.length; i += 1) {
        toggleLinkedImage(links[i], container);
    }
}(this, this.document));
&#8203;