'Random <b> tag being added to contentEditable div?
I'm cloning the chat post from Tumblr:
I'm using regex, range and getSelection() to wrap any text before the colon with a <span> element that bolds the interior font with css.
Consider this situation: I type Me:, the text is correctly wrapped and bolded. I backspace, watching everything be deleted in google chrome developer tools. Once the entire div is empty I try typing again and all of a sudden a <b> tag has been added and is now wrapping all the text. If I continue to type and type Me: again, the text will be wrapped by the span tag inside of this errant <b> tag.
I'd really appreciate any help on this. I'm about to throw my laptop out of the window. If you look at the code below I'm no longer creating any <b> tag. I was trying to create <b> tags previously and switched to <span>, so is there any possibility that some child has just never been cleared out of the relevant div? Beyond that I have no idea...
Here's the code:
const ChatPostInput = () => {
const regexChat = () => {
var chatDiv = document.querySelector('.chatText')
console.log(chatDiv.childNodes)
var regexBold = new RegExp(/^(.*?:)/, 'gm')
if (window.getSelection) {
var sel = window.getSelection(),
suffixNode, bold = document.createElement('span') //here I'm creating the span element
bold.setAttribute('class', 'boldText')
var range = sel.getRangeAt(0)
range.deleteContents()
var text = range.commonAncestorContainer.textContent
var matched = text.match(regexBold)
if (matched) {
bold.innerText = range.commonAncestorContainer.textContent
range.commonAncestorContainer.textContent = '';
range.insertNode(bold)
range.setEndAfter(bold)
range.collapse(false)
range.insertNode((suffixNode = document.createTextNode(' ')))
range.setStartAfter(suffixNode);
sel.removeAllRanges();
sel.addRange(range)
}
}
}
return (
<div
className='chatText'
contentEditable={true}
onInput={e => {
//this is a hack to simply skip regexChat() when hitting backspace
if (e.nativeEvent.data !== null) {
regexChat()
}
}}
onKeyDown={e => {
e.stopPropagation();
if (e.key === 'Enter') {
if (window.getSelection) {
var selection = window.getSelection(),
range = selection.getRangeAt(0),
br = document.createElement('br'),
br2 = document.createElement('br'),
suffixNode
range.deleteContents();
range.insertNode(br);
range.collapse(false)
range.insertNode(br2);
range.setEndAfter(br2);
range.collapse(false);
range.insertNode((suffixNode = document.createTextNode(' ')));
range.setStartAfter(suffixNode);
selection.removeAllRanges();
selection.addRange(range);
}
}
}}
>
</div>
)
}
UPDATE 1
I've just found a hacky fix where I override the value of the <b> tag to be font-weight: normal but I mean what in the actual !@$% is going on here? This hack will be fine for my purposes for now but if anyone could reproduce this issue I'd really appreciate it.
Solution 1:[1]
Handle the backspace in onKeyDown event.
If div is empty do the following:
const range = document.createRange()
range.selectNode(node);
range.setStart(node, 0);
range.setEnd(node, 0);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Chadjulian |

