Существует ли одобренная Internet Explorer замена для selectionStart и selectionEnd? - PullRequest
19 голосов
/ 25 октября 2008

Узнать, что выбрано в реальных браузерах, так же просто, как:

var range = {
  start: textbox.selectionStart,
  end: textbox.selectionEnd
}

Но IE, как обычно, не понимает. Какой лучший кросс-браузерный способ сделать это?

Ответы [ 4 ]

22 голосов
/ 17 ноября 2010

Я опубликую эту функцию в другой раз, так как этот вопрос связан с другим.

Следующее выполнит работу во всех браузерах и решит все проблемы с новыми линиями без серьезного снижения производительности. Я пришел к этому после некоторого пробуждения , и теперь я совершенно уверен, что это лучшая такая функция из всех.

UPDATE

Эта функция предполагает, что текстовое поле / ввод имеет фокус, поэтому вам может потребоваться вызвать метод focus() текстового поля перед его вызовом.

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

var el = document.getElementById("your_input");
el.focus();
var sel = getInputSelection(el);
alert(sel.start + ", " + sel.end);
7 голосов
/ 25 октября 2008

Реализация Range в IE - ужасный ужас. Он действительно хочет, чтобы вы использовали исполняемый интерфейс execCommand вместо всего, что связано с индексацией в тексте.

Есть два подхода для получения индексов, и у них обоих есть проблемы. Первый использует range.text как в вашем примере кода. К сожалению, у range.text есть привычка убирать начальные и конечные символы новой строки, что означает, что если курсор / выделение находится в начале строки, отличной от первой, то передLength будет отключено (число новых строк * 2) символами, и вы Вы получите неправильно выбранный текст.

Второй подход заключается в использовании range.moveStart / End (в дублированном диапазоне), как указано в ответе на этот вопрос: Смещение символов в InternetRe TextRange (однако при использовании известный родитель textarea, вы можете игнорировать материал о поиске узлов). Это не та же проблема, но она сообщает обо всех индексах, как если бы переводы строк были простыми символами LF, хотя textarea.value и range.text будут возвращать их как последовательности CRLF! Таким образом, вы не можете использовать их напрямую для индексации в текстовой области, но вы можете либо исправить их с помощью подсчета новой строки, либо просто заменить строки всеми CRs из значения, прежде чем использовать его.

6 голосов
/ 25 октября 2008

Мое текущее решение многословно и основано на этой теме , но я открыт для лучших решений.

function getSelection(inputBox) {
    if ("selectionStart" in inputBox) {
        return {
            start: inputBox.selectionStart,
            end: inputBox.selectionEnd
        }
    }

    //and now, the blinkered IE way
    var bookmark = document.selection.createRange().getBookmark()
    var selection = inputBox.createTextRange()
    selection.moveToBookmark(bookmark)

    var before = inputBox.createTextRange()
    before.collapse(true)
    before.setEndPoint("EndToStart", selection)

    var beforeLength = before.text.length
    var selLength = selection.text.length

    return {
        start: beforeLength,
        end: beforeLength + selLength
    }
}
0 голосов
/ 25 ноября 2014

С BootstrapFormHelpers

  function getCursorPosition($element) {
    var position = 0,
        selection;

    if (document.selection) {
      // IE Support
      $element.focus();
      selection = document.selection.createRange();
      selection.moveStart ('character', -$element.value.length);
      position = selection.text.length;
    } else if ($element.selectionStart || $element.selectionStart === 0) {
      position = $element.selectionStart;
    }

    return position;
  }

  function setCursorPosition($element, position) {
    var selection;

    if (document.selection) {
      // IE Support
      $element.focus ();
      selection = document.selection.createRange();
      selection.moveStart ('character', -$element.value.length);
      selection.moveStart ('character', position);
      selection.moveEnd ('character', 0);
      selection.select ();
    } else if ($element.selectionStart || $element.selectionStart === 0) {
      $element.selectionStart = position;
      $element.selectionEnd = position;
      $element.focus ();
    }
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...