1

I want to write a Chrome extension that will change the src= value of an img element before the image is loaded.

I have the code to change the image, but it always executes after the img has loaded. How can I change the url in SRC before the image is loaded?

Gregg
  • 9
  • 1
  • 2
  • possible duplicate of [Chrome Extension - override .js file](http://stackoverflow.com/questions/7931565/chrome-extension-override-js-file) – apsillers Aug 07 '12 at 15:30

3 Answers3

4

You should:

  1. Make sure the run_at property of the content script is document start.
  2. Place your image rewriting code in a beforeload event handler.

Your script should look like:

String.prototype.endsWith = function(str) {
    return this.substr(str.length*-1) === str;;
};

function doBeforeLoad(event) {
    // Check to see if its what you want to redirect
    // You can check against different things about the element, such as its type (tagName), id, class, whatever
    // Be aware that if your checking the src attribute and it was a relative path in the html then the src you recieve will be resolved....
    // so if the html was <img src="/bunyip.png"> and the base url is www.google.com then the event.srcElement.src will be www.google.com/bunyip.png
    // this is why I use the ends with...so you dont have to deal with things like http://www.google.com, https://www.gooogle.com, http://google.com 
    // We also check for a data attribute that we set, so we know its allready been redirected
    // we do this because if you redirect a source it will fire another beforeload event for its new url
    if (!event.srcElement.dataset['redirected'] && event.srcElement.tagName == "IMG" && event.srcElement.src.endsWith('/test.png')) {
        // If it is something we want to redirect then set a data attribute so we know its allready been changed
        // Set that attribute to it original src in case we need to know what it was later
        event.srcElement.dataset['redirected'] = event.srcElement.src;
        // Set the source to the new url you want the element to point to
        event.srcElement.src = "replacement.png";
    }
}

document.addEventListener('beforeload', doBeforeLoad, true);
PAEz
  • 8,366
  • 2
  • 34
  • 27
apsillers
  • 112,806
  • 17
  • 235
  • 239
  • 2
    If this doesn't work, another option is to use the beforeload event. – PAEz Aug 07 '12 at 03:02
  • @PAEz The `beforeload` event should be used for this task. Please post it as an answer if I do not find a duplicate question. – Rob W Aug 07 '12 at 12:57
  • @RobW I've corrected my answer, but it is [indeed a duplicate](http://stackoverflow.com/questions/7931565/chrome-extension-override-js-file), answered by PAEz, in fact. The duplicate is about scripts instead of images, but the answer is identical. – apsillers Aug 07 '12 at 15:29
  • 1
    @Rob W Hope its OK, but I changed the source to deal with a couple of things. Mainly the fact that changing the src will fire another beforeload for the new url. Added a bunch of comments to explain it all. – PAEz Aug 07 '12 at 18:07
  • Looks good. Another suitable alternative (without using the `beforeload` event) is the [`chrome.webRequest`](http://code.google.com/chrome/extensions/webRequest.html) API (to redirect images). This has to be implemented in the background page, and is preferred over `beforeload` if certain images always have to be redirected. – Rob W Aug 07 '12 at 20:42
0

Take a look at Avoid jQuery (pre)loading images or construct a DOM tree from a string without loading resources (specifically images). I ran into this a little while ago and my solution was essentially the same (replace the src attribute in the html string with 'blah=' and then add my own src). As it says in the link, if you're using jquery don't use $(html) because as soon as it parses it will fetch the image.

Community
  • 1
  • 1
tterrace
  • 1,955
  • 1
  • 16
  • 19
  • 1
    Just a little tip incase you want to do things the way your suggesting....Those answers are old, in Chrome and other modern browser (IE9+ for instance) your much better of using createHTMLDocument http://www.quirksmode.org/dom/w3c_html.html#t12 ...look it up, its REALLY handy because you can use things like querySelector and any other dom methods. – PAEz Aug 07 '12 at 18:45
  • Do you mean use createHTMLDocument, find the `` element, insert my html string inside of that, and then use querySelector? That's not excessively verbose but it's not `$(str).find('img');` either. – tterrace Aug 07 '12 at 19:12
  • 1
    Its actually better than that, you pass the whole pages html in and you have a parsed dom with body and what not. And it doesnt get images, execute scripts, that sorta thing. Then you can do your stuff and get its innerHTML to use. Just keep in mind that the returned html will have been reformatted to something that the browser thinks is valid..so if you had something like `some naughty text
    ` Chrome will put the text outside the table as it doesnt see it as valid, which it will do when it renders it anyways. a simple example http://stackoverflow.com/a/10896868/189093
    – PAEz Aug 07 '12 at 19:30
  • 1
    oh...and this might interest you aswell.... http://stackoverflow.com/questions/11638509/chrome-extension-remove-script-tags/11669581#11669581 ...it shows how to replace a pages content – PAEz Aug 07 '12 at 19:41
  • Oh nice, that's really clean and concise. I'm definitely going to use this method in my project. Thanks! – tterrace Aug 07 '12 at 20:39
0

If you know the url pattern, you can use the webRequest API-http://developer.chrome.com/extensions/webRequest.html, to block and redirect the image calls. However this won't change src, you can do it later. This will prevent even the GET call for that image source.

Originally from - How can I prevent loading from <img> via content script?

Community
  • 1
  • 1
chandaniitr
  • 185
  • 6