javascript - instalar - ¿Existe un sustituto aprobado por Internet Explorer para selectionStart y selectionEnd?
habilitar javascript en internet explorer 11 (4)
Mi solución actual es prolija y está basada en este hilo , pero estoy abierto a mejores soluciones.
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
}
}
Averiguar qué se selecciona en los navegadores reales es tan simple como:
var range = {
start: textbox.selectionStart,
end: textbox.selectionEnd
}
Pero IE, como de costumbre, no entiende. ¿Cuál es la mejor forma de hacer esto entre navegadores?
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 ();
}
}
La implementación del rango de IE es un horror slithy. Realmente quiere que uses la execrable interfaz execCommand en lugar de usar indexación en el texto.
Hay dos enfoques que conozco para obtener los índices y ambos tienen problemas. El primero usa range.text como en tu código de ejemplo. Desafortunadamente, range.text tiene el hábito de eliminar las líneas nuevas y finales, lo que significa que si la línea / selección está al principio de una línea que no sea la primera, beforeLength estará desactivado por (número de líneas nuevas * 2) caracteres y usted Obtendré el texto seleccionado incorrecto.
El segundo enfoque es usar range.moveStart / End (en un rango duplicado), como se indica en la respuesta a esta pregunta: Compensación de caracteres en un TextRange de Internet Explorer (sin embargo, como está utilizando un elemento principal conocido como textarea, puede ignorar las descubrimiento de nodos). Esto no tiene el mismo problema, pero informa todos los índices como si las líneas nuevas fueran simples caracteres LF, ¡aunque textarea.value y range.text los devolverán como secuencias CRLF! Por lo tanto, no puede usarlos directamente para indexar en el área de texto, pero puede repararlos con un montón de recuento de línea nueva o simplemente reemplazar todos los CR del valor antes de usarlo.
Publicaré esta función para otro momento, ya que esta pregunta se vinculó desde otra.
Lo siguiente hará el trabajo en todos los navegadores y se ocupa de todos los nuevos problemas de línea sin comprometer seriamente el rendimiento. He llegado a esto después de algunos toing y froing y ahora estoy bastante convencido de que es la mejor función de este tipo.
ACTUALIZAR
Esta función asume que el área de texto / entrada tiene foco, por lo que puede necesitar llamar al método focus()
antes de llamarlo.
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);