【问题标题】:Cursor moves to end of the contenteditable div when character removed from div当从 div 中删除字符时,光标移动到 contenteditable div 的末尾
【发布时间】:2018-03-08 07:03:43
【问题描述】:

我正在创建自己的聊天应用程序,其中我使用内容可编辑div 作为聊天框。 我正在实现提及功能,其中我提及的是包含在跨度标记中的用户名,后跟空格( ),但我的问题是当我删除空格时,我的光标移动到 div 的末尾。

带空格

<html>

<head>
</head>

<body>
  <div contenteditable=true><span contenteditable='false'>UserName</span>&nbsp;</div>
</body>

</html>

没有空格

<html>

<head>
</head>

<body>
  <div contenteditable=true><span contenteditable='false'>UserName</span></div>
</body>

</html>

这就是我在代码中实现的方式,而且这个错误只发生在 chrome 中。

【问题讨论】:

    标签: javascript css html contenteditable


    【解决方案1】:

    这实际上是浏览器中的一个错误,我有一个解决方法,但我不知道它对您有多大帮助,但这是我们能做的最好的现在据我所知。

    div>span {
       display:inline-block;
    }
    &lt;div contenteditable="true"&gt;&lt;span contenteditable="true"&gt;&lt;span contenteditable="false"&gt;UserName&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;/div&gt;

    没有空格

    div>span {
      display:inline-block;
    }
    &lt;div contenteditable="true"&gt;&lt;span contenteditable="true"&gt;&lt;span contenteditable="false"&gt;UserName&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;

    如果您想要完整证明内容,那么这里有一个解决方案,script 结合 : before 伪:

    这里我将: before 伪元素的宽度转移到div 元素padding-left。我使用脚本牢记您的动态用户名。

    var testBox = document.querySelector('.test'),
      pseudoBeforeWidth = window.getComputedStyle(testBox, ':before').width, //getting the width of the parent elemnts `:before`
      pseudoBeforeContent = window.getComputedStyle(testBox, ':before').content;
    
    testBox.style.paddingLeft = pseudoBeforeWidth; //handing the width to the parent elemnts padding left style
    var i = 0
    var n = 0;
    testBox.addEventListener('keydown', function(event) {
      const key = event.key; // const {key} = event; ES6+
      if ((key === "Backspace" || key === "Delete") && n == 0) {
        i++
        console.log(testBox.textContent, i, n);
        if (testBox.textContent == "" && i >= 2) {
          testBox.className += ' userhide ';
          testBox.style.paddingLeft = 0;
          n = 1;
        }
      }
    });
    div:before {
      content: attr(data-user);
      display: inline-block;
      position: absolute;
      left: 5px;
    }
    
    .test.userhide:before {
      display: none;
    }
    &lt;div class="test" contenteditable="true" data-user="UserName"&gt;&lt;/div&gt;

    我希望这对你有帮助。

    【讨论】:

    • 它可以防止光标走到最后,但我必须按两次退格键才能将其删除。
    • 请在第一个代码 sn-p(带空格)中测试您的代码,删除用户名跨度需要 2 个退格键
    • 在第一个代码 sn-p 中,1 个退格用于删除空格,2 个退格用于删除 span,总共 3 个退格
    • 我的 chrome 版本也一样,但我的代码只清除了 2 个退格键中的所有内容
    • @HimanshuBansal 我已经为您需要的结果更新了javascript 代码,所以请检查您是否对script 解决此错误感兴趣。
    【解决方案2】:

    分析

    想象一个简单的文本编辑器(记事本),您在其中输入了三个字符 - TRY

    现在,很明显,这里的光标只能放在4个地方,分别是:

    • T 之前
    • 在 T 和 R 之间
    • 在 R 和 Y 之间
    • Y 之后

    原因很简单,这 3 个字符是这里唯一的 可编辑 字符,它们是 3 个单独的实体,无法进一步编辑/分离。例如,我们不能将光标放在字母“T”之间并将与其分开。

    您的方案也是如此,因为一旦 &amp;nbsp; 被清除,光标就会移动到 div 的末尾,因为 contenteditable=true 设置为 &lt;div&gt; 并设置为 false 到 @ 987654329@。因此div 是这里唯一可编辑的元素,span 不是。因此,光标只能将自己定位在可编辑元素的开头(在本例中为div)或结尾且not介于两者之间的可编辑位置。

    由于div 是块元素,当块元素占据其父元素的整个宽度时,光标将移动到页面的末尾。如果我们将width: 50%; 设置为div,我们可以看到光标移动到页面中间。

    解决方案

    考虑到您的 cmets 在其他答案上,您需要将宽度保持为 100%,解决方案是将 div 与另一个也具有属性 contenteditable=true 的包装在一起,并将子 div 保留为inline-block 元素。

    <div contenteditable=true>
      <div class="inl-blck" contenteditable=true><span contenteditable='false'>UserName</span>&nbsp;</div>
    </div>
    

    CODEPEN

    说明

    在这里,父元素和子元素divs 都是可编辑的,其中父元素占据全宽(100%),子元素是inline-block 元素,它只占据其内容的空间。因此,一旦&amp;nbsp; 被清除,光标就会移动到下一个可编辑内容的末尾,即子div

    请注意,您需要将子 divspan&amp;nbsp; 一起保留在代码的同一行中,否则会在该部分中创建额外的字符(空格),这会破坏contenteditable 进一步。

    希望这会有所帮助。

    【讨论】:

    • 做得很好。在我的回答中,我只是放错了&amp;nbsp;。大声笑,谢谢你的澄清兄弟。 :) 赏金是你的。
    • 谢谢。很高兴我能帮忙:)
    【解决方案3】:

    这可以帮助你

    <div contenteditable=true style="display: inline-block;background: #000;color:#fff;"><span contenteditable=false>UserName</span>&nbsp;</div>
    

    【讨论】:

    • 不,我的 div 宽度设置为 100%
    【解决方案4】:

    信不信由你,这个错误与实际 HTML 标记本身中的空白有关。

    这是一个工作示例:

    .username {
        margin-left: 10px;
    }
    <div contenteditable="true">
      <span contenteditable="false" class="username">Username</span>
    </div>

    只需将结束的 div 移动到下一行,我们就可以将中断传达给 html 解析器。

    【讨论】:

    • 感谢您提供的信息,但我们仍然需要在 用户名 之前添加一个空格&amp;nbsp;,将其添加到您的答案中,结果与问题错误相同。
    • 更新了 sn-p,使用 CSS 来强制用户名周围的间距。
    • 1个退格用来去掉空格,2个退格用来去掉span这就是他想要的。
    猜你喜欢
    • 2012-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-17
    • 1970-01-01
    相关资源
    最近更新 更多