Reputation: 383
The following code has a weird quirk:
function createSVG(){
let svgarea = document.getElementById("svgarea");
let svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("id", "my_svg");
svg.setAttribute("width", "100%");
svg.setAttribute("height", "100%");
svgarea.appendChild(svg);
}
When I run call it from script when loading page or on window.onload, the script fails
"Cannot read property 'appendChild' of null"
at the
svgarea.appendChild(svg);
But it works normally if I call it from console. Is there a workaround for this? I suspect that the createElementNS somehow hangs before it gets to appending the result, but somehow it doesn't when calling from console.
Upvotes: 0
Views: 201
Reputation: 21143
It means the DOM Element #svgarea
isn't there yet when you execute:
let svgarea = document.getElementById("svgarea");
When you execute the same statement from the console the DOM is there, ready
So you must delay execution of your createSVG
function:
window.addEventListener("DOMContentLoaded", createSVG);
You could also use the load
Event but that fires later, after all content is loaded.
If you use window.onload =
you have to be 100% sure no later code will override it. addEventListener
does what it says: it adds extra listeners
setTimeout(createSVG);
Also does the trick, in cases where the Events have long past, and you can't use them. No time required because setTimeout
will run after the Event Loop is done, thus any DOM creation will have happened.
If you want to create SVG, you can also use HTML notation:
function createSVG(){
document
.getElementById("svgarea")
.innerHTML=`<svg xmlns='http://www.w3.org/2000/svg' id='my_svg' width='100%' height='100%'></svg>`
}
Or, because innerHTML is render blocking, creates DOM nodes immediately:
function createSVG(){
let area = document.getElementById("svgarea");
area.innerHTML=`<svg xmlns='http://www.w3.org/2000/svg' id='my_svg'></svg>`;
let svg = area.querySelector("svg");
svg.setAttribute("width","100%");
svg.setAttribute("height","100%");
}
And don't forget you probably need a viewBox
attribute on those SVGs
Upvotes: 3