title: preload image with ajax
body: <p>Found this technique of using ajax to preload things at: <a href="http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/">http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/</a></p>
  
  <pre><code>window.onload = function() {
      setTimeout(function() {
          // XHR to request a JS and a CSS
          var xhr = new XMLHttpRequest();
          xhr.open('GET', 'http://domain.tld/preload.js');
          xhr.send('');
          xhr = new XMLHttpRequest();
          xhr.open('GET', 'http://domain.tld/preload.css');
          xhr.send('');
          // preload image
          new Image().src = "http://domain.tld/preload.png";
      }, 1000);
  };
  </code></pre>
  
  <p>I noticed that the 'ajax' preloading for this image isn't really ajax at all. It is the same as what I have been using for years already, just setting the url in a new image object's source and letting the browser load it into the cache.</p>
  
  <p>Now imagine that there was an application where, I needed to actually cancel the preloading of the image if it took over a certain amount of time. There really is no good way to do this with just setting the image to src, unlike the xhr.abort() method which stops the loading of an actual xhr request.</p>
  
  <p>Is there any reason that doing some thing like the below wouldn't preload the image just as well and allow the cancellation of the preload request?</p>
  
  <pre><code>function preload(url, timeout){
      this.canceltimeout = function(){
          clearTimeout(this.timeout);
          this.loaded = true;
          return false;
      }
  
      this.abort = function(){
          this.xhr.abort();
          this.aborted = true;
      }
  
      //creates a closure to bind the functions to the right execution scope
      this.$_bind = function(method){
          var obj = this;
          return function (e){ obj[method](e);};
      }
  
      //set a default of 10 second timeout
      if(timeout == null){
          timeout = 10000;
      }
  
      this.aborted = false;
      this.loaded = false;
      this.xhr = new XMLHttpRequest();
      this.xhr.onreadystatechange = this.$_bind('canceltimeout');
      this.xhr.open('GET', url);
      this.xhr.send('');
      this.timeout = setTimeout(this.$_bind('abort'), timeout);
  }
  
  var llama = new preload('/image.gif');
  show_image();
  
  function show_image(){
      if(llama.loaded){
          var l = new Image();
          l.src = '/image.gif';
          application.appendChild(l);
      }else if(llama.aborted){
          var l = document.createElement('p');
          l.innerHTML = 'image.gif got cancelled';
          application.appendChild(l);
      }else{
          setTimeout(show_image, 10);
      }
      return false;
  }
  </code></pre>