Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chrome/Firefox Content Scripts: Hiding <img> while image is loading appears to break other <img>s with same src

I created an addon for Chrome and for Firefox and I noticed some weird behavior now.

Basically, this extension allows one to switch between normal view and a special "read mode" on certain webcomic sites. To do that, it will hide all existing elements using a CSS rule and create a new <img> element which is inserted into the body and gets the same URL set as the existing <img> element which originally showed the comic.

Now the behavior I observed, which happens in both browser by the way, is: When you switch the mode while the image is still being loaded, weird stuff happens: It looks like one of the <img> tags will continue working (usually the one where the image started loading, but not always), but the other one will just keep showing a "broken image" icon for the rest of the time the user stays on the page. Interestingly, it looks like this can even happen with the <img> tag which is dynamically created/deleted (not just shown/hidden) when the mode is switched...

I think this is a pretty strange behavior, I would expect that hiding an image would either not stop the loading, or pause it and continue or restart it when another <img> tag with the same src is displayed, but not that things break like that.

The relevant code part is:

var $s, $c;
var setState = function(readModeEnabled, allowScrolling) {
    if($s) {
        $s.remove();
        $s = null;
    }
    if($c) {
        $c.remove();
        $c = null;
    }
    if(readModeEnabled) {
        if(allowScrolling) {
            $s = "<style id='cherry-read-mode'>*{display:none !important;} html,body{display:block !important;width:100%;height:100%;text-align:center;} #cc-comic-2{display:inline-block !important;max-width:100%;}";
        } else {
            $s = "<style id='cherry-read-mode'>*{display:none !important;} html,body{display:block !important;width:100%;height:100%;text-align:center;overflow:hidden;} #cc-comic-2{display:inline-block !important;max-width:100%;max-height:100%;}";
        }
        $("head").append($s);
        $s = $("#cherry-read-mode");
        $c = $("<img id='cc-comic-2'/>").attr("src", $("#cc-comic").attr("src"));
        $("body").append($c);
    }
};

(readModeEnabled is what's toggled. The $s trick using the ID there was used only because I noticed that $("<style>something</style>").appendTo(...) didn't set the content of the style tag correctly, but $(...).append("<style>something</style>") does.)

Do I do anything wrong? What is the problem there, what is the best solution?

EDIT: I was unable to reproduce the behavior on jsfiddle, which is weird. This fiddle comes very close to how it works in the real case, but there everything is OK...

EDI2: Now it appears that this only happens from an extension! I ruled this out at first because it's both in Chrome and Firefox, and they use different rendering engines and everything... But the thing is, when I open Chrome, go to http://sleeplessdomain.com, enable throttling in the devtools to "Good 2G" so that the images load slowly, then copy the fiddle code into the console (plus code to load jQuery) and then play with the Enter key, it works!

EDIT3: I now even copied the whole content script including jQuery into the devtools console and then it works fine. So it appears to be an issue with content scripts, but in both Chrome and Firefox!

EDIT4: Ohhh. The difference in the above edits was that I used Enter instead of ESC - in the extension I have ESC as key binding. And I didn't realize that it's used also for aborting page load. e.preventDefault() did it... I feel kinda dumb now ^^

like image 957
CherryDT Avatar asked Oct 18 '22 11:10

CherryDT


1 Answers

The difference between my tests and the real case was that I used Enter instead of ESC - in the extension I have ESC as key binding. And I didn't realize that it's used also for aborting page load. e.preventDefault() did it...

like image 199
CherryDT Avatar answered Oct 30 '22 05:10

CherryDT