Search code examples
javascripthtmlsvgonload-event

Trap the "Image" loading event on an SVG element in IE11


Hopefully someone has already resolved this, so it should be easy.

The closest I've come on SO already is this question:

Is it possible to listen image load event in SVG?

which hasn't helped.

Scenario

I'm using a 3rd party toolkit to create an SVG graphic in a custom document editor I'm creating.

This 3rd party toolkit creates SVG '..' tags to hold the images being edited.

Specifically, it creates an output as follows:

<g transform="translate(0.5,0.5)" style="visibility: visible;">
  <image x="4.68" y="0" width="469" height="81" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="genimage?1453893356324" preserveAspectRatio="none">
  </image>
</g>

Part of the application, needs to know when all of the images have finished loading so that it can complete an initialisation task.

In order to provide this notification of image loading Iv'e added a 'load' event handler to the elements using jQuery.

I can't add an "onLoad" or modify the '' tag being generated as I don't have access to it. The soonest I have access to it is when the svg has already been injected into the dom by the 3rd party toolkit, by which time the loading is already under way and I can't attach or modify anything because I'm too late to influence the operation.

What Iv'e tried and what's happening

My adding of the 'load' event works perfectly fine in Chrome and Firefox. I'm adding the following:

$('g image').on('load', (e) => {
  console.log("Image Loaded");
  console.log(e);
});

And that works perfectly fine except in IE

I'm not targeting anything except IE11 (IE10 at a push but nothing less), but no matter what I try, IE11 just does not trigger the event.

Now, here's a slightly strange twist to the tale.

Before I set this event up, and before I tell the 3rd party product to load it's images, I have a single place holder image that's loaded just using a standard

documentMockImage: HTMLImageElement = new Image();
this.documentMockImage.src = "mockimage";

and, the handler I add, triggers in IE to tell me that the mock image loaded (Which is not what I want) but in Chrome & FF it triggers as expected for each loaded image in the graph, but NOT for the image place holder (Which is the behaviour I do want)

So my question is this: How can I get a uniform behaviour, that tells me after each individual image in the svg graph, that works across IE11, Chrome & FF.

To answer the questions I can hear people already asking me:

  • YES, I'm using typescript, but that shouldn't matter to how this is solved.
  • The 3rd party toolkit is 'MxGraph'/'JGraph', but this is NOT a toolkit specific question it's an SVG image question
  • No I can't provide sample code (Other than what I've already shown) this is a closed project
  • YES, I do have jQuery in the project, and yes I can use that, but I CAN also use native, I would however rather NOT have to add any more dependencies/libraries *The project currently uses, jQuery, Knockout, Bootstrap & Require, in typescript, coding to ES6 standards and transpiling to ES5 on output.

If anyone can offer any suggestions to solving this, it would be muchly appreciated.

UPDATE 1

Continuing on researching this, I decided just to see what each browser was finding natively, so I added the following:

var svgImages = document.getElementsByTagName('image');
console.log(svgImages);

Chrome & FF as expected returned the 4 SVG Images in my document

Images in Chrome Debugger

Images in Firefox debugger

Internet explorer however, adds not only 'image' tags from svg, but 'img' tags from elsewhere in the doc too

Images in the IE debugger

This would suggest that IE either deliberately does this, or can't tell the difference between 'image' & 'img'


Solution

  • Here's a sample that Kaiido suggested. I know it sucks, but I couldn't find any other options for IE and Edge.

    var url = "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png";
    var svg = document.getElementById('svg');
    var img = document.createElementNS("http://www.w3.org/2000/svg", 'image');
    
    var dummy = new Image();
    dummy.addEventListener('load', function()
    {
      console.log("dummy onload");
      img.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", url);
      img.setAttribute("width", dummy.width);
      img.setAttribute("height", dummy.height);
      svg.appendChild(img);
    }, false);
    dummy.src = url;
    <svg id="svg" width="1000px" height="500px" />