Я не удивлен, но я обнаружил, что IE8 ведет себя совершенно иначе, чем Chrome и Firefox, в отношении извлечения позиции каретки из текста <input>
или <textarea>
. В то время как Chrome и Firefox сообщают позицию каретки аналогично индексу в строковом значении, IE8 этого не делает.
Прежде всего, вот функции, которые я использую для извлечения позиций каретки соответственно в Chrome / Firefox и IE:
function getCaretPosGecko(txtbox) {
return txtbox.selectionStart;
}
function getCaretPosIE(txtbox) {
var range, rangeCopy;
txtbox.focus();
range = document.selection.createRange();
if (range !== null) {
rangeCopy = range.duplicate();
rangeCopy.moveToElementText(txtbox);
rangeCopy.setEndPoint('EndToStart', range);
return rangeCopy.text.length - range.text.length;
} else {
return -1;
}
}
Насколько я могу судить, функции, которые я реализовал, довольно стандартные. Теперь, скажем, у меня есть <textarea>
, и я набираю «a» в первой строке, «b» во второй строке и ничего больше. Приведенный выше код сообщает о следующих позициях каретки для заданных критериев в Chrome и Firefox:
--------------------------------------------------------------------
| I put the caret... | Code reports caret at position... |
--------------------------------------------------------------------
| 1st line, after the "a" | 1 (As expected) |
| 2nd line, before the "b" | 2 (As expected) |
| 2nd line, after the "b" | 3 (As expected) |
--------------------------------------------------------------------
В IE8 результаты, к сожалению, очень разные:
--------------------------------------------------------------------
| I put the caret... | Code reports caret at position... |
--------------------------------------------------------------------
| 1st line, after the "a" | 1 (As expected) |
| 2nd line, before the "b" | 1 (Maybe it doesn't count new lines?) |
| 2nd line, after the "b" | 4 (Now, it seems to include \r\n?) |
--------------------------------------------------------------------
Я предполагаю, что IE включает "\ r \ n" в расчет для третьего случая, но почему он не включает его для второго случая?
Что более важно, что я могу сделать, чтобы обойти это несоответствие? Мне нужно знать, где находится курсор в строковом значении текстового поля, чтобы сделать некоторые строковые манипуляции. Моей первой мыслью было смещение позиции каретки в IE на число «\ r \ n» перед кареткой, но это не сработает, если каретка находится в начале или конце строки.
Вот рабочий пример: http://jsfiddle.net/FishBasketGordo/ExZM9/
РЕДАКТИРОВАТЬ: @ Ответ Тим Тима Дауна был чуть ли не точным. Мне нужно было сделать несколько модификаций. Функция ниже возвращает те же результаты, что и ее аналог Gecko:
function getCaretPosIE(txtbox) {
var caret, normalizedValue, range, textInputRange, len, endRange;
txtbox.focus();
range = document.selection.createRange();
if (range && range.parentElement() == txtbox) {
len = txtbox.value.length;
normalizedValue = txtbox.value.replace(/\r\n/g, '');
textInputRange = txtbox.createTextRange();
textInputRange.moveToBookmark(range.getBookmark());
endRange = txtbox.createTextRange();
endRange.collapse(false);
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
caret = txtbox.value.replace(/\r\n/g, '\n').length;
} else {
caret = -textInputRange.moveStart("character", -len);
caret += normalizedValue.slice(0, start).split("\n").length - 1;
}
}
}
Вот исправленный рабочий пример: http://jsfiddle.net/FishBasketGordo/uXWXF/