La mayoría de las respuestas que encuentra en el posicionamiento de cursor contento son bastante simplistas, ya que solo atienden entradas con texto simple. Una vez que usa elementos html dentro del contenedor, el texto ingresado se divide en nodos y se distribuye generosamente en una estructura de árbol.
Para establecer la posición del cursor, tengo esta función que recorre todos los nodos de texto secundarios dentro del nodo suministrado y establece un rango desde el inicio del nodo inicial hasta el carácter chars.count :
function createRange(node, chars, range) {
if (!range) {
range = document.createRange()
range.selectNode(node);
range.setStart(node, 0);
}
if (chars.count === 0) {
range.setEnd(node, chars.count);
} else if (node && chars.count >0) {
if (node.nodeType === Node.TEXT_NODE) {
if (node.textContent.length < chars.count) {
chars.count -= node.textContent.length;
} else {
range.setEnd(node, chars.count);
chars.count = 0;
}
} else {
for (var lp = 0; lp < node.childNodes.length; lp++) {
range = createRange(node.childNodes[lp], chars, range);
if (chars.count === 0) {
break;
}
}
}
}
return range;
};
Luego llamo a la rutina con esta función:
function setCurrentCursorPosition(chars) {
if (chars >= 0) {
var selection = window.getSelection();
range = createRange(document.getElementById("test").parentNode, { count: chars });
if (range) {
range.collapse(false);
selection.removeAllRanges();
selection.addRange(range);
}
}
};
Range.collapse (false) establece el cursor al final del rango. Lo probé con las últimas versiones de Chrome, IE, Mozilla y Opera y todas funcionan bien.
PD. Si alguien está interesado, obtengo la posición actual del cursor usando este código:
function isChildOf(node, parentId) {
while (node !== null) {
if (node.id === parentId) {
return true;
}
node = node.parentNode;
}
return false;
};
function getCurrentCursorPosition(parentId) {
var selection = window.getSelection(),
charCount = -1,
node;
if (selection.focusNode) {
if (isChildOf(selection.focusNode, parentId)) {
node = selection.focusNode;
charCount = selection.focusOffset;
while (node) {
if (node.id === parentId) {
break;
}
if (node.previousSibling) {
node = node.previousSibling;
charCount += node.textContent.length;
} else {
node = node.parentNode;
if (node === null) {
break
}
}
}
}
}
return charCount;
};
El código hace lo contrario de la función set: obtiene la ventana actual.getSelection (). FocusNode y focusOffset y cuenta hacia atrás todos los caracteres de texto encontrados hasta que llega a un nodo padre con la identificación de containerId. La función isChildOf solo comprueba antes de ejecutar que el nodo suministrado es realmente hijo del parentId proporcionado .
El código debería funcionar directamente sin cambios, pero lo acabo de tomar de un complemento jQuery que he desarrollado, así que he pirateado algunos de estos, ¡ avíseme si algo no funciona!