【问题标题】:Insert 4 spaces instead of tab插入 4 个空格而不是制表符
【发布时间】:2019-01-29 03:15:31
【问题描述】:

我有一个contenteditablediv,里面有divs,如下所示:

<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>

使用 CSS,使用 ::before 作为行号,如下所示:

现在,我想,每当有人按下制表符时,它会自动插入四个空格而不是制表符。我得到了这个函数,但它在触发事件后什么都不做。

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();
    }
}

正如我所说,什么都没有发生(可能是因为isTrusted: false?),也没有抛出任何错误。
顺便说一句,我注意到 this question 具有相同的标题,但这在很大程度上取决于 jQuery 库,我正在寻找一种纯 JavaScript 方法。

【问题讨论】:

标签: javascript html


【解决方案1】:

模拟点击和击键是considered a security risk。根据W3C UI Events Working Draft

“大多数不受信任的事件不会触发它们的默认操作...”

相反,您可以使用 selectionsranges 操作 contenteditable=true 元素的内容,就像我在这个 sn-p 中演示的那样。

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;
}
&lt;div id="editor" contenteditable=true&gt;&lt;/div&gt;

【讨论】:

  • 感谢您的回答!我以为只有HTMLTextAreaElement 有选择属性,我不知道Window 也有它们。按预期工作!
  • 我似乎无法让它完全为我工作,它只会在另一个字符之后插入一个空格。我已经更改了代码以尝试使其正常工作,但它仍然拒绝。这是我发现甚至可以做任何事情的唯一答案。 let node=document.createTextNode(' '); node.innerHTML = '&amp;nbsp; &amp;nbsp; '; range.insertNode(node);
  • @vzybilly,如果您在答案中运行 sn-p,它是否按预期工作?我只在 Chrome 和 Firefox 中测试过,但它仍然对我有用。我不确定您引入的哪些条件会使其按照您所描述的方式运行......顺便说一句,您无法像您所描述的那样创建一个包含 HTMLEntities 的 Text 节点。首先,Text 节点甚至没有 innerHTML 设置器。此外,如果您使用  传递给 createTextNode 的值中的实体,您最终会得到纯文本“ ”作为内容而不是实际的空格字符。
  • 发现问题,div 需要white-space:pre; 的样式。我记得以前把它放在某个地方,但它弄乱了整个页面,但只把它放在那个 div 上解决了这个问题。希望这对其他人有所帮助,并感谢您的帮助。
【解决方案2】:

您是否尝试过在每个空格中插入一个 &amp;nbsp; 而不是多个空字符? 在 HTML 中,除非您使用 &amp;nbsp;,否则多个空格不会一起呈现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-06
    • 2011-09-12
    • 2011-05-27
    • 1970-01-01
    • 2017-02-07
    • 2011-03-28
    • 2012-06-25
    • 2010-12-06
    相关资源
    最近更新 更多