I'm working to create a feature rich text editor that simulates some of the functionality you'd find in full scale word processors like MS word and google docs. I am trying to apply styling (bold, italics, highlight, etc...) to user selected text.
I have put together the following code that does the job, but only as long as the highlighted text does not cross html elements.
const hightlightBtn = document.querySelector('.btn');
hightlightBtnS.addEventListener('click', () => {
const selected = window.getSelection().getRangeAt(0);
console.log(selected);
highlightElement(selected);
});
function highlightElement(range){
const newNode = document.createElement('div');
newNode.setAttribute(
'style',
'background-color: yellow; display: inline;'
)
range.surroundContents(newNode);
};
If I try to highlight text that is from two paragraphs (and encased in separate
tags) I'm given the error:
Uncaught DOMException: Failed to execute 'surroundContents' on 'Range': The Range has partially selected a non-Text node.
This appears to be an issue with the surroundContents() method.
In the MDN refernce material for this method, I find the following:
An exception will be thrown, however, if the Range splits a non-Text node with only one of its boundary points. That is, unlike the alternative above, if there are partially selected nodes, they will not be cloned and instead the operation will fail.
Is there any way I can get around this issue while still using surround contents? Or can anybody help me figure out another way to apply styling to user selected text?
Why not simply use CSS?
p::selection, p ::selection {
background-color: green;
color: #fff;
}
<p>Mark some text <i>here</i> in this paragraph.</p>
The pseudo selector ::selection
has very broad browser support, going back as far as even IE 9:
https://caniuse.com/#feat=css-selection
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With