This question already has answers here:
Closed 6 years ago.
I have an <object>
tag on a web page, whose data
attribute is changed programmatically in JS (jQuery, specifically). The data
tag always points to a SVG image.
In Firefox, when the data
tag is changed, the new SVG loads and all the proper events fire. In Chrome, this doesn't occur until I click on the SVG canvas -- once that happens, the new SVG displays and its associated events all fire.
Why is this? How can I force Chrome to refresh the <object>
when I change its data
attribute?
Well, I was really bored tonight and I wanted to do something that wasn't schoolwork, so I dug through a lot of specs and forums for you.
The HTML4 spec doesn't seem to have any mention of SVG, so there's a dead end. The HTML5 Spec Working Draft tells us that we can use data
to invoke plugins and load content. The HTML5 Spec Editor's Draft does mention SVG, telling us that SVG falls under the category of embedded content.
Because the Editor's Draft adds additional detail to the <object>
element as defined in the Working Draft, we could say that the behavior of loading <object>
elements is not an accepted standard. (Somebody please correct me if I'm wrong.)
Anyway, in the <object>
specification, aside from all the usual technical jargon about how the browser should interpret the object by MIME-type etc... We find the part that's relevant to this question:
4.6: If the load failed (e.g. there was an HTTP 404 error, there was a DNS error), fire a simple event named error at the element, then jump to the last step in the overall set of steps (fallback).
...
10.: Once the resource is completely loaded, queue a task to fire a simple event named load at the element.
(Simple events merely mean that the events do not bubble (so we can't listen for it in any parent elements) and are not cancelable, and use the Event
interface)
So, looking at this, I figured that if I select the <object>
element off the DOM, it should have an onload
and onerror
event, if not object.addEventListener
. If you look at the Mozilla Developer Network docs for SVG and <object>
, much of the JavaScript documentation is incomplete. Bummer.
Just goofing around with JSFiddle and the Chrome Dev Tools and Firefox Web Console, I found that they both supported onload
and onerror
, or so I thought.
Results of testing
Google Chrome (18.0.1025.165) and Firefox (12.0)
Supports:
addEventListener('load', function(){})
obj.onload = function(){};
Does not support (events don't seem to fire):
addEventListener('error', function(){})
obj.onerror = function(){}
As you can see from the fiddle, in Chrome using the load
event causes infinite loops. It is not supposed to do this (according to the editor's draft):
The above algorithm is independent of CSS properties (including 'display', 'overflow', and 'visibility'). For example, it runs even if the element is hidden with a 'display:none' CSS style, and does not run again if the element's visibility changes.
It looks like somebody already filed a bug, so if you would go and confirm the bug it would help the Chrome Developers Team.
TL;DR
The behavior for loading objects is not an accepted standard yet, but you can go verify a bug in the Chromium project. You could try doing as @Hello71 suggested and try removing the element from the DOM and re-adding it, but I couldn't get it to work.
Actually, I got exactly the same issue. Have a look at the http://jsfiddle.net/unesJ/, I solved it with the following code:
The html:
<object id="graph" data="image1.svg" type="image/svg+xml"></object>
The javascript:
var new_url = 'image2.svg';
$('#graph').attr('data', new_url);
$('#graph').load(new_url);
It work for me on
- Chrome 24.0.1312.52 m
- Firefox 17.0.1
Hope it helps !
I have tried quite a few things. Unfortunately I've had to resort to doing the following:
setTimeout(function(){
$('body').trigger('click');
}, 40);
No, I don't really have a better solution, but it gets the job done.