【问题标题】:How to keep the caret on the same place in my contenteditable div while clicking buttons?单击按钮时,如何在我的 contenteditable div 中将插入符号保持在同一位置?
【发布时间】:2017-04-18 13:12:15
【问题描述】:

单击带有图标的按钮后,我试图在我的 contenteditable div 中创建一个图标。问题是,在选择图标/按钮时,我丢失了文本中的插入符号。关闭按钮后,我希望这个插入符号回到原来的位置。

我做了一个 JS-Fiddle 来说明这个问题:JSFiddle

PS:这个问题尤其是关于插入符号的。是否插入图标对我来说并不重要。那部分应该很容易弄清楚:)。

html

<div id="write-mail">
   <div style="position: relative;">
      <div id="new-mail-content" contenteditable="true">
          <div>How to return the caret where it was in the sentence after clicking the buttons?</div>
          <div>Maybe prevent the caret from being removed after clicking the buttons?</div>
          <div>I know I can store the current selection by using window.getSelection(). If I would be able to reactivate this selection, that would be great!</div>
      </div>
      <div id="emotepicker">
        <button><span>&#10004;</span></button>
        <button><span>&#10031;</span></button>
        <button><span>&#10008;</span></button>
      </div>
  </div>
        <button class="add-icon">Add Icon</button>
</div>

css

#new-mail-content{
  background-color: white;
  min-height: 5em;
}
#write-mail button{
  height: 30px;
}
#emotepicker{
  display: none; 
  position: absolute;
  left: 0px;
  right: 0px;
  bottom: 0px;
  background-color: rgba(0,0,0,0.1);
  text-align: center;
}
div{
  padding: 2px;
}

jquery/javascript

$(".add-icon").click(function(){
    $("#emotepicker").toggle();
});

【问题讨论】:

  • @Felix Häberle 你对我的 css 的更改应该有什么帮助?
  • 看看stackoverflow.com/questions/3972014/… 开始编辑时保存插入符号位置,关闭表情面板时恢复。
  • 我发布的示例对您有帮助吗?
  • 随时为有帮助的答案投票。 ;)

标签: javascript jquery html contenteditable caret


【解决方案1】:

在单击事件方法中使用 jquery 焦点方法。

您可能希望将 new-mail-content div 设置为文本区域。这样的事情应该可以工作。

$(".add-icon").click(function(){
    $("#emotepicker").toggle();
    $("#new-mail-content").focus();
});

这里是文档的链接:https://api.jquery.com/focus/

【讨论】:

  • 这并不能真正回答问题。如问题中所述,我正在使用内容可编辑的 div。我无法解决这个问题。对于文本区域,将插入符号放回原来的位置并不是问题。 .focus() 也不保留插入符号的旧位置。
  • 仅仅通过关注控件是不行的,因为在它前面打开另一个 div 后编辑器不再存在。您需要保存光标位置并在该 div 关闭后恢复它。
  • 嗯,我可能已经太快忽略了这个答案。由于某种原因,它实际上将插入符号返回到以前的位置:jsfiddle.net/bdy2Ltwo/6。这是 jQuery 的一些内置功能吗?我在官方 jQuery 文档中找不到任何关于插入符号的信息。这在所有浏览器中是否可靠(它似乎在 Chrome 和 MS-Edge 中工作)?
  • 自 2006 年 1.0 版本以来,focus 方法一直是 JQuery 的一部分。我不能确定它是否适用于所有浏览器,但我认为应该支持 11 年前的功能。
【解决方案2】:

这应该可以满足您的需要:

var caretpos =0 ;
$(".add-icon").click(function(){
    $("#emotepicker").toggle();
});

$('#close').click(function(e){
    $("#emotepicker").toggle();
  $("#new-mail-content").focus();
  var node = document.querySelector("new-mail-content");
  node.focus();
  var textNode = node.firstChild;
  var caret = caretpos;
  var range = document.createRange();
  range.setStart(textNode, caret);
  range.setEnd(textNode, caret);
  var sel = window.getSelection();
  sel.removeAllRanges();
  sel.addRange(range);
})

function getCaretCharacterOffsetWithin(element) {
    var caretOffset = 0;
    var doc = element.ownerDocument || element.document;
    var win = doc.defaultView || doc.parentWindow;
    var sel;
    if (typeof win.getSelection != "undefined") {
        sel = win.getSelection();
        if (sel.rangeCount > 0) {
            var range = win.getSelection().getRangeAt(0);
            var preCaretRange = range.cloneRange();
            preCaretRange.selectNodeContents(element);
            preCaretRange.setEnd(range.endContainer, range.endOffset);
            caretOffset = preCaretRange.toString().length;
        }
    } else if ( (sel = doc.selection) && sel.type != "Control") {
        var textRange = sel.createRange();
        var preCaretTextRange = doc.body.createTextRange();
        preCaretTextRange.moveToElementText(element);
        preCaretTextRange.setEndPoint("EndToEnd", textRange);
        caretOffset = preCaretTextRange.text.length;
    }
    return caretOffset;
}

function showCaretPos() {
    var el = document.getElementById("new-mail-content");
    var caretPosEl = document.getElementById("caretposition");
    caretpos = getCaretCharacterOffsetWithin(el);
    caretPosEl.innerHTML = "Caret position: " + carePosEl;
}

document.body.onkeyup = showCaretPos;
document.body.onmouseup = showCaretPos;

https://jsfiddle.net/bdy2Ltwo/4/

【讨论】:

  • getCaretCharacterOffsetWithin(element) 似乎很有魅力。您在“showCaretPos()”中犯了一个小错字; carePosEl 应该是 caretposEl。在 "$('#close').click(function(e)" 我不确定 document.querySelector("new-mail-content") 是否正确。这实际上导致我删除了部分代码并结束了与 John Meyer 的回答一致。您的回答是朝着正确方向迈出的非常好的一步,但可能会带来更好的跨浏览器兼容性。
  • 你说得对,我试过了,但我不能,它说需要编辑才能投票。我试图修改它(我不能添加任何有意义的东西)但需要通过同行评审。如果您在帖子中添加内容,我会尽快投票。
  • 谢谢,但是评论是针对 RMo 的。我想我可以将链接移到底部...
猜你喜欢
  • 2019-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-06
  • 2012-05-11
  • 2011-06-02
  • 2014-07-29
  • 1970-01-01
相关资源
最近更新 更多