I have a text tag that I'm adding to SVG via JS script and would like to make that text editable.
Found a couple of solutions on StackOverflow:
creating a css class and applying it to my SVG text element. This works perfectly, at least in Safari, but isn't remended it by MDN Here is the class that is actually someone's answer, unfortunately I can't remember whose:
.editable { font-size: 0.3em; user-modify: read-write; -moz-user-modify: read-write; -webkit-user-modify: read-write; }
wrapping the svg in a contenteditable div (answer given by Erik). This also works but results in bad cursor behavior, at least in Safari.
<div contenteditable="true">
<svg id="svgArea" viewBox="0 0 200 200" xmlns="">
</svg>
</div>
I have a text tag that I'm adding to SVG via JS script and would like to make that text editable.
Found a couple of solutions on StackOverflow:
creating a css class and applying it to my SVG text element. This works perfectly, at least in Safari, but isn't remended it by MDN https://developer.mozilla/en-US/docs/Web/CSS/user-modify Here is the class that is actually someone's answer, unfortunately I can't remember whose:
.editable { font-size: 0.3em; user-modify: read-write; -moz-user-modify: read-write; -webkit-user-modify: read-write; }
wrapping the svg in a contenteditable div (answer given by Erik). This also works but results in bad cursor behavior, at least in Safari.
<div contenteditable="true">
<svg id="svgArea" viewBox="0 0 200 200" xmlns="http://www.w3/2000/svg">
</svg>
</div>
The JS part
function foo(x, y, w, h) {
var rect, group;
var svgPlace = document.getElementById('svgArea');
var xmlns = "http://www.w3/2000/svg";
group = document.createElementNS(xmlns, 'g');
svgPlace.appendChild(group);
var txtElem = document.createElementNS(xmlns, 'text');
txtElem.setAttributeNS(null, 'x', x);
txtElem.setAttributeNS(null, 'y', y * 1.25);
txtElem.setAttributeNS(null, 'fill', 'LightBlue');
txtElem.setAttributeNS(null, 'contentEditable', true); //does nothing!
txtElem.setAttributeNS(null, 'class', 'editable'); //this is the best working option at the moment
var txtVal = document.createTextNode('test');
txtElem.appendChild(txtVal);
group.appendChild(txtElem);
}
I'd love to be able to set the contentEditable as an attribute, if that's possible. But most importantly, what's the best way to make SVG text editable?
Share Improve this question edited Mar 30, 2019 at 10:09 Masoud Keshavarz 2,2449 gold badges40 silver badges49 bronze badges asked Mar 29, 2019 at 21:30 a_visitora_visitor 631 silver badge9 bronze badges 4-
document.getElementById("element").contentEditable = "true";
You can also use the refcontenteditable="true"
in an HTML element like so:<div contenteditable="true">
. – ABC Commented Mar 29, 2019 at 21:40 - In your second example, you have no text element to edit.. – Keith Commented Mar 29, 2019 at 21:56
- Raymond, The <div contenteditable="true"> wrapped around <svg> works but produces odd cursor behavior. I can't get setting contentEditable to 'true' to work. This is what I tried, am I doing it wrong?: document.getElementsByTagName("text")[0].contentEditable='true' – a_visitor Commented Mar 29, 2019 at 21:56
- The text element is added via JS to the SVG element in the second code part. – a_visitor Commented Mar 29, 2019 at 22:00
2 Answers
Reset to default 2@Raymond ment is the correct answer but since you still have problem I wrote down an example.
document.getElementById("svgWrapper").contentEditable = "true";
<div id="svgWrapper">
<svg id="svgArea" viewBox="0 0 200 200" xmlns="http://www.w3/2000/svg">
</svg>
</div>
I ended up solving this by placing an input tag inside a foreign object, which is added to an SVG group. That works on Safari so I wanted to post it here, in case anyone else is struggling with the same thing.
<svg>
<g>
<foreignobject>
<input></input>
</foreignobject>
</g>
</svg>
If you need to add using JS:
function addSvg(x, y, w, h) {
var rect, group;
var svgPlace = document.getElementById('svgArea');
var xmlns = "http://www.w3/2000/svg";
group = document.createElementNS(xmlns, 'g');
svgPlace.appendChild(group);
// solution
let foreigner = document.createElementNS(xmlns, "foreignObject");
foreigner.setAttributeNS(null, "x", x);
foreigner.setAttributeNS(null, "y", y);
foreigner.setAttributeNS(null, "width", w);
foreigner.setAttributeNS(null, "height", h);
group.appendChild(foreigner);
let txt = document.createElement('input');
foreigner.appendChild(txt);
}