javascript - Obtenga el desplazamiento inicial y final de una gama en relación con su contenedor principal
textrange (2)
Sé que tiene un año, pero esta publicación es un resultado de búsqueda superior para muchas preguntas sobre cómo encontrar la posición de Caret y me pareció útil.
Intenté utilizar la excelente secuencia de comandos de Tim anterior para encontrar la nueva posición del cursor después de arrastrar y soltar un elemento de una posición a otra en un div editable de contenido. Funcionó perfectamente en FF e IE, pero en Chrome, la acción de arrastre resaltó todo el contenido entre el principio y el final del arrastre, lo que resultó en que el caretOffset
devuelto sea demasiado grande o pequeño (por la longitud del área seleccionada).
Agregué algunas líneas a la primera declaración if para verificar si el texto ha sido seleccionado y ajustar el resultado en consecuencia. La nueva declaración está debajo. Perdónenme si no es apropiado agregar esto aquí, ya que no es lo que el OP intentaba hacer, pero como dije, varias búsquedas de información relacionada con la posición de Caret me llevaron a esta publicación, por lo que (con suerte) es probable que ayude a otra persona. .
Primera declaración if de Tim con líneas adicionales (*):
if (typeof window.getSelection != "undefined") {
var range = window.getSelection().getRangeAt(0);
var selected = range.toString().length; // *
var preCaretRange = range.cloneRange();
preCaretRange.selectNodeContents(element);
preCaretRange.setEnd(range.endContainer, range.endOffset);
if(selected){ // *
caretOffset = preCaretRange.toString().length - selected; // *
} else { // *
caretOffset = preCaretRange.toString().length;
} // *
}
Supongamos que tengo este elemento HTML:
<div id="parent">
Hello everyone! <a>This is my home page</a>
<p>Bye!</p>
</div>
Y el usuario selecciona "casa" con su mouse.
Quiero poder determinar cuántos caracteres #parent
inicia su selección (y cuántos caracteres finaliza #parent
finaliza su selección). Esto debería funcionar incluso si selecciona una etiqueta HTML. (Y necesito que funcione en todos los navegadores)
range.startOffset
parece prometedor, pero es un desplazamiento relativo solo al contenedor inmediato del rango, y es un desplazamiento de caracteres solo si el contenedor es un nodo de texto.
ACTUALIZAR
Como se señaló en los comentarios, mi respuesta original (a continuación) solo devuelve el final de la selección o la posición de intercalación. Es bastante fácil adaptar el código para devolver un inicio y un desplazamiento final; he aquí un ejemplo que lo hace:
function getSelectionCharacterOffsetWithin(element) {
var start = 0;
var end = 0;
var doc = element.ownerDocument || element.document;
var win = doc.defaultView || doc.parentWindow;
var sel;
if (typeof win.getSelection != "undefined") {
sel = win.getSelection();
if (sel.rangeCount > 0) {
var range = win.getSelection().getRangeAt(0);
var preCaretRange = range.cloneRange();
preCaretRange.selectNodeContents(element);
preCaretRange.setEnd(range.startContainer, range.startOffset);
start = preCaretRange.toString().length;
preCaretRange.setEnd(range.endContainer, range.endOffset);
end = preCaretRange.toString().length;
}
} else if ( (sel = doc.selection) && sel.type != "Control") {
var textRange = sel.createRange();
var preCaretTextRange = doc.body.createTextRange();
preCaretTextRange.moveToElementText(element);
preCaretTextRange.setEndPoint("EndToStart", textRange);
start = preCaretTextRange.text.length;
preCaretTextRange.setEndPoint("EndToEnd", textRange);
end = preCaretTextRange.text.length;
}
return { start: start, end: end };
}
function reportSelection() {
var selOffsets = getSelectionCharacterOffsetWithin( document.getElementById("editor") );
document.getElementById("selectionLog").innerHTML = "Selection offsets: " + selOffsets.start + ", " + selOffsets.end;
}
window.onload = function() {
document.addEventListener("selectionchange", reportSelection, false);
document.addEventListener("mouseup", reportSelection, false);
document.addEventListener("mousedown", reportSelection, false);
document.addEventListener("keyup", reportSelection, false);
};
#editor {
padding: 5px;
border: solid green 1px;
}
Select something in the content below:
<div id="editor" contenteditable="true">A <i>wombat</i> is a marsupial native to <b>Australia</b></div>
<div id="selectionLog"></div>
Aquí hay una función que obtendrá el desplazamiento de caracteres del cursor dentro del elemento especificado; sin embargo, esta es una implementación ingenua que casi seguramente tendrá inconsistencias con saltos de línea, y no intenta tratar con texto oculto a través de CSS (sospecho que IE ignorará correctamente dicho texto mientras que otros navegadores no lo harán). Manejar todo esto correctamente sería complicado. Lo he intentado para mi biblioteca Rangy .
Ejemplo en vivo: http://jsfiddle.net/TjXEG/900/
function getCaretCharacterOffsetWithin(element) {
var caretOffset = 0;
var doc = element.ownerDocument || element.document;
var win = doc.defaultView || doc.parentWindow;
var sel;
if (typeof win.getSelection != "undefined") {
sel = win.getSelection();
if (sel.rangeCount > 0) {
var range = win.getSelection().getRangeAt(0);
var preCaretRange = range.cloneRange();
preCaretRange.selectNodeContents(element);
preCaretRange.setEnd(range.endContainer, range.endOffset);
caretOffset = preCaretRange.toString().length;
}
} else if ( (sel = doc.selection) && sel.type != "Control") {
var textRange = sel.createRange();
var preCaretTextRange = doc.body.createTextRange();
preCaretTextRange.moveToElementText(element);
preCaretTextRange.setEndPoint("EndToEnd", textRange);
caretOffset = preCaretTextRange.text.length;
}
return caretOffset;
}