Simple Swap (image rollovers)

posted June 9th 2005 at 0537 EDT in All, HTML, Articles, Javascript

Our goal is to make simple things simpler... right?

Simple Swap is a way to use custom tag attributes and JavaScript triggers to simplify image rollovers, and make Image Rollovers the easiest thing in the world to use without messy JavaScript function calls and image preloading.

Peter-Paul Koch gets us heading down the path of using custom attributes of existing HTML elements to help abstract our Javascript and keep it from cluttering our HTML in his article JavaScript Triggers. This article uses that method to simplify image rollovers.

We have all dealt with JavaScript files pre-loading images for mouseover and mouseout events, and some ugly cryptic functions (not to mention HTML) to execute image rollovers. What we needed was just a easier simpler way to put that all together.

Let's work to apply this concept abstraction, and see where it leaves us. Conceptually, Peter-Paul argues that we should add an attribute to the html tag which triggers Javascript actions. Our starting place is a simple image embeded in a page.


<img src="image.gif">
 

The only additional piece of information we need for a rollover image, is where the image is. So we add that specific image source as a custom attribute named oversrc to the image. This attribute will be what triggers our javascript rollover later on.


<img src="image.gif" oversrc="image_over.gif">
 

Before we get to triggering image rollovers based upon this attribute, we need to setup a function which will execute the onmouseover and onmouseout events. This function performs both the mouseover and mouseout events, and just changes which image url to set the src attribute to. It's a simple function, but so are image rollovers.


function SimpleSwap(el,which){
        el.src=el.getAttribute(which||"origsrc");
}
 

This approach is simple, and is just one step ahead of where we are; it ties the rollover image source url with the tag, and simplifies our rollover functions.

Now, if we didn't want to trigger our javascript automatically we could embed it like this:


<img src="image.gif" oversrc="image_over.gif" onmouseover="javascript:SimpleSwap(this,'oversrc');" onmouseout="javascript:SimpleSwap(this);">
 

This works, however our goal is to have this rollover functionality triggered by the existance of the oversrc attribute on an image tag, so we need to automagically create the onmouseover and onmouseout function calls.

This function simply goes through all images on a page, and if the oversrc attribute is present, it adds the appropriate event handlers for the SimpleSwap rollover function. The only tricky part is setting the scope of the function call when adding it as an event handler so it gets the correct value for 'this' when passed as a parameter to the SimpleSwap function.


function SimpleSwapSetup(){
  var x = document.getElementsByTagName("img");
  for (var i=0;i<x.length;i++){
    var oversrc = x[i].getAttribute("oversrc");
    if (!oversrc) continue;
    // preload image
    // comment the next two lines to disable image pre-loading
    x[i].oversrc_img = new Image();
    x[i].oversrc_img.src=oversrc;
    // set event handlers
    x[i].onmouseover = new Function("SimpleSwap(this,'oversrc');");
    x[i].onmouseout = new Function("SimpleSwap(this);");
    // save original src
    x[i].setAttribute("origsrc",x[i].src);
  }
}
 

Now one last piece of code to run the setup function when the document onload event is fired. We want to do this in such a way that we don't need to add a function call to our <body> tag onload event handler. This method of attaching the SimpleSwapSetup function preserves any existing functions on that event handler.


var PreSimpleSwapOnload =(window.onload)? window.onload : function(){};
window.onload = function(){PreSimpleSwapOnload(); SimpleSwapSetup();}
 

Example

The following code is all we end up with for a nice clean implementation of Image Rollovers:


<script language="javascript" src="/download/simpleswap.js"></script>
<p><img src="/images/ss_img.gif" oversrc="/images/ss_img_over.gif"></p>
 

A final example is here: http://jehiah.com/sandbox/simpleswap.html

Download

Download the final javascript file : http://jehiah.com/download/simpleswap.js

Update

6/10 - version 1.1 - Major updates to simplify javascript code (not usage) even further provided by Adam Vandenberg. Combined SimpleSwapOn and SimpleSwapOff and simplified some of the inialization code.

51 Responses

  1. #1 brett
    2 years, 11 months ago

    Holy cow that’s friggin’ rad. I don’t use image rollovers much anymore, but wow, is this the way to do it when it needs doin’.

  2. #2 Martin
    2 years, 11 months ago

    Two simple changes to make it even better:

    1) There is no language attribute to . User type=”text/javascript”

    2) Drop the “javascript:” strings from the eventhandlers. They are not necessary to indicate javascript, eventhandlers all contain script. “javascript:” will just be interprated as a label by the Javascript engine.

  3. #3 brett
    2 years, 11 months ago

    Just a quick note, if anybody’s interested: This script works excellently with alpha PNG transparencies in IE6 with Dean Edwards IE7 script (which, if you haven’t checked it out, you really should; quite amazing).

    Again, great work. Thanks Jehiah.

  4. #4 Scott Palmer
    2 years, 11 months ago

    Thanks so much for this, it’s great and could not be simpler to implement!

  5. #5 nicolaas
    2 years, 10 months ago

    Does this script take into consideration that images may not be loaded yet?

  6. #6 Jehiah
    2 years, 10 months ago

    nicolas: good question. The script actually preloads the rollover image so that it displays “instantly”.

    Of course if your site is heavy on images; or you are accessing over a slow connection - when mousing over - you see the normal image untill the rollover image has completed loading.

  7. #7 Anonymous
    2 years, 10 months ago

    Actually, this doesn’t work:

    function SimpleSwap(el,which){
    el.src=el.getAttribute(which||”origsrc”);
    }

    It swaps the image, but does not swap it back.

  8. #8 jehiah
    2 years, 10 months ago

    @Anonymous: actually it does work… It’s a clever usage of defaults. If you notice only one of the calls to SimpleSwap() has two parameters.

    What browser are you using where it isn’t working? example page?

  9. #9 Anonymous
    2 years, 10 months ago

    IE6 http://www.mapgasprices.com/dev/index.asp

    Mouseover on North frame border

  10. #10 jehiah
    2 years, 10 months ago

    ahhaa. my intermediate example leaves something out. Since you arn’t calling the SimpleSwapSetup() onload, you also need origsrc="/path/to/normal/image.gif" property. This will take the place of the following line of code in the setup function.

    x[i].setAttribute("origsrc",x[i].src);

    hope that clears things up.

  11. #11 hous
    2 years, 7 months ago

    Jehiah,

    Great site, great script. I’m currently using it on my (in construction) website for previous and next buttons for an image slideshow. It works great, but I need to not display the images when the viewer is at the beginning or end of the slideshow… Is there a way, in JavaScript, to not display the next button image when the viewer is at the end of the slideshow? I already have a variable that equals 1 when the user is at the end, but I can’t figure out how to essentially remove the img tag when this variable is 1. Is that possible?

  12. #12 jehiah
    2 years, 7 months ago

    Hey, I have an idea for you. You can change the style on an element so that it doesn’t display Given the following tag, you would access it by the “id” attribute, and change the style. To display it again just set the .style.display='';

    <img src="/path/to/img.png" id="forward">
    
    <script>
    document.getElementById("forward").style.display='none';
    </script>
    
  13. #13 hous
    2 years, 7 months ago

    Perfect! That works wonderfully… Thanks for your help!

  14. #14 hous
    2 years, 6 months ago

    I’m having a browser issue with simpleSwap… my mouseovers aren’t working when I view my site with Mozilla, they only work when viewing with IE… is this part of the script or did I miss something?

  15. #15 dcb
    2 years, 6 months ago

    Truly masterful. This is the best mouseover script I’ve seen, thank you for making it so simple to implement.

    I needed a different behavior for one page on my site, so changed mouseover & mouseout to mousedown & mouseup (respectively), do you anticipate any browser compatibility issues for these new triggers?

    It works fine in firefox but I don’t have other browsers to test with.

  16. #16 jehiah
    2 years, 6 months ago

    @dcb:

    You are welcome.

    No browser compatabilities with mousup/down but if it is for something that needs to be used via keyboard as well you might want to experiment with using onfocus/onblur

  17. #17 Anthony
    2 years, 6 months ago

    It’s great and all but how would you add a sound effect to it. (I’ve tryed myself but I’m still trying to get use to javascript)

  18. #18 Anthony
    2 years, 6 months ago

    This is the code I tryed for sound

    sound=”navsound0″

  19. #19 Anthony
    2 years, 6 months ago

    what happened to that comment I posted?

  20. #20 Simon Thomson
    2 years, 6 months ago

    Great Script, but I can not get it to work in a <iframe> page. see www.eluk.co.uk/upton2006/ for example. It works great with the logo but not on the Welcome panel.

  21. #21 Arnold Karpel
    2 years, 5 months ago

    Rollover works fine. I need to change an image and text. The text must be displayed as text not an image. Any suggestions?

  22. #22 Andreas Koehler
    2 years, 4 months ago

    There is one Problem with the onload function. If you have another onload script in your code the script dont work anymore.

  23. #23 jehiah
    2 years, 4 months ago

    Try

    [js]
    window.attachEvent(”onload”,SimpleSwapSetup);
    [/js]

  24. #24 Scottcrew
    2 years, 3 months ago

    Could an onmousedown be used with this script?
    The:
    window.attachEvent(”onload”,SimpleSwapSetup);
    Where would that code be placed?

  25. #25 Drake
    2 years, 2 months ago

    Following code doesn’t work on Firefox
    [js]
    window.attachEvent(”onload”,SimpleSwapSetup);
    [/js]

    Sorry don’t know the solution

  26. #26 Chet
    2 years, 1 month ago

    Jehiah,

    You seem to know this stuff inside out and backwards so I’m hoping you might be able to help me with a problem that relates to image swapping. I’m kind of at a dead end.

    I have a function that swaps out several images on a page. The function is invoked by clicking on a hyperlink. I have this working just fine, but if the user navigates to another page and then uses the browser’s Back button to return to the page where the images were swapped, the original images are shown (and not the images that were swapped). Is there some way to preserve the last swap state?

    You can see this in action (and view the source) here:

    http://www.designityourselfgiftbaskets.com/wine-gift-baskets-wine-baskets.htm

    My problem is that after the products are “filtered” and the images are swapped, the users are clicking on a product and going to the product detail page. When the use the Back button to return to product listing page, the original unswapped images are restored.

    Any help would be greatly appreciated!

  27. #27 eric
    1 year, 11 months ago

    sorry to butt in, but have you thought about using a cookie?

  28. #28 Tim
    1 year, 11 months ago

    Hi! thanks for the great code! a relief to have some meaningful js that i can nut out..

    i have adapted this to trigger disjoint rollovers, and have it working in FF and IE6, but the FF JS console warns

    ‘Element referenced by ID/NAME in the global scope. Use W3C standard document.getElementById() instead.’

    .. i havent been able to figure out where the problem lies, think i must be missing something.. tried googling, no definitive solution…

    for the moment, i can live with the warnings, but its less satisfying :)

    thanks again! regards, tim

    [code]
    function DJSwap(el,which){
    el.src = (which) ? which : el.getAttribute(”origsrc”);
    }

    function DisjointSwapSetup(){

    // define the image which will change:
    var dj = window.document.getElementById(”dj”);

    // save original src
    dj.setAttribute(”origsrc”,dj.src);

    // gather the triggers for the rollover
    var a = document.getElementsByTagName(”a”);

    for (var i=0;iimg = new Image();
    a[i].djsrcimg.src=djsrc;

    // set event handlers
    a[i].onmouseover = new Function(”DJSwap(dj,’” + djsrc + “‘);”);
    a[i].onmouseout = new Function(”DJSwap(dj);”);
    }
    }

    var PreSimpleSwapOnload =(window.onload)? window.onload : function(){};
    window.onload = function(){PreSimpleSwapOnload(); SimpleSwapSetup(); DisjointSwapSetup();}
    [/code]

  29. #29 Jaime
    1 year, 9 months ago

    got the mouseover working, but not when there is a div above it. My buttons have text positioned over them. When you mouse over the text the button doesn’t work. I’m assuming this is because the mouseover action for the div takes precedence. Any workaround?

  30. #30 Donna
    1 year, 9 months ago

    I’m a total novice. Is there a way to edit this code, or, would you recommend a different code were the “_over” image is larger? I want a smaller picture setting on the page, but, a larger one to display on the mouseover.

  31. #31 Donna
    1 year, 9 months ago

    pardon my last question. Duh. I was using a bad file name. This script works wonderfully, especially for someone like me with absolutely no understanding of the script. Thank you very much for providing this code.

  32. #32 jrags
    1 year, 8 months ago

    Great Job! Thanks very much!

  33. #33 bugeye
    1 year, 5 months ago

    Thanks for the scripts! I really like this solution, but I was concerned about failed W3c validation due to the custom img attribute. I have worked up a (somewhat untested) modification that uses the Class attribute as a trigger for swappable images, and then uses a naming convention to target the rollover image. The rollover images are named identically to the originals, but have “_on” added before the “.gif”.

    [code]

    function swapItSetup(){
    var x = document.getElementsByTagName(”img”);
    for (var i=0;iimg = new Image();
    x[i].oversrcimg.src = x[i].getAttribute(”src”).replace(”.”,”_on.”);

            // set event handlers
            x[i].onmouseover = new Function("swapIt(this,'oversrc');");
            x[i].onmouseout = new Function("swapIt(this);");
    
            // set attributes for over and original images
            x[i].setAttribute("oversrc",x[i].oversrc_img.src);
            x[i].setAttribute("origsrc",x[i].src);
        }
    }
    

    }

    [/code]

    I have yet to try this in any browser other than FF/Mac, but we’ll see.

  34. #34 Ed
    1 year, 2 months ago

    Can someone show me an example of #33 bugeye’s Class attribute used as a trigger for swappable images? Thanks!

  35. #35 manta
    1 year, 2 months ago

    WOW! Works like a charm!

    no probs in IE nor in FF.
    I dont think theres a simpler solution.
    Thank you!

  36. #36 Lothario
    1 year, 1 month ago

    Hmm…when I roll over in ie6, the hover-image just stays…perhaps because I’m using a png-transparency fix?

  37. #37 Mark Jeweler
    1 year, 1 month ago

    Jehiah,

    Great solution! Instantly solved a problem I was struggling with. Thanks!

    Took and combined your solution with an incomplete comment of one of your other readers, and someone else I saw out there to overcome a few issues I had :
    1) I wanted to be able to pass validation testing, so no use of the “oversrc” tag
    2) I wanted to be able to easily classify certain images as having this rollover functionality, while others did not.
    3) I did not want to preclude the use of the Class attribute for other formatting of images.

    So a minor variation to your function is as follows:
    function SimpleSwapSetup()
    {
    var images = document.getElementsByTagName(”img”);
    for (var i=0; ioff.”))
    {
    // preload image
    // comment the next two lines to disable image pre-loading
    images[i].oversrcimg = new Image();
    images[i].oversrcimg.src = images[i].getAttribute(”src”).replace(”off.”, “on.”);
    // set event handlers
    images[i].onmouseover = new Function(”SimpleSwap(this, ‘oversrc’);”);
    images[i].onmouseout = new Function(”SimpleSwap(this);”);
    // save original src
    images[i].setAttribute(”origsrc”, images[i].src);
    images[i].setAttribute(”oversrc”, images[i].oversrc
    img.src);
    }
    }
    }

    with this variation, I simply set the SRC attribute to the original image filename, with an “off” suffix prior to the extension (i.e., src=”myfile.jpg” becomes src=”myfileoff.jpg”), and then add a corresponding “on” suffixed image (i.e., src=”myfileon.jpg”). Thus under normal conditions, the _off image is displayed, and during a mouse-over, the _on image is displayed.

    If I don’t want an image to have any rollover capability, I leave out the _off suffix, and the function ignores it.

    Hope this is useful to someone else!

  38. #38 James
    11 months, 4 weeks ago

    Great piece of code!
    I just have a problem with it. I try to place several swap images one beside another with no space between them as a simple menu. When I use your js it just adds a default space spoiling the side-by-side effect.
    Is there any way to add CSS or hspace on these images?

  39. #39 shann
    10 months, 3 weeks ago

    oww… Im a beginner and rollover images using codes are one of our projects in school… using html in notepad! so all of those rollover tags really have javascript codes??? Isnt there any code thats only for HTML??? pweeaassee… tell me!… T_T

  40. #40 Shaun
    9 months, 2 weeks ago

    Unfortunatly as per a comment above about Dean Edwards IE7 script working with this… It does NOT.

    The image rollover changes fine but does not change back.

    Is there any way to tweak this and make it work?

  41. #41 Cristian
    9 months, 1 week ago

    This is awesome!!! Thanks for sharing!

  42. #42 Katherine
    8 months, 4 weeks ago

    Yeah, doesn’t work if you’re using a png fix in ie6.

  43. #43 Michael
    8 months, 2 weeks ago

    This is indeed great. Nice, streamlined and effective, and great for someone who has written nearly no JavaScript in the past 5 years. I have a question, though - what Creative Commons license do you offer this under - Attribution?

    Thanks

  44. #44 Marcus
    6 months, 3 weeks ago

    Hello,

    thanks for the nice little javascript.
    only disadvantage with it is that oversrc is not a valid attribute for img tag.

  45. #45 Gregg
    6 months, 1 week ago

    Anyone else having safari problems?

  46. #46 Leah
    6 months ago

    Thank you for such an elegant script. I’m using it to create a seamless-transition photo portfolio for a friend.

    I’m wondering if it’s simple enough to add a double mouseover event- everything’s working perfectly, but I’d like not only to swap out photos on click, but somehow swap out the photo link as well- please take a look at my file in test for clarity.

    If anyone has suggestions, I’d appreciate them- my javascript is weak, I don’t know where to begin. Thanks again!

  47. #47 Michelle
    5 months, 1 week ago

    I am a web developer HAHA… well I try to be, for this website, and I’ve always wanted to have a function whereby the customer clicks on a picture of the vehicle (in the more detailed page), and that picture swaps to the bigger image on the top left hand side. The problem is, the pictures cannot be preloaded; I use asp coding, and it calls the pictures by rows.

    Any suggestions?

  48. #48 Ari
    3 months, 2 weeks ago

    Hi jehiah, thanks for sharing this script. I am trying to use the it, but for some reason, when I use it more than once on a page, it only works on the last instance… I am trying to figure it out, but to no avail. Any ideas or suggestions?

  49. #49 Ari
    3 months, 2 weeks ago

    Hi… I figured it out, I goofed. Thanks for writing a great script!

  50. #50 enco
    2 months ago

    Great code. Thank you. Can somebody post the complete code without ‘oversrc’ so that it is W3C standard compatible — I am java script beginner.

  51. #51 Travelmonger
    1 month, 2 weeks ago

    Hello there,

    I’ve been looking fr a script like this for my new website. It’s great and the comments of users have also helped me a lot.

    Thing is that… this script is quite complex, long even and takes some time to understand it and get the hang of it.

    Until now I’ve been using Frontpage’s swap effect and it created tremendous errors in certain browsers…

    Thanks for the script!

Leave a comment