1

I would like to fire an even if an <object> fails to load.

I know I can do this:

<object>Some Error Happened</object>

But I need to detect it with Javascript as well, and then fire some logic if the object fails.

That seems like an extremely impossible thing to do?

I have tried with:

document.querySelector('object').addEventListener('error', () => { alert('Something went wrong'); })

But that doesn't work either.

2 Answers 2

1

The error event is fired on a Window object:

window.addEventListener('error', (event) => {
    console.log(event)
});

https://developer.mozilla.org/en-US/docs/Web/API/Window/error_event

1
  • Error events don't bubble, if you want to catch them from window you need to add the capture flag to your listener. But here it won't do much anyway.
    – Kaiido
    Commented Oct 29, 2020 at 12:58
1

This would be a Chrome bug.

Per specs, the error event should fire on the <object> element (and it does in Firefox) both if the URL parsing failed, or if the resource loading failed.
There is though some kind of a grey area where if the request didn't end in a network error, and if the resource does not have associated Content-Type metadata, then it will just silently fail...
This seems counter-intuitive and might require a specs bug.

Anyway, I think Chrome fails to recognize network errors as it should, so the solution is probably to open a chrome issue so they fix it. I added a comment on BUG 853140, let's see how it goes

The workaround is to use an <iframe> instead. <object> will probably get deprecated soon anyway.

Note that setting a type attribute to an unsupported type or just having it in the response's MIME type, Chrome will fire the event, but it still faces a new issue where it fires this event synchronously, even before we have time to attach any handler. So we have to force it to fire again by setting the data attribute again:

document.querySelectorAll('object')
  .forEach( el => {
    el.onerror = e => console.log( "error", el );
    el.data = el.data; // force fire again
  } );
<object data="/foo"></object> <!-- doesn't fire -->
<object data="/foo" type="image/svg+xml"></object> <!-- doesn't fire -->
<object data="/foo" type="foo/bar"></object> <!-- does fire -->
<object data="data:foo,"></object>  <!-- does fire -->

1
  • Thanks for your answer @Kaiido. The reason why I choose to use <object> instead of <iframe> is that object re-sizes the embedded content to fit the object dimensions. most notable on safari in iPhone 4s where screen width is 320px and the html from the embedded URL may set dimensions greater. But I'll see if theres a workaround for this with iframe.
    – FooBar
    Commented Nov 10, 2020 at 8:33

Not the answer you're looking for? Browse other questions tagged or ask your own question.