title: Dynamically Preloading/Displaying Webcam Snapshots on a Web Page Using AJAX
body: <p>I have an IP Camera that streams out live video to a web site of mine.  Problem is, it is powered by an ActiveX control.  Even worse, this control is unsigned.  To provide a more secure alternative to the people that are using browsers other than IE, or are (rightfully) unwilling to change their security settings, I am tapping into the cameras built in snap-shot script that serves up a 640x480 live JPEG image.  The plan was to update the image live on the screen every ~500ms using Javascript without having to reload the entire page.</p>
  
  <p>I tried using the Image() object to pre-load the image and update the SRC attribute of the image element when onload fired:</p>
  
  <pre><code>function updateCam() {
    var url = "../snapshot.cgi?t=" + new Date().getTime();
    img = new Image();
    img.onload = function() {
      $("#livePhoto").attr("src", url);
      camTimer = setTimeout(updateCam, 500);
    }
    img.src = url;
  }
  </code></pre>
  
  <p>This worked decently, but it was difficult to determine when the camera had been disabled, which I needed to do in order to degrade gracefully.  The internal snapshot script is setup to return an HTTP status code of 204 (No Content) under this circumstance, and of course there is no way for me to detect that using the Image object.  Additionally, the onload event was not 100% reliable.</p>
  
  <p>Therefore, I am using the jQuery (version 1.2.6) <code>ajax</code> function to do a GET request on the URL, and on the <code>complete</code> callback I evaluate the status code and set the URL accordingly:</p>
  
  <pre><code>function updateCam() {
    var url = "../snapshot.cgi?t=" + new Date().getTime();
  
    $.ajax({
      type: "GET",
      url: url,
      timeout: 2000,
      complete: function(xhr) {
        try {
          var src = (xhr.status == 200) ? url : '../i/cam-oos.jpg';
          $("#livePhoto").attr("src", src);            
        }
        catch(e) {
          JoshError.log(e);
        }
  
        camTimer = setTimeout(updateCam, 500);
      }
    });
  }
  </code></pre>
  
  <p>And this works beautifully.  <strong>But only in IE!</strong>  This is the question that I would like to have answered: Why doesn't this work in Firefox or Chrome?  The <code>complete</code> event does not even fire in Firefox.  It does fire in Chrome, but only very rarely does setting the SRC actually load the image that was requested (usually it displays nothing).</p>