Comment obtenir la position de la colonne caret (pas les pixels) dans une zone de texte, en caractères, depuis le début?

StackOverflow https://stackoverflow.com/questions/263743

Question

Comment obtenez-vous la position du curseur dans une <textarea> utilisation de JavaScript?

Par exemple: This is| a text

Ceci devrait renvoyer 7.

Comment voulez-vous qu'il retourne les chaînes entourant le curseur / la sélection?

Exemple: 'This is', '', ' a text'.

Si le mot & # 8220; est & # 8221; est mis en surbrillance, il renverra 'This ', 'is', ' a text'.

Était-ce utile?

La solution

Avec Firefox, Safari (et les autres navigateurs basés sur Gecko), vous pouvez facilement utiliser textarea.selectionStart, mais pour IE, cela ne fonctionne pas. Vous devrez donc faire quelque chose comme ceci:

function getCaret(node) {
  if (node.selectionStart) {
    return node.selectionStart;
  } else if (!document.selection) {
    return 0;
  }

  var c = "\001",
      sel = document.selection.createRange(),
      dul = sel.duplicate(),
      len = 0;

  dul.moveToElementText(node);
  sel.text = c;
  len = dul.text.indexOf(c);
  sel.moveStart('character',-1);
  sel.text = "";
  return len;
}

( code complet ici )

Je vous recommande également de consulter le FieldSelection Plugin de jQuery, ce qui vous permet de le faire et beaucoup plus ...

Modifier: j'ai effectivement réimplémenté le code ci-dessus:

function getCaret(el) { 
  if (el.selectionStart) { 
    return el.selectionStart; 
  } else if (document.selection) { 
    el.focus(); 

    var r = document.selection.createRange(); 
    if (r == null) { 
      return 0; 
    } 

    var re = el.createTextRange(), 
        rc = re.duplicate(); 
    re.moveToBookmark(r.getBookmark()); 
    rc.setEndPoint('EndToStart', re); 

    return rc.text.length; 
  }  
  return 0; 
}

Consultez un exemple ici .

Autres conseils

Mis à jour le 5 septembre 2010

Comme tout le monde semble être dirigé ici pour cette question, j'ajoute ma réponse à une question similaire, qui contient le même code que cette réponse, mais avec un arrière-plan complet pour ceux qui sont intéressés:

Document.selection.createRangeRange de IE ne pas inclure de lignes vides de début ou de fin

Il est difficile de prendre en compte les sauts de ligne de fin dans IE, et je n’ai pas vu de solution permettant de le faire correctement, y compris d’autres réponses à cette question. Il est cependant possible d’utiliser la fonction suivante qui vous renverra le début et la fin de la sélection (identiques dans le cas d’un curseur) dans un <textarea> ou un texte <input>.

Notez que la zone de texte doit avoir le focus pour que cette fonction fonctionne correctement dans IE. En cas de doute, appelez d’abord la focus() méthode de la textarea

.
function getInputSelection(el) {
    var start = 0, end = 0, normalizedValue, range,
        textInputRange, len, endRange;

    if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
        start = el.selectionStart;
        end = el.selectionEnd;
    } else {
        range = document.selection.createRange();

        if (range && range.parentElement() == el) {
            len = el.value.length;
            normalizedValue = el.value.replace(/\r\n/g, "\n");

            // Create a working TextRange that lives only in the input
            textInputRange = el.createTextRange();
            textInputRange.moveToBookmark(range.getBookmark());

            // Check if the start and end of the selection are at the very end
            // of the input, since moveStart/moveEnd doesn't return what we want
            // in those cases
            endRange = el.createTextRange();
            endRange.collapse(false);

            if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
                start = end = len;
            } else {
                start = -textInputRange.moveStart("character", -len);
                start += normalizedValue.slice(0, start).split("\n").length - 1;

                if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
                    end = len;
                } else {
                    end = -textInputRange.moveEnd("character", -len);
                    end += normalizedValue.slice(0, end).split("\n").length - 1;
                }
            }
        }
    }

    return {
        start: start,
        end: end
    };
}

J'ai modifié la fonction ci-dessus pour prendre en compte les retours à la ligne dans IE. Cela n’a pas été testé, mais j’ai fait quelque chose de similaire avec cela dans mon code, il devrait donc être viable.

function getCaret(el) {
  if (el.selectionStart) { 
    return el.selectionStart; 
  } else if (document.selection) { 
    el.focus(); 

    var r = document.selection.createRange(); 
    if (r == null) { 
      return 0; 
    } 

    var re = el.createTextRange(), 
    rc = re.duplicate(); 
    re.moveToBookmark(r.getBookmark()); 
    rc.setEndPoint('EndToStart', re); 

    var add_newlines = 0;
    for (var i=0; i<rc.text.length; i++) {
      if (rc.text.substr(i, 2) == '\r\n') {
        add_newlines += 2;
        i++;
      }
    }

    //return rc.text.length + add_newlines;

    //We need to substract the no. of lines
    return rc.text.length - add_newlines; 
  }  
  return 0; 
}

Si vous n'avez pas besoin de supporter IE, vous pouvez utiliser les attributs selectionStart et selectionEnd de textarea.

Pour obtenir la position du curseur, utilisez simplement <=>:

function getCaretPosition(textarea) {
  return textarea.selectionStart
}

Pour obtenir les chaînes entourant la sélection, utilisez le code suivant:

function getSurroundingSelection(textarea) {
  return [textarea.value.substring(0, textarea.selectionStart)
         ,textarea.value.substring(textarea.selectionStart, textarea.selectionEnd)
         ,textarea.value.substring(textarea.selectionEnd, textarea.value.length)]
}

démonstration sur JSFiddle .

Voir aussi les documents HTMLTextAreaElement .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top