Узнать, что выбрано в реальных браузерах, так же просто, как:
var range = {
start: textbox.selectionStart,
end: textbox.selectionEnd
}
Но IE, как обычно, не понимает. Какой лучший способ перекрестного браузера?
Узнать, что выбрано в реальных браузерах, так же просто, как:
var range = {
start: textbox.selectionStart,
end: textbox.selectionEnd
}
Но IE, как обычно, не понимает. Какой лучший способ перекрестного браузера?
Я отправлю эту функцию в другое время, увидев, что этот вопрос связан с другим.
Следующее выполнит работу во всех браузерах и займется всеми новыми проблемными линиями без серьезного ущерба производительности. Я пришел к этому после некоторых новинок и вскрытия, и теперь я уверен, что это лучшая такая функция.
UPDATE
Эта функция предполагает, что в textarea/input есть фокус, поэтому вам может потребоваться вызвать метод textarea 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);
Реализация IE Range - это скользкий ужас. Он действительно хочет, чтобы вы использовали отлаженный интерфейс execCommand вместо всего, что связано с индексированием в текст.
Есть два подхода, которые я знаю для получения индексов, и у них обоих есть проблемы. Первый использует range.text как в вашем примере кода. К сожалению, у range.text есть привычка снимать ведущие и завершающие символы новой строки, что означает, что если каретка/выбор находится в начале строки, отличной от первой, beforeLength будет отключен (число символов новой строки * 2), а вы Вы получите неправильный выделенный текст.
Второй подход заключается в использовании range.moveStart/End (в дублированном диапазоне), как указано в ответе на этот вопрос: Смещение символов в Internet Explorer TextRange (однако, поскольку вы используете известного родителя textarea, вы можете игнорировать материал о node -finding). У этого нет той же проблемы, но он сообщает все индексы, как если бы символы новой строки были простыми символами LF, даже если textarea.value и range.text вернут их как последовательности CRLF! Таким образом, вы не можете использовать их напрямую для индексации в текстовое поле, но вы можете либо исправить их с помощью подсчета новой строки, либо просто заменить строку - все CR из значения, прежде чем использовать его.
Мое текущее решение многословно и основано на этой теме, но я открыт для лучших решений.
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
}
}
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 ();
}
}