2011-01-29 10 views
26

Estoy insertando un elemento en un contentEditable div pero el navegador establece la posición del cursor antes del elemento insertado. ¿Es posible establecer el cursor justo después del elemento insertado para que el usuario siga escribiendo sin tener que reajustar la posición del cursor?Establecer la posición de intercalación justo después del elemento insertado en un contentEditable div

+0

relacionadas: http://stackoverflow.com/questions/2920150/insert-text-at-cursor-in-a-content-editable-div – payne

+0

eso no responde a mi pregunta. Puedo insertar el elemento en la posición de intercalación, pero debo colocar el símbolo de intercalación justo después del elemento insertado. – Elie

+0

Ha intentado simular un evento de teclado después de insertar la cadena, como la tecla "final" (código de clave # 35) en el teclado. – jnkrois

Respuesta

28

La siguiente función lo hará. Los objetos DOM Range 2 Range lo hacen fácil en la mayoría de los navegadores. En IE, debe insertar un elemento marcador después del nodo que está insertando, mover la selección a él y luego eliminarlo.

ejemplo vivo: http://jsfiddle.net/timdown/4N4ZD/

Código:

function insertNodeAtCaret(node) { 
    if (typeof window.getSelection != "undefined") { 
     var sel = window.getSelection(); 
     if (sel.rangeCount) { 
      var range = sel.getRangeAt(0); 
      range.collapse(false); 
      range.insertNode(node); 
      range = range.cloneRange(); 
      range.selectNodeContents(node); 
      range.collapse(false); 
      sel.removeAllRanges(); 
      sel.addRange(range); 
     } 
    } else if (typeof document.selection != "undefined" && document.selection.type != "Control") { 
     var html = (node.nodeType == 1) ? node.outerHTML : node.data; 
     var id = "marker_" + ("" + Math.random()).slice(2); 
     html += '<span id="' + id + '"></span>'; 
     var textRange = document.selection.createRange(); 
     textRange.collapse(false); 
     textRange.pasteHTML(html); 
     var markerSpan = document.getElementById(id); 
     textRange.moveToElementText(markerSpan); 
     textRange.select(); 
     markerSpan.parentNode.removeChild(markerSpan); 
    } 
} 

Como alternativa, puede usar mi Rangy library. El código equivalente no sería

function insertNodeAtCaret(node) { 
    var sel = rangy.getSelection(); 
    if (sel.rangeCount) { 
     var range = sel.getRangeAt(0); 
     range.collapse(false); 
     range.insertNode(node); 
     range.collapseAfter(node); 
     sel.setSingleRange(range); 
    } 
} 
+4

Heh. Esto es divertido: "Los objetos DOM Range 2 Range lo hacen fácil en la mayoría de los navegadores". He estado probando varias permutaciones de esto durante tres días con poco éxito. (Lo sé, no es un comentario útil, pero solo tenía que decirlo) – eon

+0

@eon: :) Tal vez debería haber calificado eso: "Comparado con el desagradable truco necesario en IE <9, los objetos del rango DOM Nivel 2 lo hacen fácil en la mayoría de los navegadores ". –

+1

Solo parecía funcionar para el nodo de texto. ¿Intentó dándole un elemento de tramo y el cursor termina antes del tramo? – user984003

0

Si está insertando un div vacío, po palmo, creo que es necesario que haya "algo" dentro del elemento recién creado para la gama para agarrar - y en Para poner el cursor dentro de allí.

Aquí está mi truco que parece funcionar bien en Chrome. La idea es simplemente poner una cadena temporal dentro del elemento, luego eliminarla una vez que el cursor esté allí.

// Get the selection and range 
var idoc = document; // (In my case it's an iframe document) 
var sel = idoc.getSelection(); 
var range = sel.getRangeAt(0); 

// Create a node to insert 
var p = idoc.createElement("p"); // Could be a div, span or whatever 

// Add "something" to the node. 
var temp = idoc.createTextNode("anything"); 
p.appendChild(temp); 
// -- or -- 
//p.innerHTML = "anything"; 

// Do the magic (what rangy showed above) 
range.collapse(false); 
range.insertNode(p); 
range = range.cloneRange(); 
range.selectNodeContents(p); 
range.collapse(false); 
sel.removeAllRanges(); 
sel.addRange(range); 

// Clear the non 
p.removeChild(p.firstChild); 
// -- or -- 
//p.innerHTML = ""; 
Cuestiones relacionadas