İmlecin Javascript / jquery kullandığı bir metin ekleme


167

Çok fazla metin kutusu olan bir sayfam var. Birisi bir bağlantıyı tıklattığında, imlecin bulunduğu yere veya bir odağı olan metin kutusuna eklenecek bir veya iki sözcüğün eklenmesini istiyorum.

Örneğin, imleç / odak 'elma' diyen bir metin kutusu üzerindeyse ve '[e-posta]' diyen bir bağlantıyı tıklatırsa, metin kutusunun 'elma bob@example.com' demesini istiyorum.

Bunu nasıl yapabilirim? Odak radyo / açılır / metin kutusu olmayan bir öğe üzerinde olursa ne olur? Son odaklanan metin kutusu hatırlanabilir mi?


Bunun mümkün olduğunu düşünüyorum çünkü WYSISYG editörlerinin temeli, nasıl yapılacağını bilmiyorum.
Ian Elliott


Bu soruyu sorduğunuz için teşekkür ederim ... şimdi Chrome uzantımla imlece "[sürüm]" ekleyebilirim!
haykam

Geri alma desteğine sahip basit bir modül arıyorsanız, insert-text-textarea öğesini deneyin . IE8 + desteğine ihtiyacınız varsa, imleç-metin-imleç paketini deneyin .
fregante

Yanıtlar:


241

Bunu buradan kullanın :

function insertAtCaret(areaId, text) {
  var txtarea = document.getElementById(areaId);
  if (!txtarea) {
    return;
  }

  var scrollPos = txtarea.scrollTop;
  var strPos = 0;
  var br = ((txtarea.selectionStart || txtarea.selectionStart == '0') ?
    "ff" : (document.selection ? "ie" : false));
  if (br == "ie") {
    txtarea.focus();
    var range = document.selection.createRange();
    range.moveStart('character', -txtarea.value.length);
    strPos = range.text.length;
  } else if (br == "ff") {
    strPos = txtarea.selectionStart;
  }

  var front = (txtarea.value).substring(0, strPos);
  var back = (txtarea.value).substring(strPos, txtarea.value.length);
  txtarea.value = front + text + back;
  strPos = strPos + text.length;
  if (br == "ie") {
    txtarea.focus();
    var ieRange = document.selection.createRange();
    ieRange.moveStart('character', -txtarea.value.length);
    ieRange.moveStart('character', strPos);
    ieRange.moveEnd('character', 0);
    ieRange.select();
  } else if (br == "ff") {
    txtarea.selectionStart = strPos;
    txtarea.selectionEnd = strPos;
    txtarea.focus();
  }

  txtarea.scrollTop = scrollPos;
}
<textarea id="textareaid"></textarea>
<a href="#" onclick="insertAtCaret('textareaid', 'text to insert');return false;">Click Here to Insert</a>


7
Bu harika çalıştı, ancak tüm metin editörlerinin yaptığı gibi seçilen metnin değiştirilmesini sağlamaz. Bu, posterin orijinal sorusu için gerekli olmayabilir, ancak ihtiyacınız varsa, 'strPos'u' txtArea.selectionEnd 'ile değiştirebilirsiniz. Aşağıdaki cevabım, IE'nin eski sürümlerini desteklemeniz gerekmiyorsa tarayıcı algılama kodunun kaldırılmasıyla birlikte bunu gösteriyor.
Jeffrey Harmon

Tüm öğeleri seçmenin bir yolu var mı areaId?
haykam

1
Böyle bir işlev ekleyerek seçilen metni otomatik olarak silebilirsiniz. function deleteTxt() { var ele = document.getElementById('yourTextarea'); var text = ele.value; text = text.slice(0, ele.selectionStart) + text.slice(ele.selectionEnd); ele.value = text; return text; }
NSTuttle

Fare konumuna metin nasıl eklenir?
Thamarai T

En iyisi sensin!
Ecko Santoso

156

Belki daha kısa bir versiyon, anlaşılması daha kolay olur?

    jQuery("#btn").on('click', function() {
        var $txt = jQuery("#txt");
        var caretPos = $txt[0].selectionStart;
        var textAreaTxt = $txt.val();
        var txtToAdd = "stuff";
        $txt.val(textAreaTxt.substring(0, caretPos) + txtToAdd + textAreaTxt.substring(caretPos) );
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<textarea id="txt" rows="15" cols="70">There is some text here.</textarea>
<input type="button" id="btn" value="OK" />

Bunu jquery ile işaretçinin geçerli konumundan bir metin kutusuna nasıl metin eklenir?


11
Ayrıca ile değerini değiştirdikten sonra şapka konumunu geri yükleyebilirsiniz: document.getElementById("txt").selectionStart = caretPos + txtToAdd.length.
Bludwarf

1
benim için çalıştı, teşekkürler. FYI "selectionStart" özelliği jquery seçici $ ("#") ile mevcut değildir. Document.getElementById ()
Lego

1
jsfiddle.net/NaHTw/802 seçilen alanı yapıştırılan ile değiştirmek için biraz ekstra eklenen bir çözümdür
patrick

3
Eğer jQuery'yi bu kadar kaldırarak gidecekseniz, hepsini de kaldırabilirsiniz . ; ^)
ruffin

8
Sadece yardım etmek için, caret pozisyon geri yüklemesi ile komple çözüm ve seçilen alanı yapıştırılan içerikle değiştirin: jsfiddle.net/NaHTw/1028
AlfaTeK

41

George Claghorn'un onayladığı cevap, imleç konumuna metin eklemek için harika çalıştı. Kullanıcı metni seçtiyse ve metnin değiştirilmesini istiyorsanız (çoğu metinde varsayılan deneyim), 'geri' değişkenini ayarlarken küçük bir değişiklik yapmanız gerekir.

Ayrıca, IE'nin eski sürümlerini desteklemeniz gerekmiyorsa, modern sürümler textarea.selectionStart'ı destekler, böylece tüm tarayıcı algılamasını ve IE'ye özgü kodu çıkarabilirsiniz.

İşte en azından Chrome ve IE11 için çalışan ve seçilen metni değiştirmeyi işleyen basitleştirilmiş bir sürüm.

function insertAtCaret(areaId, text) {
    var txtarea = document.getElementById(areaId);
    var scrollPos = txtarea.scrollTop;
    var caretPos = txtarea.selectionStart;

    var front = (txtarea.value).substring(0, caretPos);
    var back = (txtarea.value).substring(txtarea.selectionEnd, txtarea.value.length);
    txtarea.value = front + text + back;
    caretPos = caretPos + text.length;
    txtarea.selectionStart = caretPos;
    txtarea.selectionEnd = caretPos;
    txtarea.focus();
    txtarea.scrollTop = scrollPos;
}

Bu iyidir, ancak öğenin maxlengthhesabını dikkate almaz , bu nedenle eklemeden sonraki sonuç değeri maksimumdan daha uzun olabilir.
mbomb007

22

Yukarıdaki kod IE'de benim için çalışmadı. İşte bu cevaba dayanan bazı kodlar .

Ben çıkardı getElementByIdben farklı bir şekilde eleman başvurmak böylece.

function insertAtCaret(element, text) {
  if (document.selection) {
    element.focus();
    var sel = document.selection.createRange();
    sel.text = text;
    element.focus();
  } else if (element.selectionStart || element.selectionStart === 0) {
    var startPos = element.selectionStart;
    var endPos = element.selectionEnd;
    var scrollTop = element.scrollTop;
    element.value = element.value.substring(0, startPos) +
      text + element.value.substring(endPos, element.value.length);
    element.focus();
    element.selectionStart = startPos + text.length;
    element.selectionEnd = startPos + text.length;
    element.scrollTop = scrollTop;
  } else {
    element.value += text;
    element.focus();
  }
}
input{width:100px}
label{display:block;margin:10px 0}
<label for="in2copy">Copy text from: <input id="in2copy" type="text" value="x"></label>
<label for="in2ins">Element to insert: <input id="in2ins" type="text" value="1,2,3" autofocus></label>
<button onclick="insertAtCaret(document.getElementById('in2ins'),document.getElementById('in2copy').value)">Insert</button>

EDIT: Çalışan bir snippet eklendi, jQuery kullanılmıyor .


Element bir jquery nesnesi mi, değil mi? element.value ve element.focus () her ikisi de çalışamaz ...
Scott Stafford

7
element.focus()DOMElements üzerinde meşru bir JavaScript yöntemidir: w3schools.com/jsref/met_html_focus.asp
oliverseal

1
En iyi fikir IE uyumluluğunu düşürmektir.
ar2015

2
Evet, bu cevabı 7 yıl önce yazdım. Bu noktada IE 11 iyi bir minimum desteklenen sürümdür ve yukarıdaki kod orada çalışır.
Collin Anderson

6

@quick_sliv yanıtını kullanarak:

function insertAtCaret(el, text) {
    var caretPos = el.selectionStart;
    var textAreaTxt = el.value;
    el.value = textAreaTxt.substring(0, caretPos) + text + textAreaTxt.substring(caretPos);
};

4

JQuery ve JavaScript aracılığıyla bir TextBox'ın mevcut imleç konumuna bazı Metin ekleme

süreç

  1. Geçerli İmleç Konumunu Bulma
  2. Kopyalanacak Metni Edinin
  3. Metni Orada Ayarla
  4. İmleç konumunu güncelleme

Burada 2 TextBox ve bir Button var. Bir metin kutusundaki belirli bir konuma tıklattıktan sonra metni diğer metin kutusundan önceki metin kutusunun konumuna yapıştırmak için düğmeye tıklamam gerekiyor.

Burada asıl mesele, metnin yapıştırılacağı geçerli imleç konumunu elde etmektir.

//Textbox on which to be pasted
<input type="text" id="txtOnWhichToBePasted" />

//Textbox from where to be pasted
<input type="text" id="txtFromWhichToBePasted" />


//Button on which click the text to be pasted
<input type="button" id="btnInsert" value="Insert"/>


<script type="text/javascript">

$(document).ready(function () {
    $('#btnInsert').bind('click', function () {
            var TextToBePasted = $('#txtFromWhichToBePasted').value;
            var ControlOnWhichToBePasted = $('#txtOnWhichToBePasted');

            //Paste the Text
            PasteTag(ControlOnWhichToBePasted, TextToBePasted);
        });
    });

//Function Pasting The Text
function PasteTag(ControlOnWhichToBePasted,TextToBePasted) {
    //Get the position where to be paste

    var CaretPos = 0;
    // IE Support
    if (document.selection) {

        ControlOnWhichToBePasted.focus();
        var Sel = document.selection.createRange();

        Sel.moveStart('character', -ctrl.value.length);

        CaretPos = Sel.text.length;
    }
    // Firefox support
    else if (ControlOnWhichToBePasted.selectionStart || ControlOnWhichToBePasted.selectionStart == '0')
        CaretPos = ControlOnWhichToBePasted.selectionStart;

    //paste the text
    var WholeString = ControlOnWhichToBePasted.value;
    var txt1 = WholeString.substring(0, CaretPos);
    var txt2 = WholeString.substring(CaretPos, WholeString.length);
    WholeString = txt1 + TextToBePasted + txt2;
    var CaretPos = txt1.length + TextToBePasted.length;
    ControlOnWhichToBePasted.value = WholeString;

    //update The cursor position 
    setCaretPosition(ControlOnWhichToBePasted, CaretPos);
}

function setCaretPosition(ControlOnWhichToBePasted, pos) {

    if (ControlOnWhichToBePasted.setSelectionRange) {
        ControlOnWhichToBePasted.focus();
        ControlOnWhichToBePasted.setSelectionRange(pos, pos);
    }
    else if (ControlOnWhichToBePasted.createTextRange) {
        var range = ControlOnWhichToBePasted.createTextRange();
        range.collapse(true);
        range.moveEnd('character', pos);
        range.moveStart('character', pos);
        range.select();
    }
}

</script>

3

Geçerli imleç konumuna metin eklemek iki adımdan oluşur:

  1. Geçerli imleç konumuna metin ekleme
  2. Geçerli imleç konumunu güncelleme

Demo: https://codepen.io/anon/pen/qZXmgN

Chrome 48, Firefox 45, IE 11 ve Edge 25'te test edildi

JS:

function addTextAtCaret(textAreaId, text) {
    var textArea = document.getElementById(textAreaId);
    var cursorPosition = textArea.selectionStart;
    addTextAtCursorPosition(textArea, cursorPosition, text);
    updateCursorPosition(cursorPosition, text, textArea);
}
function addTextAtCursorPosition(textArea, cursorPosition, text) {
    var front = (textArea.value).substring(0, cursorPosition);
    var back = (textArea.value).substring(cursorPosition, textArea.value.length);
    textArea.value = front + text + back;
}
function updateCursorPosition(cursorPosition, text, textArea) {
    cursorPosition = cursorPosition + text.length;
    textArea.selectionStart = cursorPosition;
    textArea.selectionEnd = cursorPosition;
    textArea.focus();    
}

HTML:

<div>
    <button type="button" onclick="addTextAtCaret('textArea','Apple')">Insert Apple!</button>
    <button type="button" onclick="addTextAtCaret('textArea','Mango')">Insert Mango!</button>
    <button type="button" onclick="addTextAtCaret('textArea','Orange')">Insert Orange!</button>
</div>
<textarea id="textArea" rows="20" cols="50"></textarea>

2

Sanırım son odaklı metin kutusunu izlemek için aşağıdaki JavaScript'i kullanabilirsiniz:

<script>
var holdFocus;

function updateFocus(x)
{
    holdFocus = x;
}

function appendTextToLastFocus(text)
{
    holdFocus.value += text;
}
</script>

Kullanımı:

<input type="textbox" onfocus="updateFocus(this)" />
<a href="#" onclick="appendTextToLastFocus('textToAppend')" />

Önceki bir çözüm (gclaghorn'den aksesuarlar) textarea kullanır ve imlecin konumunu da hesaplar, bu nedenle istediğiniz şey için daha iyi olabilir. Öte yandan, eğer aradığınız buysa, bu daha hafif olacaktır.


İyi bir fikir. Ben jquery kullandım, böylece belirli bir sınıf vardı her metin kutusu, her metin kutusunun html "onfocus = ..." koymak yerine kendilerine uygulanan bu olay vardı. But good approach :)
Upvote

1

Internet Explorer 9'da kabul edilen cevap benim için çalışmadı. Bunu kontrol ettim ve tarayıcı algılama düzgün çalışmıyor, Internet Explorer'dayken ff (firefox) algıladı .

Ben sadece bu değişikliği yaptım:

if ($.browser.msie) 

Onun yerine:

if (br == "ie") { 

Ortaya çıkan kod şudur:

function insertAtCaret(areaId,text) {
    var txtarea = document.getElementById(areaId);
    var scrollPos = txtarea.scrollTop;
    var strPos = 0;
    var br = ((txtarea.selectionStart || txtarea.selectionStart == '0') ? 
        "ff" : (document.selection ? "ie" : false ) );

    if ($.browser.msie) { 
        txtarea.focus();
        var range = document.selection.createRange();
        range.moveStart ('character', -txtarea.value.length);
        strPos = range.text.length;
    }
    else if (br == "ff") strPos = txtarea.selectionStart;

    var front = (txtarea.value).substring(0,strPos);  
    var back = (txtarea.value).substring(strPos,txtarea.value.length); 
    txtarea.value=front+text+back;
    strPos = strPos + text.length;
    if (br == "ie") { 
        txtarea.focus();
        var range = document.selection.createRange();
        range.moveStart ('character', -txtarea.value.length);
        range.moveStart ('character', strPos);
        range.moveEnd ('character', 0);
        range.select();
    }
    else if (br == "ff") {
        txtarea.selectionStart = strPos;
        txtarea.selectionEnd = strPos;
        txtarea.focus();
    }
    txtarea.scrollTop = scrollPos;
}



0

İçerik Düzenlenebilir, HTML veya başka bir DOM öğesi Seçimi

Eğer üzerine bir şapka yerleştirmeye çalışıyorsanız <div contenteditable="true">, özellikle düzenlenebilir kap içinde çocuklar varsa, bu çok daha zor hale gelir.

Rangy kütüphanesini kullanarak gerçekten büyük şanslar yaşadım :

Gibi bir ton harika özelliğe sahiptir:

  • Konumu veya Seçimi Kaydet
  • Ardından, Konumu veya Seçimi Geri Yükleme
  • Seçim HTML veya Düz Metin al
  • Diğerleri arasında

Online demo son çalışmıyordu kontrol ettim, ancak repo çalışma demoları var. Başlamak için Repo'yu Git veya NPM'den indirin ve ardından ./rangy/demos/index.html dosyasını açın.

Caret pos ve metin seçimi ile çalışmayı bir esinti yapar!


0

Bu sorunun cevabı çok uzun zaman önce gönderildi ve bir Google aramasıyla tökezledim. HTML5 içerir HTMLInputElement API içeren setRangeText () bir metnin bir dizi yerine yöntem, <input>ya da <textarea>yeni bir dizi ile elemanının:

element.setRangeText('abc');

Yukarıda içine yapılan seçimi yerini alacak elementolan abc. Ayrıca, giriş değerinin hangi kısmının değiştirileceğini de belirleyebilirsiniz:

element.setRangeText('abc', 3, 5);

Yukarıdakiler, giriş değerinin 4. ila 6. karakterlerini değiştirecektir abc. Ayrıca, metin değiştirildikten sonra 4. parametre olarak aşağıdaki dizelerden birini sağlayarak seçimin nasıl ayarlanması gerektiğini belirleyebilirsiniz:

  • 'preserve'seçimi korumaya çalışır. Bu varsayılan ayardır.
  • 'select' yeni eklenen metni seçer.
  • 'start' seçimi, eklenen metnin hemen öncesine taşır.
  • 'end' seçimi, eklenen metnin hemen sonrasına taşır.

Tarayıcı Uyumluluğu

SetRangeText için MDN sayfası tarayıcı uyumluluk verileri sağlamaz, ancak temelde tüm modern tarayıcılar, IE 9 ve üstü, Edge 12 ve üstü olan HTMLInputElement.setSelectionRange () ile aynı olacağını tahmin ediyorum .

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.