4

I'm currently finishing a huge Backbone.js application with JQuery, RequireJS and Underscore.

There are many images in my underscore template (lots of .png) and it's a little bit long to append() || prepend() these templates in my current view.

So there is a good way to do what I do ? I'm looking for a library or an example to do preloading on my templates.

Awea
  • 3,163
  • 8
  • 40
  • 59
  • Is this substantially different from [these questions](http://stackoverflow.com/search?q=jquery+preload+images)? Are you looking for a way to automatically pull the list of images to preload out of your template code, for example? – nrabinowitz Jan 20 '12 at 20:25
  • Yeah i'm looking for what you say, I found this http://www.gayadesign.com/diy/queryloader2-preload-your-images-with-ease/ but If I use something like this how can I did it with backbone/requireJs/Underscore ? I need to adapt this library for working with require.js right ? – Awea Jan 20 '12 at 20:49

2 Answers2

8

I don't think you necessarily need a library for this, unless there's one specifically for use with templates. As detailed in these related questions, preloading images is relatively simple:

$("<img />").attr("src", url);

will preload the image at url. It's pretty obvious that you can apply this easily to an array (here using $.each for concise syntax):

function preload(urls) {
    $.each(urls, function(i, url) {
        $("<img />").attr("src", url);
    });
}
preload(['/images/1.png', '/images/2.png', ... ]);

You don't need a library for this. The hard part, in your case, is generating the list of URLs to preload. It's impossible to know the best approach here without understanding your templating system better, but here are a few approaches:

  • If you have your templates available as DOM objects in memory, then you can loop through them using something like $('img').map(function() { return $(this).attr('href') }) to find the URLs. But if you're using Underscore templates in <script> tags and you don't make them into DOM objects until you render the view, then this is unlikely to work - it's going to be a pain and somewhat processor-intensive to render them with dummy data just for the purpose of extracting URLs.

  • If you use a build system like Ant, and if your templates are fairly separate from your other code (e.g. each template in a separate file), then you might consider using regex to parse the templates for URLs and then sticking them into an array in a Javascript file, which you can use for input to your preloader. This is a pretty complicated build task, but it's probably the best option from a performance standpoint, as all the template parsing happens at build time, not at run time.

  • Another build system approach, probably simpler, would be to put all images you want to preload into a given directory, and then put every file under that directory into the Javascript array. This is probably the easiest approach with Ant, though it might require you to revise your directory structure for images.

  • You can always make your array of URLs by hand, but it will be a pain to keep it up to date with a complex set of templates.

  • If you have a complex app and you want to only preload certain images at any given time, you'll probably need to identify those images by hand, and then call preload(upcomingImages) at the appropriate time for the appropriate set of images.

Community
  • 1
  • 1
nrabinowitz
  • 55,314
  • 10
  • 149
  • 165
  • Thanks for your great answer I prefer to do not use a library (because I need to make it work with requireJS). I think i'm going to preload img by using an array of them to append them in my view or something like that :) – Awea Jan 21 '12 at 00:43
  • You know I find this amazing that this same code also works to preload background images used for divs. Even though it looks like we are preloading images into tags, it seems to preload the image and makes it useable anywhere in the site that references the same src. So you can use this to preload any image used on the site, not just images inside tags. – Nearpoint Mar 27 '14 at 12:47
1

If you need a more granular control you can use the DOM's Image object. Like:

var img = new Image();

img.src = 'image.png';

img.load = function () {
  console.log('image.png is fully loaded');
}

You will need to queue the image urls and at least one callback.

a simple worker would look like:

function worker (url, callback) {
  var img = new Image();
  img.src = url;
  img.load = callback;
}
LoG
  • 1,141
  • 9
  • 15