web-dev-qa-db-fra.com

contenteditable, placez le curseur à la fin du texte (cross-browser)

sortie en Chrome:

<div id="content" contenteditable="true" style="border:1px solid #000;width:500px;height:40px;">
    hey
    <div>what's up?</div>
<div>
<button id="insert_caret"></button>

Je crois en FF cela ressemblerait à ceci:

hey
<br />
what's up?

et en IE :

hey
<p>what's up?</p>

malheureusement, il n'y a pas de moyen sympa de faire en sorte que chaque navigateur insère un <br /> au lieu d'une balise div ou p, ou du moins je n'ai rien trouvé en ligne.


Quoi qu'il en soit, ce que j'essaie de faire maintenant, c'est que lorsque je tape sur le bouton, je veux que le curseur soit défini à la fin du texte, il devrait donc ressembler à ceci:

hey
what's up?|

aucune façon de le faire pour que cela fonctionne dans tous les navigateurs?

exemple:

$(document).ready(function()
{
    $('#insert_caret').click(function()
    {
        var ele = $('#content');
        var length = ele.html().length;

        ele.focus();

        //set caret -> end pos
     }
 }
103
user317005

La fonction suivante le fera dans tous les principaux navigateurs:

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>

Placer le curseur au début est presque identique: il suffit de changer le booléen passé dans les appels à collapse(). Voici un exemple qui crée des fonctions pour placer le curseur au début et à la fin:

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);
263
Tim Down

Malheureusement, l'excellente réponse de Tim n'a fonctionné pour moi que pour le placement à la fin, pour le placement au début, j'ai dû le modifier légèrement.

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

Je ne sais pas si si focus() et select() sont réellement nécessaires.

5
dimid