Reputation: 1413
I'm trying to build a text editor using DOM Range. Let's say I'm trying to bold selected text. I do it using the following code. However, I couldn't figure out how I would remove the bold if it's already bolded. I'm trying to accomplish this without using the execCommand function.
this.selection = window.getSelection();
this.range = this.selection.getRangeAt(0);
let textNode = document.createTextNode(this.range.toString());
let replaceElm = document.createElement('strong');
replaceElm.appendChild(textNode);
this.range.deleteContents();
this.range.insertNode(replaceElm);
this.selection.removeAllRanges();
Basically, if the selection range is enclosed in <strong>
tags, I'd want to remove it.
Upvotes: 2
Views: 661
Reputation: 2129
Ok so I drafted this piece of code. It basically grabs the current selected node, gets the textual content and removes the style tags.
// Grab the currenlty selected node
// e.g. selectedNode will equal '<strong>My bolded text</strong>'
const selectedNode = getSelectedNode();
// "Clean" the selected node. By clean I mean extracting the text
// selectedNode.textContent will return "My bolded text"
/// cleandNode will be a newly created text type node [MDN link for text nodes][1]
const cleanedNode = document.createTextNode(selectedNode.textContent);
// Remove the strong tag
// Ok so now we have the node prepared.
// We simply replace the existing strong styled node with the "clean" one.
// a.k.a undoing the strong style.
selectedNode.parentNode.replaceChild(cleanedNode, selectedNode);
// This function simply gets the current selected node.
// If you were to select 'My bolded text' it will return
// the node '<strong> My bolded text</strong>'
function getSelectedNode() {
var node,selection;
if (window.getSelection) {
selection = getSelection();
node = selection.anchorNode;
}
if (!node && document.selection) {
selection = document.selection
var range = selection.getRangeAt ? selection.getRangeAt(0) : selection.createRange();
node = range.commonAncestorContainer ? range.commonAncestorContainer :
range.parentElement ? range.parentElement() : range.item(0);
}
if (node) {
return (node.nodeName == "#text" ? node.parentNode : node);
}
};
I don't know if this is a "production" ready soution but I hope it helps. This should work for simple cases. I don't know how it will react with more complex cases. With rich text editing things can get quite ugly.
Keep me posted :)
Upvotes: 2