I managed to load an external svg and to grab the path's name and insert it into a tooltip.
But when i now toggle the display of the div, containing the svg object, off and on again the EventListener somehow doesn't work anymore (it only works in FireFox) and the name of the path will not show again. Any idea Why Safari and Chrome won't listen anymore?
window.onload = function() {
var a = document.getElementById("Map1");
var svgDoc = a.contentDocument;
var myImage = svgDoc.getElementsByTagName("path");
for (var i = 0; i < myImage.length; i++) {
myImage[i].addEventListener('mouseover', show);
myImage[i].addEventListener('mouseout', hide);
}
var text = document.getElementById("show");
function show() {
var myID = this.id;
text.innerHTML = myID;
document.getElementById("show").style.display = "block";
}
function hide() {
var myID = this.id;
text.innerHTML = '';
document.getElementById("show").style.display = "none";
}
}
function myFunction() {
var toggle = document.getElementById("Map");
toggle.style.display = toggle.style.display === 'none' ? 'block' : 'none';
}
#show {
display: none;
}
<button onclick="myFunction()">Show Map!</button>
<div id="show" style="position: absolute; left: 100px; background-color:aqua; padding: 5px;"></div>
<div id="Map" style="display: block;"><object id='Map1' data="Test-01.svg" type="image/svg+xml">Your browser doesn't support SVG</object></div>
This is a very surprising behavior which is actually still per specs, even though it's not interoperable since now only WebKit browser maintained it, and is prone to be changed any time soon (though these elements don't get much love these days from specs authors).
The core of the issue is that, per specs, WebKit browsers1 will unload an <object>
or <embed>
content when their CSS display
is set to none
(when their being rendered state is changed).
document.querySelector("object").data =
URL.createObjectURL(
new Blob(
[`<!DOCTYPE html><body>
<script>
document.body.append("The time at loading is " + new Date().getTime());
<\/script></body>`
],
{ type: "text/html" }
)
);
:checked ~ object {
display: none;
}
<input type=checkbox id=c><label for=c>Hide the <object></label><br>
<object></object><br>
In Safari switching the checkbox will produce a new number every time. In Firefox and Chrome the same number will be shown every time.
Doing so, it will remove all of its content your event listeners included, since you basically have a new Document
now.
One possible workaround is to use an <iframe>
. This tag is not concerned by this behavior.
document.querySelector("iframe").src =
URL.createObjectURL(
new Blob(
[`<!DOCTYPE html><body>
<script>
document.body.append("The time at loading is " + new Date().getTime());
<\/script></body>`
],
{ type: "text/html" }
)
);
:checked ~ iframe {
display: none;
}
<input type=checkbox id=c><label for=c>Hide the <iframe></label><br>
<iframe></iframe><br>
The same number will be shown every time in all 3 major browsers.
It also used to be possible to use other CSS rules to hide your <object>
, but in the recent years Safari did introduce a bug where just changing the position
of and <object>
tag will also trigger the reload of the Document...
document.querySelector("object").data =
URL.createObjectURL(
new Blob(
[`<!DOCTYPE html><body>
<script>
document.body.append("The time at loading is " + new Date().getTime());
<\/script></body>`
],
{ type: "text/html" }
)
);
:checked ~ object {
position: absolute;
}
<input type=checkbox id=c><label for=c>Hide the <object></label><br>
<object></object><br>
In Safari even switching the <code>position</code> property will trigger the element's reload.
Footnotes
1. Actually WebKit browsers do so when the element is being rendered again, which is the behavior specced for <embed>
elements, but not the one for <object>
elements. They also do it when other properties of the element change even though the element still has a box.