Почему позиция каретки IE в текстовом вводе не равна строковому индексу?Какой обходной путь? - PullRequest
1 голос
/ 04 августа 2011

Я не удивлен, но я обнаружил, что 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/

1 Ответ

2 голосов
/ 04 августа 2011

Получение позиции каретки относительно свойства value текстовой области не является простым в IE из-за проблем с разрывом строки, с которыми вы столкнулись. Я провел некоторое время назад, исследуя это, и придумал, что я считаю лучшим подходом там. Я опубликовал это несколько раз на Переполнении стека. Вот один пример:

IE. document.selection.createRange не содержит начальных или конечных пустых строк

...