Проверял только в хроме.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="h1-trigger">Turn selection</button>
<button id="check">Check selection status</button>
<div id="editor">This is the text where we can select some word by double-clicking, and press the "h1-trigger button". The function wraps the selection with h1 tags. When clicked again it will unwrap the selection and return to previous text. But if we unselect the wrapped word (h1 heading), select by double-click again, and press the button, it does another result. The second button shows the selection status with console log. Why re-selection doesn't contain the created tags?</div>
</body>
<script>
document.getElementById('h1-trigger').addEventListener('click', function () {
headerFormatter();
});
document.getElementById('check').addEventListener('click', function () {
let sel = window.getSelection();
let range = sel.getRangeAt(0).cloneRange();
let rangeProxy = sel.getRangeAt(0).cloneContents();
console.log(sel);
console.log(range);
console.log(rangeProxy);
});
function headerFormatter() {
if( !window.getSelection ) { return; }
let sel = window.getSelection();
if( !sel.rangeCount ) { return; }
let range = sel.getRangeAt(0).cloneRange();
let node, start, end;
if( range.startContainer.nodeName == "#text" ){
node = range.startContainer.parentNode;
start = range.startOffset;
end = range.endOffset;
} else {
node = range.startContainer.childNodes[ range.startOffset ];
start = 0;
end = node.childNodes[0].length;
}
//console.log( node.closest("h1") );
if( node.closest("h1") && node.closest("h1").closest("#editor") )
{
let childNodes = node.closest("h1").parentNode.childNodes;
for( var i=0; i<childNodes.length; i++ ){
if( childNodes[i] == node ) {--i; break;}
}
if( childNodes[i].nodeName == "#text" ){
start += childNodes[i].length;
end += childNodes[i].length;
node = node.closest("h1");
node.outerHTML = node.innerHTML; //удалить тег
range.setStart(childNodes[i], start);
range.setEnd(childNodes[i], end);
sel.removeAllRanges();
sel.addRange(range);
//console.log(range);
}
} else {
if( !range.collapsed ){
let newTag = document.createElement('h1');
range.surroundContents(newTag);
sel.removeAllRanges();
sel.addRange(range);
}
}
}
</script>
</html>