Karakter dizisinde, metin olarak düzeltme sütunu (piksel değil) konumu nasıl elde edilir?


174

<textarea>JavaScript kullanarak düzeltme konumunu nasıl elde edersiniz ?

Örneğin: This is| a text

Bu geri dönmeli 7.

İmleci / seçimi çevreleyen dizeleri döndürmeyi nasıl elde edersiniz?

Ör: 'This is', '', ' a text'.

“İs” sözcüğü vurgulanırsa geri döner 'This ', 'is', ' a text'.


Bu soruya bakın: stackoverflow.com/questions/164147/… ve eğer yeni satırlarınız olacaksa, bununla ilgili not: stackoverflow.com/questions/235411/…
bobince

1
JQuery kullanıyorsanız jquery caret eklentisini $ ('textarea') kullanabilirsiniz. GetSelection (). Start plugins.jquery.com/plugin-tags/caret @ ++
redochka

Blog.vishalon.net/index.php/… adresinde iyi bir çözüm buldum . Firefox ve chrome'da test ettim ve her ikisinde de çalıştı. Yazar IE + Opera'da da çalıştığını söylüyor.
pycoder112358

Basit kullanımı textarea.selectionStart, textarea. selectionEnd, textarea.setSelectionRange developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement
EAndreyF

Yanıtlar:


173

Firefox, Safari (ve diğer Gecko tabanlı tarayıcılar) ile textarea.selectionStart'ı kolayca kullanabilirsiniz, ancak işe yaramayan IE için, böyle bir şey yapmanız gerekecek:

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

( kodu burada girin )

Ayrıca jQuery FieldSelection Eklentisini kontrol etmenizi öneririm , bunu yapmanızı ve çok daha fazlasını yapmanızı sağlar ...

Düzenleme: Aslında yukarıdaki kodu yeniden uygulandı:

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

Buradan bir örnek kontrol edin .


1
Bu, şapka boş bir satıra yerleştirildiğinde şapka konumlarını ayırt etmez. Bkz. Stackoverflow.com/questions/3053542/…
Tim Down

4
Bu cevap boş satırlarla ilgili değildir.
Tim Down

6
CONTENTEDITABLE div için bunu nasıl kullanabilirim?
Muhammet Göktürk Ayan

1
Bu cevabı biraz yeniden yazmak isteyebilirsiniz Safari (and other Gecko based browsers), Safari'nin Gecko kullandığını ima etmek gibi görünüyor. Gecko Mozilla'nın motorudur; Safari, WebKit kullanıyor.
Yararsız Kod

1
0 pozisyonundaki if (el.selectionStart) { return el.selectionStart; }
düzeltme

57

Güncellendi 5 Eylül 2010

Herkesin bu sorun için burada yönlendirilmiş gibi göründüğüne göre, bu cevapla aynı kodu içeren ancak ilgilenenler için tam arka plana sahip benzer bir soruya cevabımı ekliyorum:

IE'nin document.selection.createRange, önde gelen veya sondaki boş satırları içermez

Sondaki satır sonlarını hesaba katmak IE'de zor ve bu soruya verilen diğer yanıtlar da dahil olmak üzere bunu doğru yapan herhangi bir çözüm görmedim. Bununla birlikte, bir <textarea>veya metin içinde seçimin başlangıcını ve sonunu (bir düzeltme durumunda aynıdır) döndüren aşağıdaki işlevi kullanarak mümkündür <input>.

IE'de bu işlevin düzgün çalışması için metin alanının odağa sahip olması gerektiğini unutmayın. Şüpheniz varsa, önce textarea focus()yöntemini çağırın .

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

Affedersiniz ama ' range && range.parentElement () ' ne anlama geliyor?
sergzach

IE'de düzeltme konumu almak istiyorsak bir sorun var (seçim boşsa). Bu durumda bitiş olarak 0 ve bitiş olarak dize uzunluğu döndürür ( range && range.parentElement () == el yerine true kullanırsak ).
sergzach

@sergzach: Seçimin range && range.parentElement() == elmetin alanı içinde olup olmadığını test etmek için orada. Metin alanı odağa sahip olduğu sürece düzeltme konumu elde etme işlevinde bir sorun yoktur . Emin değilseniz, aramadan önce textarea focus()yöntemini çağırın getInputSelection(). Cevaba bir not ekleyeceğim.
Tim Down

1
@Tim: Seçimi göstermek için bir div öğesine tıkladığınızda "start" ve "end" her zaman aynıdır.
Misha Moroshko

3
@Misha: Bu işlevin hatası değildir: işlev yürütüldüğünde aslında seçilen budur. Uyarı kutusunu çıkardıktan sonra görsel olarak görebilirsiniz. Ben senin son soruya cevabım belirttiğimiz gibi, iki olası geçici çözümler kullanan mousedownolayı veya ekleme unselectable="on"için <div>eleman.
Tim Down

3

IE'de satır başlarını hesaba katmak için yukarıdaki işlevi değiştirdim. Denenmemiş ama uygulanabilir olması gerekir bu yüzden benim kodunda benzer bir şey yaptım.

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

2

IE desteklemek yoksa, kullanabileceğiniz selectionStartve selectionEndnitelikleritextarea .

Düzeltme konumu almak için şunu kullanın selectionStart:

function getCaretPosition(textarea) {
  return textarea.selectionStart
}

Seçimi çevreleyen dizeleri almak için aşağıdaki kodu kullanın:

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)]
}

JSFiddle'da demo .

Ayrıca bkz . HTMLTextAreaElement belgeleri .

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.