0

I've been struggling a long time with this, lots of older posts address the issue but in incomplete, indirect or obsolete ways. Its such a common issue, a common solution would be ideal. I cannot/should-not modify the SVG. The svg has an id and all the various groups have ids that I need to interact with.

The issue is that I can't assign a load event to the svg element itself because it isn't loaded yet when my controller runs; And if I assign the on load event to the parent embed tag, well, then I can't access the elements via getElementByID because they aren't loaded yet either.

View:

<div style="width:1000px" ng-controller="Controller">
    <embed id="svgObject" width="100%" height="100%" ng-src="{{modelSVG}}" type="image/svg+xml"></embed>
</div>

Controller:

   .controller('HomeController',['BaseController','$scope','$location',function (BaseController,scope,location) {
            scope.modelSVG = location.protocol() + '://' + location.host() + '/svg/pic.svg';
            var svgObject = document.getElementById("svgObject");

            svgObject.addEventListener('load', function(){
                var svgDocument = svgObject.contentDocument;
                **Do lots of stuff to EACH and every shape loadeded (e.g. show/hide, set hover/click events, etc
            })
   }])

Another attempt to get at the actual svg document

var svgDocument = svgObject.contentDocument ? svgObject.contentDocument : svgObject.contentWindow.document;

I can't believe this is so difficult.

gunslingor
  • 1,358
  • 12
  • 34
  • With the AngularJS framework use a [custom directive](https://docs.angularjs.org/guide/directive) or use the new [ng-on directive](https://docs.angularjs.org/api/ng/directive/ngOn) to attach an event handler to an element. – georgeawg Nov 21 '18 at 23:34
  • Tried equivalent solutions, will not work. ng-on-load isn't different than onload and would have to go on the svg object inside the svg file; but the file cannot be modified. As far as I can tell, a custom directive wouldn't be able to tell be when the child directive, the svg document, is fully loaded by the browser . – gunslingor Nov 21 '18 at 23:49

1 Answers1

0

This is by far the prettiest and best solution I found that doesn't require much code. In essence, we GET the svg file and parse it as a document fragment so everything is added to the DOM (apparently and magically), then we assign the result back to the original div and can then access the svg directive by id.

View:

<div style="width:1000px" ng-controller="Controller">
    <div id="svgObject" style="width: 600px; height: 600px;"></div>
</div>

Controller:

.controller('HomeController',['BaseController','$scope','$location',function (BaseController,scope,location) {
            scope.modelSVG = location.protocol() + '://' + location.host() + '/svg/pic.svg';
            http({
               method : "GET",
               url : scope.svgPath
            }).then(function mySuccess(response) {
               var svgObject = document.getElementById('svgObject');
               svgObject.appendChild(parseSVG(response.data));

               var svgDocument = document.getElementById("svgDocument");//the id of the actual svg tag.
               //do anything to fully loaded svg
            }, function myError(response) {
                alert(response.statusText);
            });

The Magic Function:

function parseSVG(svg) {
    var div= document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
    div.innerHTML= '<svg xmlns="http://www.w3.org/2000/svg">'+svg+'</svg>';
    var frag= document.createDocumentFragment();
    while (div.firstChild.firstChild)
        frag.appendChild(div.firstChild.firstChild);
    return frag;
}

Approach was discovered here: jquery's append not working with svg element?

gunslingor
  • 1,358
  • 12
  • 34