2012-04-02 16 views
7

Estoy haciendo uso de un div satisfactorio en combinación con la biblioteca Javascript rangy para insertar HTML en la posición del cursor.contenteditable div: IE8 no está contento con el retroceso eliminación del elemento HTML

Al final del día el contenido del div se ve comúnmente como:

<div contenteditable="true"> 
    "Hello " 
    <button contenteditable="false" data-id="147">@John Smith</button> 
    " " 
</div> 

Los usuarios obtienen sugirieron al pulsar '@' y obtener posteriormente inserta como un botón cuando está seleccionado (al estilo de Google Plus). También inserto un &nbsp; después de este botón.

El botón se elimina en Chrome/Safari/Firefox cuando se presiona el espacio de retroceso (después de eliminar primero el &nbsp;), pero no en IE8. En IE8, el cursor simplemente salta sobre el botón sin quitarlo. Lo que es aún más extraño en IE8 es que si deja el &nbsp; al lado del botón y coloca el cursor justo al lado del botón, se elimina el botón en el retroceso. Por lo tanto, es feliz cuando hay un &nbsp; a la derecha del cursor.

¿Alguien sabe lo que necesito para que IE8 funcione en i.t.o. ¿Quitar el botón al retroceder sin la necesidad de un &nbsp; a la derecha del cursor? (alguna información sobre este extraño comportamiento también podría ayudar)

P.S. No he probado otras versiones de IE

+0

¿Por qué tiene la contenteditable = false en el botón? – MorganTiley

+1

Para que lo elimine del DOM (de una vez) cuando presiona la tecla de retroceso o cuando presiona eliminar (actualmente funciona en Chrome/Safari/Firefox). Si contenteditable = true, el texto del botón se puede editar, que no es mi caso de uso. –

+0

genial No lo sabía. (No he trabajado con entradas en contEd antes). ¿Qué pasa con el manejo del chasquido de retroceso y la comprobación previa de la relación del primer nodo en el rango de selección? – MorganTiley

Respuesta

6

Mi sugerencia sería verificar primero que el cursor esté posicionado después del nodo no editable, y si es así, crear un rango que comience inmediatamente después del elemento no editable y termine en la posición de intercalación. Verifique si el texto en este rango está vacío. Si lo es, eso significa que el símbolo de intercalación se coloca directamente después del elemento no editable, por lo que en ese caso, elimine el elemento. Finalmente, coloque el cursor donde había estado el no editable.

Demostración en directo: http://jsfiddle.net/timdown/vu3ub/

Código:

document.onkeypress = function(e) { 
    e = e || window.event; 
    var keyCode = e.which || e.keyCode; 
    if (keyCode !== 8) { 
     return; 
    } 

    var sel = rangy.getSelection(); 
    if (sel.rangeCount === 0) { 
     return; 
    } 

    var selRange = sel.getRangeAt(0); 
    if (!selRange.collapsed) { 
     return; 
    } 

    var nonEditable = document.getElementById("nonEditable"); 
    if (!nonEditable) { 
     return; 
    } 

    // Check the caret is located after the non-editable element 
    var range = rangy.createRange(); 
    range.collapseAfter(nonEditable); 

    if (selRange.compareBoundaryPoints(range.START_TO_END, range) == -1) { 
     return; 
    } 

    // Check whether there is any text between the caret and the 
    // non-editable element. If not, delete the element and move 
    // the caret to where it had been 
    range.setEnd(selRange.startContainer, selRange.startOffset); 
    if (range.toString() === "") { 
     selRange.collapseBefore(nonEditable); 
     nonEditable.parentNode.removeChild(nonEditable); 
     sel.setSingleRange(selRange); 

     // Prevent the default browser behaviour 
     return false; 
    } 
}; 
+0

Brillante! Enormes gracias por una respuesta tan completa. Lo modifiqué ligeramente: en lugar de usar document.getElementById ("no editable") utilicé selRange.startContainer.previousSibling (ya que no sé qué nodo necesito eliminar en el retroceso). –

+0

Gracias a todos por la gran respuesta, Tim. Esto ha sido extremadamente útil para mí hoy. –

1

hice un jsFiddle con una muestra rápida de cómo mirar a la gama de la selección y el uso de la propiedad de la previousSibling startContainer para encontrar el botón: jsfiddle

Coloque el cursor en aaa y se mostrará que el botón es anterior hermano. ponerlo en ccc y bbb se mostrará.

Así que con esto podría manejar el evento de selección del div, comprobar si la tecla es retroceso + previousSibling es su botón, y eliminarlo con jQuery.

previousSibling es nulo si es un texto sin embargo, solo para tu información.

+0

Muy bueno.Creo que puedo usar el hermano anterior en combinación con el desplazamiento del rango como solución. Voy a informar sobre cómo va. –

Cuestiones relacionadas