So I'm obviously inserting elements in an editable div under selection. The problem might come when some element was already wrapped in a container. Next selection could include a part of it so, while trying to wrap the selected part again, there's a possibility of error
DOMException: Failed to execute 'surroundContents' on 'Range': The Range has partially selected a non-Text node.
So I'm trying to get innerHTML under the selection so that I could split eventual "edge" elements but can't find any way to dig it out so far.
Just in case the relevant code part is in snippet at the bottom.
If there's some way to get to that innerHTML, or alternatively find some alternative approach to this, I'd appreciate any help.
ie. Editable div content before anything
<div contentEditable="true">
phrase1 phrase2 phrase
</div>
Editable div content after one selection of "e1 phras" part
<div contentEditable="true">
phras<span>e1 phras</span>e2 phrase
</div>
Editable div content after another selection of "phrase1" part with splitted "edges" so that the p tag doesn't contain beginning of span while not containing its closing tag and throwing the error.
<div contentEditable="true">
<p>phras</p><span><p>e1</p> phras</span>e2 phrase
</div>
document.getElementById('edit').addEventListener('mouseup', () => {
obj.saveSelection()});
document.getElementById('setItalic').addEventListener('mouseup', () => {obj.setItalic()});
document.getElementById('setBold').addEventListener('mouseup', () => {obj.setBold()});
const obj = {
currentSelection: null,
selectionRange: null,
restoreSelection: function() {
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(this.selectionRange);
this.currentSelection = selection;
},
saveSelection: function() {
const selection = document.getSelection();
this.selectionRange = selection.rangeCount === 0 ? null : selection.getRangeAt(0);
},
surroundText: function(elem) { // Some DOM element. <a> <span> etc.
this.restoreSelection();
const range = this.currentSelection.getRangeAt(0);
try{
range.surroundContents(elem);
}
catch (e) {
console.error(e); // DOMException: Failed to execute 'surroundContents' on 'Range':
// The Range has partially selected a non-Text node.
}
},
setBold: function() {
this.surroundText(document.createElement('b'));
},
setItalic: function() {
this.surroundText(document.createElement('i'));
}
}
#edit {
height: 200px;
width: 200px;
background-color: #444;
color: white;
}
<button id="setItalic">italic</button>
<button id="setBold">bold</button>
<div id='edit' contentEditable="true"/>