Search code examples
jqueryfavicon

Trouble on retrieving 'favicon.ico' images using AJAX HTTP requests


I am using Ruby on Rails v3.0.9 and jQuery 1.6. I am trying to retrieve and display the favicon image from some web sites.

For instance, in order to do that for a single web site I am using the following code:

$jQ.ajax({
  type:    'GET',
  url:     'http://www.facebook.com/favicon.ico',
  data:    '',
  error:   function(jqXHR, textStatus, errorThrown) {
    $jQ('#facebook_favicon').replaceWith('ERROR');
  },
  success: function(data, textStatus, jqXHR) {
    $jQ('#facebook_favicon').replaceWith("<img width='16px' height='16px' src='http://www.facebook.com/favicon.ico' />");
  }
});

I use the above code that performs an HTTP request in order to check if the favicon was found: if so (on success), it will replace the #facebook_favicon related to an HTML tag with the just found favicon.ico image otherwise it will replace that with an ERROR text.

However, when I load the page where the above JavaScript is placed and I inspect the Firebug Console I get the following:

firebug console errors

It means that the request was successfully performed (HTTP status codes are all 200, except for Gmail) but I can not display the icon image on success. Why? What is the problem?

I noted that in Firebug Responses are all blank, like this:

firebug console errors

What I can do to accomplish what I would like to make (I am referring mostly to check if a web site favicon is found)?


If I use code like the following it will work but it doesn't check the favicon presence:

$jQ('#facebook_favicon').replaceWith("<img width='16px' height='16px' src='http://www.facebook.com/favicon.ico' />");

Solution

  • You can't do XmlHttpRequests on URLs that are not on the same domain/port/protocol than the current page.

    You can, however, check that an image exists by using an Image object and the onload and onerror events:

    var img = new Image;
    var src = 'http://www.facebook.com/favicon.ico';
    img.onload = function() {
        // the image exists, display it
    };
    img.src = src;
    

    You can wrap this in a function:

    function imageExists(src, callback) {
        var img = new Image;
        img.onload = function() {
            callback(src, true);
        };
        img.onerror = function() {
            callback(src, false);
        };
        img.src=src;
    }
    

    And use it like this:

    imageExists('http://www.facebook.com/favicon.ico', function(src, exists) {
        if (exists) {
            $('body').append('<p>The image loaded correctly!</p>');
            $('<img>').attr('src', src).appendTo('body');
        } else {
            $('body').append('<p>oops, error</p>');
        }
    });
    

    Test it here: http://jsfiddle.net/YpBsJ/2/