Reputation: 861
I have a contenteditable
div
with div
s inside them like this:
<div id="wrapper" contenteditable=true onkeydown="preventTab(event);">
<div id="line1" class="line"></div>
<div id="line2" class="line"></div>
<div id="line3" class="line"></div>
<div id="line4" class="line"></div>
</div>
With CSS, using ::before
for line numbers , this looks like this:
Now, I want, whenever someone presses tab, it automatically inserts four spaces instead of a tab. I got this function, but it doesn't do anything after it has fired the events.
function preventTab(event) {
event = event || window.event;
if (event.keyCode === 9) {
// for loop, so the user can set the amount of spaces they want.
for (let i = 0; i < tabSize; i++) {
let e = new KeyboardEvent("keydown", {
bubbles: true,
code: "Space",
key: " ",
keyCode: 32
});
event.target.dispatchEvent(e);
}
event.preventDefault();
}
}
As I said, nothing really happens (maybe because isTrusted: false
?), also no errors are thrown.
By the way, I have noticed this question with the same title, but that heavily depends on the jQuery library and I'm looking for a pure JavaScript approach.
Upvotes: 2
Views: 1225
Reputation: 4483
Simulating clicks and keystrokes is considered a security risk. According to the W3C UI Events Working Draft:
"Most untrusted events will not trigger their default actions..."
Instead you can manipulate the contents of the contenteditable=true
element using selections and ranges like I have demonstrated in this snippet.
let tabSize = 2;
let spaces = '';
for (i = 0; i < tabSize; i++) {
spaces += ' ';
}
document.getElementById('editor').addEventListener('keydown', preventTab);
function preventTab(event) {
if (event.keyCode === 9) {
event.preventDefault();
let selection = window.getSelection();
selection.collapseToStart();
let range = selection.getRangeAt(0);
range.insertNode(document.createTextNode(spaces));
selection.collapseToEnd();
}
}
html,
body {
height: 100%;
width: 100%;
margin: 0;
}
#editor {
width: 100%;
height: 100%;
font-family: monospace;
white-space: pre;
}
<div id="editor" contenteditable=true></div>
Upvotes: 1
Reputation: 1207
Have you tried inserting one
per space instead of multiple empty characters?
In HTML multiple empty spaces together will not render unless you use
.
Upvotes: 0