I have a very interesting task:
I have few "images" like that:
var image = new Image();
image.src='https://www.hootv.lt/bitrix/spread.php?s=QklUUklYX1NNX1VJREgBbjVkZXNEQ2IzVnU4ckRSSmlCbW82R0xKdmNWcUV2UzUBMAEvAQExATECQklUUklYX1NNX1VJREwBMzcwNjU0NTQyMDcBMAEvAQExATECQklUUklYX1NNX1VJREQBMjVwbmJzNjNkY2VrNGRuZ2VmaGEyYXZsMm1taGh6YWMBMTcyNjMzNjUzMAEvAQExATECQklUUklYX1NNX05DQwFZATE3MjYzMzY1MzABLwEBAQJCSVRSSVhfU01fQ0MBATABLwEBAQI%3D&k=c545bd21253d81d854fc3698d4b20854';
An image src is a PHP page which returns nothing. I have to check whenever all images generate error, than continue executing script.
So my script should look like something like that:
<script> - My code
var image = new Image();
image.src='url1';
var image = new Image();
image.src='url2';
var image = new Image();
image.src='url3';
...
var image = new Image();
image.src='url33';
</script>
(after all images generate onerror event continue with)
<script> - CMS generated code I cannot change
windows.location.href = "..."; (i cannot change line, all I can do is inject the script above)
</script>
I tried the following but obviously it’s not working:
while (!image.error) {
//wait
}
3
Answers
First of all I would like to say big thanks to @CherryDT and @AztecCodes for being so involved in my problem!
It seems like the problem I faced doesn't have a straightforward solution so I ended up modifying CMS source code for my needs.
New Approach:
Under these constraints consider using a
MutationObserver
to monitor changes in the document.scripts collection. When the unwanted script is added, remove it. Once image processing is complete re-insert the script.Please check out the Answer from CherryDT because his approach could help too.
The adjusted Script:
Update:
Because of Browser limitations here is an adjusted version of the script:
This is a tricky problem. I have a solution but it is a hack (of course), because this is not something that normally needs to be done. I don’t even know whether this will work on all browsers, and for how long it will work (but I tested on Chrome 116 and Firefox 117 and it was OK in those).
First a big warning:
This is not recommended. It’s a big hack. Use at your own risk.
But I understand that desparate times call for desparate measures. I hope this is a temporary solution and you’ll spend some time later to figure out how to solve the issue in your CMS (perhaps you can write a plugin which hooks the part of the CMS that inserts this code and stops it from doing so).
You can’t stop the code below from running, at least I couldn’t come up with any way to do that (even a
MutationObserver
will fire after the code ran, I checked). So we can try to do the next best thing, which is stopping the redirection from executing.I tried redefining
window.location
andwindow.location.href
but that’s not possible because those properties are defined withconfigurable: false
by default. We also can’t play tricks on theWindow
orLocation
prototypes. But what we can do is overwrite the redirection with our own redirection, but this time to a page that returns a status code 204 which will essentially cancel the navigation!This is what I came up with, after some playing around and testing ideas:
This will cancel the next navigation attempt. You can later navigate yourself. If the URL that the page redirects to is not fixed and you need to know what it was so you can redirect to it later, you can save it within the event handler, and access that variable later (e.g. after all your images failed to load):
A few things to note here:
https://www.google.com/gen_204
to return status 204. It’s probably better if you add your endpoint that returns status 204 and use that instead.DOMContentLoaded
event handler that removes thebeforeunload
event handler.setTimeout
is required. Attempting to changelocation
from within the invokation of thebeforeunload
handler is silently ignored by the browser.Note: I didn’t explain how to actually wait for the images to fail loading, only how to stop the navigation (the trickier part). For how to do the waiting, check out AztecCodes’ answer.