3

I currently have a rollover button implemented in rails as follows:

<%= image_tag("header/home_but.gif", :mouseover => "header/home_over.gif") %>

How can I preload/cache the mouseover image (home_over.gif) so there is no delay when the user moves their mouse over the image? Thanx.

Chris C
  • 373
  • 7
  • 17

3 Answers3

6

Are you sure you don't want a CSS Sprite here? Basically you put your image states into one image (Photoshop), set the image as the background of an anchor element, then adjust the visible area with CSS for the background property and the :hover and :visited states. Only one image has to download this way.

Andrew Atkinson
  • 1,155
  • 8
  • 20
  • I actually ended up removing the rollover buttons altogether and going with standard links with a single background_image of the div set. A CSS Sprite would have worked but deep down inside I really wanted to get rid of the images to reduce the loading time and make it easier to add more menu items in the future. Thank you for your answer and the link to CSS Sprites which will come in handy in the future. – Chris C Nov 13 '09 at 05:48
2

My environment uses jQuery, so I wanted the solution to use jQuery as well.

I found another question about preloading images with jQuery, and it's top answer had the jQuery prewritten for me. I adapted my code as follows into ERB:

<% alternate_images = [] %>
<% @resources.each do |resource| %>
  <%= image_tag(resource.primary_image.url, :mouseover => resource.alternate_image.url) %>
  <% alternate_images << resource.alternate_image.url %>
<% end %>
<script type="text/javascript">
$.fn.preload = function() {
    this.each(function(){
        $('<img/>')[0].src = this;
    });
}
$([<% alternate_images.each do |image| %>
     "<%= image %>",
   <% end %>]).preload();
</script>
Community
  • 1
  • 1
Strand McCutchen
  • 3,157
  • 1
  • 16
  • 8
0

I'm not a rails programmer, but my understanding is that Rails uses Prototype by default. Assuming that, you could include this JavaScript:

Prototype.preloadImages = function(){
    for(var i=0, images=[]; src=arguments[i]; i++){
        images.push(new Image());
        images.last().src = src;
    }
};

Then add this code wherever your onload code runs. Maybe something like this:

Event.observe(window, 'load', function(){
    Prototype.preloadImages('header/home_over.gif','another/image/to/preload.gif');
});

You'll have to assure that whatever magic image_tag() does is done to the image paths to assure that the correct image is preloaded.

artlung
  • 33,305
  • 16
  • 69
  • 121
  • Something to be aware of here is that Rails' `image_tag` helper by default will append timestamps to asset paths to allow for instant cache invalidation upon a file change. It's really hard to live without this once you are used to it, and I'd recommend avoiding hacking something new together for this. I suggest Andy Atkinson's answer for that reason. – Barry Hess Nov 11 '09 at 03:59
  • Very interesting, though the implication is that Rails has a strong bias against mouseovers. Learn something new everyday. :-) – artlung Nov 11 '09 at 07:51
  • Rails does the same timestamp appending to the mouseover images, I believe. The only negative here is that it hasn't abstracted preloading images, which I don't think can really be considered a "bias against mouseovers." Using the CSS Sprite technique should be equally achievable in Rails as in any web framework. – Barry Hess Nov 11 '09 at 15:34
  • Thank you for letting me know about the timestamps Barry. As artlung said, lean something new every day. – Chris C Nov 13 '09 at 05:39