greduan
greduan

Reputation: 4938

Once an image has failed loading, how can I make the browser retry?

I'm making a Chrome extension which in order to reduce bandwidth usage it stops all outcoming requests which are images.

I want to provide functionality where if the user clicks on the image (or technically a layer on top of that image) it would try to reload the image, this time not being blocked by the extension.

How can I tell the browser to retry loading the image? And if there isn't a straightforward way to do it, what would be a work around? Deleting the old image from the DOM and adding it again?

Any help is appreciated. :)

EDIT 1:

To answer @CBroe's question:

Using the chrome.webRequest.onBeforeRequest API in a background script.

To answer @jfriend00's question:

The usual placeholder "couldn't load image" icon, I guess also known as "broken file" icon:

broken file icon example

See all those broken images?

That screenshot also illustrates the point of a layer on top of another image. Should those images not be broken, the loaded image would be there but that layer (the one in a dark grey which shows the image's dimensions) still remains there.

The desired href still exists there in the img tag:

example of a broken img tag which retains href

Upvotes: 3

Views: 3000

Answers (4)

ic3b3rg
ic3b3rg

Reputation: 14927

The simple way to force reloading an image in JavaScript is:

var img = document.getElementById("myImage");
img.src = img.src.replace(/\?.+/,"") + "?" + new Date().getTime();

This adds a unique QueryString to the image which basically forces the browser to not use a cached version of the image.

Upvotes: 0

C3roe
C3roe

Reputation: 96383

If simply assigning the same src value to the img element is not enough¹, then create a new Image object in JavaScript, and assign the value to its src property.


¹ It might not be, if the browser just goes, “oh hey, that is the same value for the src attribute that the img already had, so I don’t have to do anything” – creating a new JS Image object however should make the browser request that resource again if he realizes he does not have it cached already.

Upvotes: 1

Beejor
Beejor

Reputation: 9398

While I'm not too familiar with the Chrome API, a quick glance seems to suggest that there's no way to get the specific img element from each onBeforeRequest, which you'd need to know in order to figure out where to attach custom code.

This may be better accomplished with native JavaScript of some sort. For example, if Chrome lets you inject code on load, you could apply a function like the one below to all img elements after document load but before image load.

// Given an img element, replaces its src with a placeholder URL,
// and sets its click action to load its original src
function makePlaceholder(elem){
    elem["data-oldtitle"] = elem.title;
    elem["data-oldhref"] = elem.href;
    elem["data-oldsrc"] = elem.src;
    elem["data-oldonclick"] = elem.onClick;
    elem.title = "Click to load the blocked image.";
    elem.href = '';
    elem.src = "http://example.com/placeholder.png";
    elem.onClick = function(){
        this.src = this["data-oldsrc"];
        this.title = this["data-oldtitle"];
        this.href = this["data-oldhref"];
        this.onClick = this["data-oldonclick"];
    };
}

Upvotes: 0

Brad
Brad

Reputation: 163438

What I would do instead is replace the URLs of the images with an image from your extension. A 1x1 pixel transparent GIF or PNG.

When you do this, add an attribute to all of the elements you replaced... something like data-yourextension-originalurl, with the URL of the original image. If the user then wants to load images, it's easy enough to go back and fix those image elements.

Upvotes: 0

Related Questions