contenteditable, set caret at the end of the text (cross-browser)

前端 未结 4 1759
小鲜肉
小鲜肉 2020-11-22 06:56

output in Chrome:

hey &
相关标签:
4条回答
  • 2020-11-22 07:31

    This (live) example shows a short simple function, setCaretAtStartEnd, which takes two arguments; A (editable) node to place the caret at & a Boolean indicating where to place it (start or end of the node)

    const editableElm = document.querySelector('[contenteditable]');
    
    document.querySelectorAll('button').forEach((elm, idx) => 
      elm.addEventListener('click', () => {
        editableElm.focus()
        setCaretAtStartEnd(editableElm, idx) 
      })
    )
    
    function setCaretAtStartEnd( node, atEnd ){
      const sel = document.getSelection();
      node = node.firstChild;
    
      if( sel.rangeCount ){
          ['Start', 'End'].forEach(pos =>
            sel.getRangeAt(0)["set" + pos](node, atEnd ? node.length : 0)
          )
      }
    }
    [contenteditable]{ padding:5px; border:1px solid; }
    <h1 contenteditable>Place the caret anywhere</h1>
    <br>
    <button>Move caret to start</button>
    <button>Move caret to end</button>

    0 讨论(0)
  • 2020-11-22 07:39

    Unfortunately Tim's excellent answer worked for me only for placing at the end, for placing at the start I had to modify it slightly.

    function setCaret(target, isStart) {
      const range = document.createRange();
      const sel = window.getSelection();
      if (isStart){
        const newText = document.createTextNode('');
        target.appendChild(newText);
        range.setStart(target.childNodes[0], 0);
      }
      else {
        range.selectNodeContents(target);
      }
      range.collapse(isStart);
      sel.removeAllRanges();
      sel.addRange(range);
      target.focus();
      target.select();
    }
    

    Not sure though if focus() and select() are actually needed.

    0 讨论(0)
  • 2020-11-22 07:40

    If you are using the google closure compiler, you can do the following (somewhat simplified from Tim's answer):

    function placeCaretAtEnd(el) {
        el.focus();
        range = goog.dom.Range.createFromNodeContents(el);
        range.collapse(false);
        range.select();
    }
    

    Here's the same thing in ClojureScript:

    (defn place-caret-at-end [el] 
       (.focus el)
       (doto (.createFromNodeContents goog.dom.Range el)
             (.collapse false)
             .select))
    

    I have tested this in Chrome, Safari and FireFox, not sure about IE...

    0 讨论(0)
  • 2020-11-22 07:50

    The following function will do it in all major browsers:

    function placeCaretAtEnd(el) {
        el.focus();
        if (typeof window.getSelection != "undefined"
                && typeof document.createRange != "undefined") {
            var range = document.createRange();
            range.selectNodeContents(el);
            range.collapse(false);
            var sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
        } else if (typeof document.body.createTextRange != "undefined") {
            var textRange = document.body.createTextRange();
            textRange.moveToElementText(el);
            textRange.collapse(false);
            textRange.select();
        }
    }
    
    placeCaretAtEnd( document.querySelector('p') );
    p{ padding:.5em; border:1px solid black; }
    <p contentEditable>foo bar </p>

    Placing the caret at the start is almost identical: it just requires changing the Boolean passed into the calls to collapse(). Here's an example that creates functions for placing the caret at the start and at the end:

    function createCaretPlacer(atStart) {
        return function(el) {
            el.focus();
            if (typeof window.getSelection != "undefined"
                    && typeof document.createRange != "undefined") {
                var range = document.createRange();
                range.selectNodeContents(el);
                range.collapse(atStart);
                var sel = window.getSelection();
                sel.removeAllRanges();
                sel.addRange(range);
            } else if (typeof document.body.createTextRange != "undefined") {
                var textRange = document.body.createTextRange();
                textRange.moveToElementText(el);
                textRange.collapse(atStart);
                textRange.select();
            }
        };
    }
    
    var placeCaretAtStart = createCaretPlacer(true);
    var placeCaretAtEnd = createCaretPlacer(false);
    
    0 讨论(0)
提交回复
热议问题