I am trying to build around contenteditable by first disabling it's text styling behavior from keyboard shortcuts, such as ctrl b
or ctrl i
.
I am using event.preventDefault()
when these shortcuts are detected on keyup
and keydown
events -- however sometimes rarely, I am noticing that contenteditable still ignores event.preventDefault()
and the keyboard shortcut is respected.
Is there any way I can fully disable these keyboard shortcuts other than cancelling keyup
and keydown
?
My shortcut detector was faulty and it was letting the event go through at certain cases. It seems cancelling the event on keydown
does actually cancel the shortcut as well.
I have created a jsfiddle for anyone who wants to try it: https://jsfiddle.net/mohj19bs/28/
I will be closing this thread tomorrow, just in case someone else might share something interesting since contenteditable
never ceased to surprise me.
CodePudding user response:
Not sure what problem you're dealing with, but this works well...
document.getElementById("test").addEventListener("keydown", e => {
if(!e.ctrlKey) return;
if(e.keyCode === 66 || e.keyCode === 73) {
e.preventDefault();
}
});
<div id="test" contenteditable>This div is editable</div>
And a one-liner for your enjoyment:
document.getElementById("test").onkeydown = e => !(e.ctrlKey && (e.keyCode === 66 || e.keyCode === 73));
<div id="test" contenteditable>This div is editable</div>
CodePudding user response:
Here is another strategy that may work for you. Instead of trying to prevent b
and i
elements from being inserted, just remove them right away on keyup
or on paste
.
Handled cases are:
- [CTRL] [b] and [CTRL] [i]
- pasted HTML which contains inline style attribute
And it works recursively to take care of nested elements.
let forbiddenTags = ["B", "I", "STRONG"]
let clean = function(e){
// Loop through all child nodes
e.target.childNodes.forEach(function(item){
// recursion if there are childnodes
if(item.childNodes){
clean({target:item})
}
// Remove forbidden tags
if(item.tagName && forbiddenTags.indexOf(item.tagName) > -1){
item.insertAdjacentHTML("afterEnd", item.innerHTML)
item.remove()
return
}
// Reset inline style
if(item.style){
item.style.fontWeight = "normal"
item.style.fontStyle = "normal"
}
})
}
document.querySelector("#test").addEventListener("keyup", clean)
document.querySelector("#test").addEventListener("paste", clean)
div{
border: 1px solid grey;
padding: 0.5em;
}
table{
border-collapse: collapse;
}
td{
border: 1px solid grey;
}
<div id="test" contentEditable=true>Enter text here</div>
<br>
Paste me in!:
<div id="pasteit">
<b>bold</b> <i>italic</i> <strong>strong</strong> <span style="font-weight:bold;">inline</span>
<table>
<tr>
<td style="font-style:italic;">Italic</td>
<td style="font-weight:bold;">Bold</td>
</tr>
</table>
</div>