【问题标题】:Get and set cursor position with contenteditable div使用 contenteditable div 获取和设置光标位置
【发布时间】:2015-12-04 15:26:58
【问题描述】:

我有一个内容可编辑的 div,我希望能够让用户插入链接、图片或 YouTube 视频等内容。目前这就是我所拥有的:

function addLink() {
  var link = $('#url').val();
  $('#editor').focus();
  document.execCommand('createLink', false, link);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Text Editor -->
<div id="editor" contenteditable="true"></div>

<!-- Add Link -->
<input type="text" id="url">
<button onclick="addLink()">Submit</button>

如您所见,用户必须在单独的文本框中输入链接地址。结果,当链接被添加到编辑器时,它并没有被添加到指针/插入符号所在的位置。

我的问题是如何获取和设置指针/插入符号的位置。我见过其他问题,例如this for setting the pointer,但我希望有一个所有现代浏览器都支持的解决方案,包括 Chrome、Safari、Firefox 和 IE9+。

有什么想法吗?谢谢。

编辑:

我在下面找到了获取位置的代码,但是它只根据它所在的行获取位置。例如,如果我有这个(| 是光标):

This is some text
And som|e more text

然后我将返回值 7,而不是 24。

function getPosition() {
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt) {
            return sel.getRangeAt(0).startOffset;
        }
    }
    return null;
}

【问题讨论】:

  • 您链接到的解决方案确实有一个适用于所有浏览器的解决方案,只需阅读超出接受的浏览器即可。至于获取光标位置试试这个:stackoverflow.com/questions/4767848/…
  • @SunKnight0 我从您提供的解决方案中尝试了以下代码,但是它一如既往地返回 0.var editor = document.getElementById('#editor'); console.log( getCaretCharacterOffsetWithin(editor) ); 我使用了这个答案中的函数stackoverflow.com/questions/4811822/…
  • 使用getElementById('editor')。您正在将原生 JavaScript 与 JQuery 混合使用。
  • @SunKnight0 抱歉,评论有误。即使使用getElementById('editor'),插入符号的位置也是0。

标签: javascript jquery html


【解决方案1】:

现场有大量相关信息。这个适合我和我的客户。

DEMO

https://stackoverflow.com/a/6249440/2813224

function setCaret(line, col) {
  var ele = document.getElementById("editable");
  var rng = document.createRange();
  var sel = window.getSelection();
  rng.setStart(ele.childNodes[line], col);
  rng.collapse(true);
  sel.removeAllRanges();
  sel.addRange(rng);
  ele.focus();
}

//https://stackoverflow.com/a/6249440/2813224

var line = document.getElementById('ln').value;
var col = document.getElementById('cl').value;
var btn = document.getElementById('btn');
btn.addEventListener('click', function(event) {
  var lineSet = parseInt(line, 10);
  var colSet = parseInt(col, 10);
  setCaret(lineSet, colSet);
}, true);
<div id="editable" contenteditable="true">
  <br/>text text text text text text
  <br/>text text text text text text
  <br/>text text text text text text
  <br/>
  <br/>
</div>
<fieldset>
  <button id="btn">focus</button>
  <input type="button" class="fontStyle" onclick="document.execCommand('italic',false,null);" value="I" title="Italicize Highlighted Text">
  <input type="button" class="fontStyle" onclick="document.execCommand('bold',false,null);" value="B" title="Bold Highlighted Text">
  <input id="ln" placeholder="Line#" />
  <input id="cl" placeholder="Column#" />
</fieldset>

【讨论】:

    【解决方案2】:

    一个好的富文本编辑器是目前最难做的事情之一,而且它本身几乎就是一个项目(不友好的 API、大量的极端情况、跨浏览器的差异等等)。我强烈建议您尝试找到现有的解决方案。

    一些可以使用的库包括:

    【讨论】:

    • 感谢您的回答,但是我想要一个简单的文本编辑器,而不是像代码镜像这样的代码编辑器。
    • 感谢您添加 Quill 和 WYSIHTML。这些似乎更适合您在问题中概述的内容。
    【解决方案3】:

    我试图找到解决方案,

    稍加帮助即可完善。 这是我在 SO 上找到的答案和我的经验的组合。

    它很棘手,很乱......但如果你必须,你可以使用它,但它需要一些工作来支持内部链接(如果你的光标在锚上,它会在锚内创建锚)

    这是 JS:

    var lastPos;
    var curNode = 0;
    function setCaret() {
      curNode=0;
      var el = document.getElementById("editor");
      var range = document.createRange();
      var sel = window.getSelection();
    
      console.log(el.childNodes);
      if (el.childNodes.length > 0) {
          while (lastPos > el.childNodes[curNode].childNodes[0].textContent.length) {
          lastPos = lastPos - el.childNodes[curNode].childNodes[0].textContent.length;
          curNode++;
    
          }
          range.setStart(el.childNodes[curNode].childNodes[0], lastPos);
          range.collapse(true);
          sel.removeAllRanges();
          sel.addRange(range);
      }
      el.focus();
    };
    
    
    function savePos() {
      lastPos = getCaretCharacterOffsetWithin(document.getElementById('editor'));
    }
    
    function addLink() {
      console.log(lastPos);
    
      setCaret();
      console.log(getCaretCharacterOffsetWithin(document.getElementById('editor')));
    
      console.log('focus');
    
      // $("#editor").focus();
      var link = $('#url').val();
      document.execCommand('createLink', false, link);
    
    }
    
    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;
    }
    

    fiddle

    【讨论】:

      【解决方案4】:

      这是您在赏金中所要求的:在以下示例中,您可以看到如何检测您单击鼠标的实际点的确切字符数:

         <!-- Text Editor -->
         <div id="editor" class="divClass" contenteditable="true">type here some text</div>
      
      
          <script>
      
      
      
         document.getElementById("editor").addEventListener("mouseup", function(key) {
      
      alert(getCaretCharacterOffsetWithin(document.getElementById("editor")));
      
      }, false);
      
      
       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;
      }
       </script>
      

      【讨论】:

        【解决方案5】:

        我发现表情符号有问题。表情符号的长度大于 1。 我解决了。

        <script>
        function getCursorPosition() {
                if(window.getSelection()){
                    var sel = window.getSelection();
                    if(sel.getRangeAt){
                        var pos = sel.getRangeAt(0).startOffset;
                        var endPos = pos + Array.from(editor.innerHTML.slice(0,pos)).length - editor.innerHTML.slice(0,pos).split("").length;
                        return endPos;
                    }
                }
                return null;
            }
        var editor = document.querySelector("#editor");
        var output = document.querySelector("#output");
        editor.addEventListener("input",function(){
        output.innerHTML = "Selection: " +  getCursorPosition();
        });
        
        </script>
        <div contenteditable id="editor">text</div>
        <div id="output">Selection:</div>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-11-13
          • 1970-01-01
          • 2011-02-21
          • 2018-07-01
          • 1970-01-01
          • 2015-05-29
          • 2017-09-17
          • 2017-05-06
          相关资源
          最近更新 更多