tags:

views:

104

answers:

6

Is there a way to tell the browser to look down a list of image URLs until it finds one that works? Pure HTML would be preferred, but I'm guessing JavaScript is probably necessary here (I'm already using JQuery, so it's not an issue).

EDIT: Thanks for your answers! I'll add a few clarifications:

  1. By "works" I mean the image can be displayed.
  2. I specifically want to do this on the client side.
A: 

You could enter the URL of some server-side application/script that serves up the image from whatever image source it can find.

You could do this in ASP.Net with an HTTPHandler that sends a response of content-type=image/jpg.

Other than ASP.Net there are amny other server-side options such as Perl, PHP...

rohancragg
A: 

Assuming you mean the browser being able to retrieve some content with an HTTP response code 200 for a specific URL, then the answer is : NO from the client side using only HTML.

In other words, you can't have an element (e.g. img) and specify multiple URLs to "try".

Of course you can craft something on the server side: a request comes in for resource X and the server has a list of URLs that "work".

jldupont
+1  A: 

INAJNBAM (I'm not a Javascript Ninja by any means), but in pseudo code, maybe try something like this after the page has loaded: (OR, now that I think about it, this would work well with PHP too)

$images = array('img1.jpg', 'img2.jpg', 'img3.png'....)
    foreach $images as $img
        {if $img.height > 0px
            {print "<img src="$img" />"
            end}
        };;;;

In fact PHP would be even better because I presume in JS this would result in images flashing up on the screen at the end of the pageload. Try it out in PHP and see if something like this fits your bill.

NOTE: I added 4 semi colons at the end. I know Javascript always wants 'em, I just didn't know where to stick them.

Alex Mcp
+1  A: 

If I am reading the specification correctly, you should be able to do this with the HTML object element. <object> tags can be nested and thereby provide a chain of resources that are tried each in turn to be rendered and upon failure the user agent continues with the next one.

Note, though, that this behaviour is/was buggy for several browsers and versions.

Joey
Yeah, unfortunately it still isn't really usable thanks to poor support in current IE versions. +1 for the way it was *supposed* to be done though.
bobince
According to http://msdn.microsoft.com/en-us/library/cc304133%28VS.85%29.aspx it works as of IE 7, although the DOM was faulty back then. MS claims it's fully supported in IE 8, including DOM accessibility for disabled nested objects.
Joey
+1  A: 

If by saying "works" you mean the image can be loaded, you can use the "load" function on an image( in your case a bunch of images) of jQuery and inside of it declare the functionality that will be fire once the loading of the an image is completed.

If by saying "works" you mean that the HTTP status code is ok then use an ajax call using jquery.

function getUrlStatus(url) {
     $.ajax({
         url: url,
         complete: function(xhr) {
             return xhr.status;
         }
     });
 }
StarScream
+1  A: 

This seems like a bad idea to me. What is the purpose of this feature? It sounds like you want something equivalent to this:

<img src="/images/file1.jpg" src2="/images/file2.jpg" src3="/images/file3.jpg">

Where the browser would try each file in succession. The problem with this approach is that it significantly increases the http traffic required and the latency. The best approach is to dynamically construct the page using the correct image tags ahead of time. Using a server-side approach you can try to load the image from the disk (or database or wherever the images are) and dynamically include the best url in the page's image tag.

If you insist on doing it client-side, you can try loading multiple image tags:

<img src="file1.jpg" alt="" onerror="this.style.display='none'">
<img src="file2.jpg" alt="" onerror="this.style.display='none'">
<img src="file3.jpg" alt="" onerror="this.style.display='none'">
<img src="file4.jpg" alt="" onerror="this.style.display='none'">
<img src="file5.jpg" alt="" onerror="this.style.display='none'">
<img src="file6.jpg" alt="" onerror="this.style.display='none'">

This will result in a page that appears to have lots of images but they disappear as the page loads. The alt="" is required to make Opera not show the broken image placeholder; the onerror is required for Chrome and IE.

If that's not spiffy enough, and if all your images are the same size, and that size is known, you could stack a bunch of images one on top of the other, so that the first image that loads hides all the others. This worked for me in Opera, FF, and IE8. It loads the last image in the list that exists. Note that this wastes bandwidth and memory because every image is loaded.

<div style="width: 50px; height:38px; background-image: url(file1.jpg);">
<div style="width: 50px; height:38px; background-image: url(file2.jpg);">
<div style="width: 50px; height:38px; background-image: url(file3.jpg);">
<div style="width: 50px; height:38px; background-image: url(file4.jpg);">
<div style="width: 50px; height:38px; background-image: url(file5.jpg);">
<div style="width: 50px; height:38px; background-image: url(file6.jpg);">
<div style="width: 50px; height:38px; background-image: url(file7.jpg);">
</div></div></div></div></div></div>

Finally, there is the JavaScript approach:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&gt;
<html>
  <head>
    <title></title>
    <script type="text/javascript">
      var image_array = ['file1.jpg', 'file2.jpg', 'file3.jpg', 'file4.jpg', 'file5.jpg','file6.jpg' ];
      function load_img(imgId, image, images, index) {
        image.onerror = function() {
          load_img(imgId, this, images, index+1);
        };
        image.onload  = function() {
          var element = document.getElementById(imgId); 
          if (element) {
            element.src = this.src; 
            element.style.display = 'block';
          }
        };  
        image.src = images[index];
      }
    </script>
  </head>
  <body>
    <img id="id_1" alt="" style="display: none;">
  </body>
  <script>
        load_img('id_1', new Image(), image_array, 0);
  </script>
</html>
Mr. Shiny and New