In my Angular appliation, I want to be able to select the embedded SVG element of an <object>
tag using JavaScript or Angular jqLite.
Normally, to do this operation, one must write something similar to:
// Create <object> element of the SVG
var objElement = document.createElement('object');
objElement.setAttribute('type',"image/svg+xml");
// Assume $rootScope.b64 contains the base64 data of the SVG
objElement.setAttribute('data', $rootScope.b64);
// Append the <object> inside the DOM's body
angular.element(document.body).append(objElement);
console.log(objElement);
console.log(objElement.getSVGDocument());
console.log(objElement.contentDocument);
In my console, objElement
returns the plete <object>
with the <svg>
element and its contents (assume that data attribute contains the full base64 data string (b64)).
<object id="svgObject" data="b64" type="image/svg+xml">
#document
<svg>
</svg>
</object>
However, getSVGDocument()
returns null
and contentDocument
returns
#document
<html>
<head></head>
<body></body>
<html>
Why can't I retrieve the SVG element? How can I get the SVG element correctly? I've already looked into many articles and I just can't get the <svg>
element. Could this have something to do with cross-origin policy?
In my Angular appliation, I want to be able to select the embedded SVG element of an <object>
tag using JavaScript or Angular jqLite.
Normally, to do this operation, one must write something similar to:
// Create <object> element of the SVG
var objElement = document.createElement('object');
objElement.setAttribute('type',"image/svg+xml");
// Assume $rootScope.b64 contains the base64 data of the SVG
objElement.setAttribute('data', $rootScope.b64);
// Append the <object> inside the DOM's body
angular.element(document.body).append(objElement);
console.log(objElement);
console.log(objElement.getSVGDocument());
console.log(objElement.contentDocument);
In my console, objElement
returns the plete <object>
with the <svg>
element and its contents (assume that data attribute contains the full base64 data string (b64)).
<object id="svgObject" data="b64" type="image/svg+xml">
#document
<svg>
</svg>
</object>
However, getSVGDocument()
returns null
and contentDocument
returns
#document
<html>
<head></head>
<body></body>
<html>
Why can't I retrieve the SVG element? How can I get the SVG element correctly? I've already looked into many articles and I just can't get the <svg>
element. Could this have something to do with cross-origin policy?
- You need to wait for the onload event of the object to fire before accessing its contents. – Robert Longson Commented Oct 27, 2015 at 19:11
-
If I enclose the
getSVGDocument()
inside a onload event, I getUncaught SecurityError: Failed to execute 'getSVGDocument' on 'HTMLObjectElement': Blocked a frame with origin "http://127.0.0.1:8080" from accessing a frame with origin "null". The frame requesting access has a protocol of "http", the frame being accessed has a protocol of "data". Protocols must match.
– Dramos Commented Oct 27, 2015 at 19:18 - Is this Chrome? I imagine you're blocked by its security model. You might try a different UA – Robert Longson Commented Oct 27, 2015 at 19:22
- Yes, I'm developing on Chrome. Do you mean User Agent? How can I toggle its security model? – Dramos Commented Oct 27, 2015 at 19:33
-
Robert means try a different browser, like Firefox. Chrome has a more restrictive security model. For instance it disallows some things if you are using
file://
URLs. – Paul LeBeau Commented Oct 28, 2015 at 0:57
3 Answers
Reset to default 5I was also unable to select the SVG using things like document.querySelector("svg")
even though the SVG was clearly loaded in the DOM. Turned out I needed to do this:
var obj = document.querySelector("object");
var svg = obj.contentDocument.querySelector("svg");
Apparently there's a boundary between the main document and this sub-document, and you have to bridge the divide using contentDocument
.
It seems getSVGDocument() is deprecated. Have you tried something like document.querySelector('object svg')
?
The reason you can't see the object is because you are most likely probing for it before DOM load. Try:
// Create <object> element of the SVG
var objElement = document.createElement('object');
objElement.setAttribute('type',"image/svg+xml");
// Assume $rootScope.b64 contains the base64 data of the SVG
objElement.setAttribute('data', $rootScope.b64);
// Append the <object> inside the DOM's body
angular.element(document.body).append(objElement);
objElement.addEventListener('load', doStuff);
function doStuff() {
console.log(objElement);
var svgDoc = getSVGDoc(objElement);
console.log('svgDoc', svgDoc);
}
function getSVGDoc(element) {
console.log('getting obj');
try {
return element.contentDocument;
} catch (e) {
try {
return element.getSVGDocument();
} catch (e) {
console.log('SVG unsupported within this browser');
}
}
}