Par programmation sélectionner du texte dans un contenteditable élément HTML?

en JavaScript, il est possible de sélectionner programmatiquement un texte dans un élément input ou textarea . Vous pouvez focaliser une entrée avec ipt.focus() , puis sélectionner son contenu avec ipt.select() . Vous pouvez même sélectionner une gamme spécifique avec ipt.setSelectionRange(from,to) .

ma question Est: y a-t-il un moyen de le faire dans un élément contenteditable aussi?

j'ai trouvé que je peux faire elem.focus() , pour mettre le caret dans un élément contenteditable , mais ensuite lancer elem.select() ne fonctionne pas (et ne fonctionne pas non plus setSelectionRange ). Je ne trouve rien sur le web à ce sujet, mais peut-être que je cherche la mauvaise chose...

soit dit en passant, si cela fait une différence, je n'en ai besoin que pour travailler dans Google Chrome, car c'est pour une extension Chrome.

88
demandé sur Cœur 2011-05-26 17:16:13

6 réponses

Si vous souhaitez sélectionner tout le contenu d'un élément (contenteditable ou pas) dans Chrome, voici comment. Cela fonctionnera également dans Firefox, Safari 3+, Opera 9+ (peut-être des versions plus anciennes aussi) et IE 9. Vous pouvez également créer des sélections jusqu'au niveau du caractère. Les API dont vous avez besoin sont DOM gamme (Spec actuel est DOM Niveau 2 , voir aussi MDN ) et la sélection , qui est spécifiée dans le cadre d'un new Range spec ( MDN docs ).

function selectElementContents(el) {
    var range = document.createRange();
    range.selectNodeContents(el);
    var sel = window.getSelection();
    sel.removeAllRanges();
    sel.addRange(range);
}

var el = document.getElementById("foo");
selectElementContents(el);
136
répondu Tim Down 2011-05-27 09:13:36

en plus de Tim Downs réponse , j'ai fait une solution qui fonctionne même en oldIE:

var selectText = function() {
  var range, selection;
  if (document.body.createTextRange) {
    range = document.body.createTextRange();
    range.moveToElementText(this);
    range.select();
  } else if (window.getSelection) {
    selection = window.getSelection();
    range = document.createRange();
    range.selectNodeContents(this);
    selection.removeAllRanges();
    selection.addRange(range);
  }
};

document.getElementById('foo').ondblclick = selectText;​

testé dans IE 8+, Firefox 3+, Opera 9+, & Chrome 2+. Même moi je l'ai mis en place dans un plugin jQuery:

jQuery.fn.selectText = function() {
  var range, selection;
  return this.each(function() {
    if (document.body.createTextRange) {
      range = document.body.createTextRange();
      range.moveToElementText(this);
      range.select();
    } else if (window.getSelection) {
      selection = window.getSelection();
      range = document.createRange();
      range.selectNodeContents(this);
      selection.removeAllRanges();
      selection.addRange(range);
    }
  });
};

$('#foo').on('dblclick', function() {
  $(this).selectText();
});

...et qui est intéressé, voici la même chose pour tous les accros du café:

jQuery.fn.selectText = ->
  @each ->
    if document.body.createTextRange
      range = document.body.createTextRange()
      range.moveToElementText @
      range.select()
    else if window.getSelection
      selection = window.getSelection()
      range = document.createRange()
      range.selectNodeContents @
      selection.removeAllRanges()
      selection.addRange range
    return

mise à jour:

si vous voulez sélectionner le page entière ou contenu d'une région modifiable (marqué avec contentEditable ), vous pouvez le faire beaucoup plus simple en passant à designMode et en utilisant document.execCommand :

Il y a un bon point de départ au MDN et un littledocumentation .

var selectText = function () {
  document.execCommand('selectAll', false, null);
};

(fonctionne bien dans IE6+, Opera 9+, Firefoy 3+, Chrome 2+) http://caniuse.com/#search=execCommand

33
répondu yckart 2017-05-23 11:33:25

Rangy vous permet de faire ce cross-browser avec le même code. Rangy est une implémentation cross-browser des méthodes DOM pour les sélections. Il est bien testé et rend cela beaucoup moins douloureux. Je refuse de toucher contenteditable sans elle.

vous pouvez trouver rangy ici:

http://code.google.com/p/rangy /

avec rangy dans votre projet, vous pouvez toujours écrire ceci, même si le navigateur est IE 8 ou plus tôt et a une API native complètement différente pour les sélections:

var range = rangy.createRange();
range.selectNodeContents(contentEditableNode);
var sel = rangy.getSelection();
sel.removeAllRanges();
sel.addRange(range);

où "contentEditableNode" est le noeud DOM qui possède l'attribut contenteditable. Vous pourriez le rapporter comme ceci:

var contentEditable = document.getElementById('my-editable-thing');

ou si jQuery fait déjà partie de votre projet et que vous le trouvez pratique:

var contentEditable = $('.some-selector')[0];
6
répondu Tom Boutell 2013-01-12 16:14:32

puisque toutes les réponses existantes traitent des éléments div , je vais vous expliquer comment le faire avec span S.

il y a une différence subtile lors de la sélection d'une plage de texte dans un span . Pour pouvoir passer l'index de début et de fin de texte, vous devez utiliser un noeud Text , comme décrit ici :

si le startNode est un noeud de type Text, Comment ou CDATASection, puis startOffset est le nombre de caractères à partir du début de startNode. Pour les autres types de noeuds, startOffset est le nombre d'enfants noeuds entre le début du startNode.

var e = document.getElementById("id of the span element you want to select text in");
var textNode = e.childNodes[0]; //text node is the first child node of a span

var r = document.createRange();
var startIndex = 0;
var endIndex = textNode.textContent.length;
r.setStart(textNode, startIndex);
r.setEnd(textNode, endIndex);

var s = window.getSelection();
s.removeAllRanges();
s.addRange(r);
6
répondu Domysee 2017-10-10 06:18:57

[mise à jour pour corriger l'erreur]

voici un exemple adapté de cette réponse qui semble bien fonctionner dans Chrome - Select range in contenteditable div

var elm = document.getElementById("myText"),
    fc = elm.firstChild,
    ec = elm.lastChild,
    range = document.createRange(),
    sel;
elm.focus();
range.setStart(fc,1);
range.setEnd(ec,3);
sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);

HTML is:

<div id="myText" contenteditable>test</div>
2
répondu patorjk 2017-05-23 12:34:59

contenteditable est juste un attribut, qui est interprété par navigateur. Vous pouvez modifier ces éléments avec des fonctions DOM ordinaires.

voir TextRanges javascript .

Btw, recherche rapide dans l'affirmative, m'a donné quelques résultats .

-6
répondu Deele 2011-05-26 13:44:23