Obtenir la position du curseur dans contentEditable div

Je trouve des tonnes de bons anwers crossbrowser sur la façon de définir la position du curseur ou du curseur dans un DIV contentEditable, mais aucun sur la façon d'obtenir ou de trouver sa position...

Ce que je veux faire est de connaître la position du curseur dans cette div, sur keyup.

Ainsi, lorsque l'utilisateur tape du texte, je peux à tout moment connaître la position de son curseur dans le div.

EDIT: je cherche l'INDEX dans le contenu div (texte), pas les coordonnées du curseur.

<div id="contentBox" contentEditable="true"></div>

$('#contentbox').keyup(function() { 
    // ... ? 
});
75
demandé sur Bertvan 2010-10-19 23:35:28

6 réponses

Le code suivant suppose:

  • Il y a toujours un seul nœud de texte dans l'éditable <div> et aucun autre nœud
  • le div modifiable n'a pas la propriété CSS white-space définie sur pre

Code:

function getCaretPosition(editableDiv) {
  var caretPos = 0,
    sel, range;
  if (window.getSelection) {
    sel = window.getSelection();
    if (sel.rangeCount) {
      range = sel.getRangeAt(0);
      if (range.commonAncestorContainer.parentNode == editableDiv) {
        caretPos = range.endOffset;
      }
    }
  } else if (document.selection && document.selection.createRange) {
    range = document.selection.createRange();
    if (range.parentElement() == editableDiv) {
      var tempEl = document.createElement("span");
      editableDiv.insertBefore(tempEl, editableDiv.firstChild);
      var tempRange = range.duplicate();
      tempRange.moveToElementText(tempEl);
      tempRange.setEndPoint("EndToEnd", range);
      caretPos = tempRange.text.length;
    }
  }
  return caretPos;
}
#caretposition {
  font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="contentbox" contenteditable="true">Click me and move cursor with keys or mouse</div>
<div id="caretposition">0</div>
<script>
  var update = function() {
    $('#caretposition').html(getCaretPosition(this));
  };
  $('#contentbox').on("mousedown mouseup keydown keyup", update);
</script>
87
répondu Tim Down 2014-12-04 11:13:21

Essayez ceci:

Caret.js Obtenir la position du caret et le décalage du champ de texte

Https://github.com/ichord/Caret.js

Démo: http://ichord.github.com/Caret.js

12
répondu J.Y Han 2014-06-02 08:29:51

$("#editable").on('keydown keyup mousedown mouseup',function(e){
		   
       if($(window.getSelection().anchorNode).is($(this))){
    	  $('#position').html('0')
       }else{
         $('#position').html(window.getSelection().anchorOffset);
       }
 });
body{
  padding:40px;
}
#editable{
  height:50px;
  width:400px;
  border:1px solid #000;
}
#editable p{
  margin:0;
  padding:0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<div contenteditable="true" id="editable">move the cursor to see position</div>
<div>
position : <span id="position"></span>
</div>
11
répondu Eisa Qasemi 2016-04-05 10:28:51
//global savedrange variable to store text range in
var savedrange = null;

function getSelection()
{
    var savedRange;
    if(window.getSelection && window.getSelection().rangeCount > 0) //FF,Chrome,Opera,Safari,IE9+
    {
        savedRange = window.getSelection().getRangeAt(0).cloneRange();
    }
    else if(document.selection)//IE 8 and lower
    { 
        savedRange = document.selection.createRange();
    }
    return savedRange;
}

$('#contentbox').keyup(function() { 
    var currentRange = getSelection();
    if(window.getSelection)
    {
        //do stuff with standards based object
    }
    else if(document.selection)
    { 
        //do stuff with microsoft object (ie8 and lower)
    }
});

Remarque: l'objet range lui-même peut être stocké dans une variable, et peut être re-sélectionné à tout moment à moins que le contenu de la div contenteditable change.

Référence pour IE 8 et inférieur: http://msdn.microsoft.com/en-us/library/ms535872 (VS.85).aspx

Référence pour les navigateurs standards (tous les autres) : https://developer.mozilla.org/en/DOM/range (c'est les documents mozilla, mais le code fonctionne aussi dans chrome, safari, opera et ie9)

4
répondu Nico Burns 2010-10-19 20:16:35

Celui-ci fonctionne pour moi:

function getCaretCharOffsetInDiv(element) {
    var caretOffset = 0;
    if (typeof window.getSelection != "undefined") {
        var range = window.getSelection().getRangeAt(0);
        var preCaretRange = range.cloneRange();
        preCaretRange.selectNodeContents(element);
        preCaretRange.setEnd(range.endContainer, range.endOffset);
        caretOffset = preCaretRange.toString().length;
    }
    else if (typeof document.selection != "undefined" && document.selection.type != "Control")
    {
        var textRange = document.selection.createRange();
        var preCaretTextRange = document.body.createTextRange();
        preCaretTextRange.moveToElementText(element);
        preCaretTextRange.setEndPoint("EndToEnd", textRange);
        caretOffset = preCaretTextRange.text.length;
    }
    return caretOffset;
} 

La ligne d'appel dépend du type d'événement, pour l'événement clé, utilisez ceci:

getCaretCharOffsetInDiv(e.target) + ($(window.getSelection().getRangeAt(0).startContainer.parentNode).index());

Pour l'événement de la souris, utilisez ceci:

getCaretCharOffsetInDiv(e.target.parentElement) + ($(e.target).index())

Sur ces deux cas, je prends soin des lignes de rupture en ajoutant l'index cible

2
répondu Jonathan R. 2015-05-22 15:11:06
function getCaretPosition() {
    var x = 0;
    var y = 0;
    var sel = window.getSelection();
    if(sel.rangeCount) {
        var range = sel.getRangeAt(0).cloneRange();
        if(range.getClientRects()) {
        range.collapse(true);
        var rect = range.getClientRects()[0];
        if(rect) {
            y = rect.top;
            x = rect.left;
        }
        }
    }
    return {
        x: x,
        y: y
    };
}
2
répondu Nishad Up 2016-03-11 14:46:23