İçeriği düzenlenebilir bir HTML öğesinde programlı olarak metin mi seçiyorsunuz?


119

JavaScript'te, bir inputveya textareaöğesindeki metni programlı olarak seçmek mümkündür . Bir girdiyi ile odaklayabilir ipt.focus()ve ardından içeriğini seçebilirsiniz ipt.select(). İle belirli bir aralık bile seçebilirsiniz ipt.setSelectionRange(from,to).

Sorum şu: Bunu bir contenteditableunsurda da yapmanın bir yolu var mı?

elem.focus()İmleci bir contenteditableöğeye koymak için yapabileceğimi öğrendim , ancak daha sonra koşmak elem.select()işe yaramıyor (ve işe yaramıyor setSelectionRange). İnternette bununla ilgili hiçbir şey bulamıyorum, ama belki de yanlış şeyi arıyorum ...

Bu arada, eğer herhangi bir fark yaratırsa, bunun bir Chrome uzantısı için olduğu gibi yalnızca Google Chrome'da çalışmasına ihtiyacım var.

Yanıtlar:


170

Chrome'da bir öğenin tüm içeriğini (memnun olsun ya da olmasın) seçmek istiyorsanız, işte bunu nasıl yapacağınız. Bu, Firefox, Safari 3+, Opera 9+ (muhtemelen daha önceki sürümler de) ve IE 9'da da çalışacaktır. Ayrıca karakter düzeyine kadar seçimler de oluşturabilirsiniz. İhtiyacınız olan API'ler, DOM Aralığı (geçerli özellik DOM Seviye 2'dir , ayrıca MDN'ye bakın ) ve yeni bir Aralık spesifikasyonunun ( MDN belgeleri ) parçası olarak belirtilen Seçimdir .

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

15
Ekstra uyumluluk selectElementContents()için bir setTimeout()veya requestAnimationFrame()bir onfocus. Bkz jsfiddle.net/rudiedirkx/MgASG/1/show
Rudie

@Dylan: Emin değilim: soru OP'nin zaten kullandığından bahsediyor focus().
Tim Down

4
@Rudie Uyumluluğu hangi uygulama için?
yckart

Masaüstünde harika çalışıyor. Mobil tarayıcılarda çalışmıyor. Seçim yapılmadı. İPhone iOS 11'de Safari ve Chrome'u denedim.
campbell

1
@campbell: Zaten bir seçiminiz olması koşuluyla , en azından iOS'ta Safari'de çalışır . Aksi takdirde hayır, tarayıcı muhtemelen kullanıcı deneyimi nedenlerinden ötürü JavaScript'in bir seçim göstermesine izin vermez.
Tim Down

34

Tim Downs cevabına ek olarak , oldIE'de bile çalışan bir çözüm geliştirdim:

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;​

IE 8+, Firefox 3+, Opera 9+ ve Chrome 2+ ile test edilmiştir. Ben bile bir jQuery eklentisine kurdum:

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

... ve kimin ilgisini çekti, işte tüm kahve bağımlıları için aynı şey:

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

Güncelleme:

Düzenlenebilir bir bölgenin (ile işaretli contentEditable) tüm sayfayı veya içeriğini seçmek istiyorsanız , aşağıdakilere geçip designModekullanarak bunu çok daha basit bir şekilde yapabilirsiniz document.execCommand:

MDN'de iyi bir başlangıç ​​noktası ve küçük bir dokümantasyon var .

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

(IE6 +, Opera 9+, Firefoy 3+, Chrome 2+ ile iyi çalışır) http://caniuse.com/#search=execCommand


10

Mevcut yanıtların tümü divöğelerle ilgilendiğinden, bunun nasıl yapılacağını spans ile açıklayacağım .

Bir metin aralığı seçerken ince bir fark var span. Metin başlangıç ​​ve bitiş dizinini geçebilmek için Text, burada açıklandığı gibi bir düğüm kullanmanız gerekir :

StartNode, Text, Comment veya CDATASection türünde bir Düğümse, startOffset, startNode'un başlangıcından itibaren karakter sayısıdır. Diğer Düğüm türleri için, startOffset, startNode'un başlangıcı arasındaki alt düğümlerin sayısıdır.

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

Gerçekten şöyle olmalı: r.setStart(e.firstChild,0); r.setEnd(e.lastChild,e.lastChild.textContent.length); Elbette e.firstChild'in aslında boş olmadığını kontrol etmelisiniz.
Yorick

2
A <div>ve bir <span>elemanda seçim yapmak arasında fark yoktur . En azından tarif ettiğiniz gibi değil.
Tim Down

Div ve span arasında farklılıklar vardır, bazı durumlarda div için bir çözüm span içinde doğru çalışmaz. Örneğin, div çözümüyle programlı olarak metin seçip yeni içeriği yapıştırırsanız, tüm metni değil, yalnızca bir parçayı değiştirir ve chrome ile firefox arasında farklar vardır
neosonne

6

Rangy, bu çapraz tarayıcıyı aynı kodla yapmanızı sağlar. Rangy, seçimler için DOM yöntemlerinin tarayıcılar arası bir uygulamasıdır. İyi test edilmiştir ve bunu çok daha az acı verici hale getirir. Onsuz tatmin edici dokunuşları reddediyorum.

Rangy'yi burada bulabilirsiniz:

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

Projenizde rangy ile, tarayıcı IE 8 veya öncesi olsa ve seçimler için tamamen farklı bir yerel API'ye sahip olsa bile bunu her zaman yazabilirsiniz:

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

"ContentEditableNode", içerik düzenlenebilir özelliğe sahip DOM düğümüdür. Bunu şu şekilde getirebilirsiniz:

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

Veya jQuery zaten projenizin bir parçasıysa ve uygun buluyorsanız:

var contentEditable = $('.some-selector')[0];

Rangy projesi şimdi Github'a taşındı: github.com/timdown/rangy
tanius

4

İşleri yapmanın modern yolu böyledir. MDN hakkında daha fazla ayrıntı

document.addEventListener('dblclick', (event) => {
  window.getSelection().selectAllChildren(event.target)
})
<div contenteditable="true">Some text</div>


Teşekkürler, bu harika çalışıyor! Fwiw, o MDN sayfası bu teknolojiyi deneysel olarak işaretliyor. Ancak, Haziran 2020'de Chrome ve
FF'nin

2

[Hatayı düzeltmek için güncellendi]

İşte bu yanıttan uyarlanmış ve Chrome'da iyi çalıştığı görülen bir örnek: Keyifli div'de aralığı seçin

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:

<div id="myText" contenteditable>test</div>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.