change javascript jquery html5 contenteditable

javascript - contenteditable jquery change



eventos de cambio contenteditable (18)

Quiero ejecutar una función cuando un usuario edita el contenido de un div con un atributo contenteditable . ¿Cuál es el equivalente de un evento onchange ?

Estoy usando jQuery, por lo que se prefiere cualquier solución que use jQuery. ¡Gracias!


Aquí está la solución que terminé usando y funciona fabulosamente. Utilizo $ (this) .text () en su lugar porque solo estoy usando un div de una línea que es editable por contenido. Pero también puede usar .html () de esta manera, no tiene que preocuparse por el alcance de una variable global / no global y el anterior se adjunta al div editor.

$(''body'').delegate(''#editor'', ''focus'', function(){ $(this).data(''before'', $(this).html()); }); $(''#client_tasks'').delegate(''.task_text'', ''blur'', function(){ if($(this).data(''before'') != $(this).html()){ /* do your stuff here - like ajax save */ alert(''I promise, I have changed!''); } });


Aquí hay una versión más eficiente que se usa on todos los contenidos editables. Se basa en las mejores respuestas aquí.

$(''body'').on(''focus'', ''[contenteditable]'', function() { const $this = $(this); $this.data(''before'', $this.html()); }).on(''blur keyup paste input'', ''[contenteditable]'', function() { const $this = $(this); if ($this.data(''before'') !== $this.html()) { $this.data(''before'', $this.html()); $this.trigger(''change''); } });

El proyecto está aquí: https://github.com/balupton/html5edit


Basado en la respuesta de @balupton:

$(document).on(''focus'', ''[contenteditable]'', e => { const self = $(e.target) self.data(''before'', self.html()) }) $(document).on(''blur'', ''[contenteditable]'', e => { const self = $(e.target) if (self.data(''before'') !== self.html()) { self.trigger(''change'') } })

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


Considere el uso de MutationObserver . Estos observadores están diseñados para reaccionar a los cambios en el DOM y como un reemplazo eficaz de los eventos de mutación .

Pros:

  • Se activa cuando se produce cualquier cambio, lo que es difícil de lograr al escuchar los eventos clave como lo sugieren otras respuestas. Por ejemplo, todos estos funcionan bien: arrastrar y soltar, poner cursiva, copiar / cortar / pegar en el menú contextual.
  • Diseñado pensando en el rendimiento.
  • Código simple y directo. Es mucho más fácil de entender y depurar el código que escucha un evento en lugar de un código que escucha 10 eventos.
  • Google tiene una excelente biblioteca de resumen de mutaciones que facilita el uso de MutationObservers.

Contras:

  • Requiere una versión muy reciente de Firefox (14.0+), Chrome (18+) o IE (11+).
  • Nueva API para entender
  • No hay mucha información disponible todavía sobre las mejores prácticas o estudios de caso

Aprende más:

  • Escribí un pequeño here para comparar el uso de MutationObserers con el manejo de una variedad de eventos. Usé el código de balupton ya que su answer tiene el mayor número de votos.
  • Mozilla tiene una excelente página en la API
  • Echa un vistazo a la biblioteca de resumen de mutaciones.

Construí un plugin de jQuery para hacer esto.

(function ($) { $.fn.wysiwygEvt = function () { return this.each(function () { var $this = $(this); var htmlold = $this.html(); $this.bind(''blur keyup paste copy cut mouseup'', function () { var htmlnew = $this.html(); if (htmlold !== htmlnew) { $this.trigger(''change'') } }) }) } })(jQuery);

Simplemente puede llamar a $(''.wysiwyg'').wysiwygEvt();

También puede eliminar / agregar eventos si lo desea


Echa un vistazo a esta idea. http://pastie.org/1096892

Creo que está cerca. HTML 5 realmente necesita agregar el evento de cambio a la especificación. El único problema es que la función de devolución de llamada evalúa if (antes == $ (this) .html ()) antes de que el contenido se actualice en $ (this) .html (). setTimeout no funciona, y es triste. Déjame saber lo que piensas.



Este hilo fue muy útil mientras estaba investigando el tema.

He modificado parte del código disponible aquí en un complemento de jQuery, por lo que se encuentra en una forma reutilizable, principalmente para satisfacer mis necesidades, pero otros pueden apreciar una interfaz más sencilla para comenzar a utilizar etiquetas personalizables.

https://gist.github.com/3410122

Actualizar:

Debido a su creciente popularidad, el complemento ha sido adoptado por Makesites.org

El desarrollo continuará desde aquí:

https://github.com/makesites/jquery-contenteditable


Esto es lo que funcionó para mí:

var clicked = {} $("[contenteditable=''true'']").each(function(){ var id = $(this).attr("id"); $(this).bind(''focus'', function() { // store the original value of element first time it gets focus if(!(id in clicked)){ clicked[id] = $(this).html() } }); }); // then once the user clicks on save $("#save").click(function(){ for(var id in clicked){ var original = clicked[id]; var current = $("#"+id).html(); // check if value changed if(original != current) save(id,current); } });


He modificado la respuesta de la ley como tal y esto funciona para mí. Uso el evento keyup en lugar de la pulsación de tecla que funciona muy bien.

$(''#editor'').on(''focus'', function() { before = $(this).html(); }).on(''blur keyup paste'', function() { if (before != $(this).html()) { $(this).trigger(''change''); } }); $(''#editor'').on(''change'', function() {alert(''changed'')});


Para evitar los temporizadores y los botones de "guardar", puede usar un evento de desenfoque que se dispara cuando el elemento pierde el foco. pero para estar seguro de que el elemento realmente fue cambiado (no solo enfocado y desenfocado), su contenido debe compararse con su última versión. o use el evento keydown para establecer algún indicador "sucio" en este elemento.


Respuesta no jQuery rápida y sucia :

function setChangeListener (div, listener) { div.addEventListener("blur", listener); div.addEventListener("keyup", listener); div.addEventListener("paste", listener); div.addEventListener("copy", listener); div.addEventListener("cut", listener); div.addEventListener("delete", listener); div.addEventListener("mouseup", listener); } var div = document.querySelector("someDiv"); setChangeListener(div, function(event){ console.log(event); });


Respuesta no jQuery ...

function makeEditable(elem){ elem.setAttribute(''contenteditable'', ''true''); elem.addEventListener(''blur'', function (evt) { elem.removeAttribute(''contenteditable''); elem.removeEventListener(''blur'', evt.target); }); elem.focus(); }

Para usarlo, llame a (diga) un elemento de encabezado con id = "myHeader"

makeEditable(document.getElementById(''myHeader''))

Ese elemento ahora será editable por el usuario hasta que pierda el foco.


Una respuesta simple en JQuery, acabo de crear este código y pensé que también será útil para otros.

var cont; $("div [contenteditable=true]").focus(function() { cont=$(this).html(); }); $("div [contenteditable=true]").blur(function() { if ($(this).html()!=cont) { //Here you can write the code to run when the content change } });


Usar DOMCharacterDataModified en MutationEvents conducirá a lo mismo. El tiempo de espera se configura para evitar el envío de valores incorrectos (por ejemplo, en Chrome tuve algunos problemas con la tecla de espacio)

var timeoutID; $(''[contenteditable]'').bind(''DOMCharacterDataModified'', function() { clearTimeout(timeoutID); $that = $(this); timeoutID = setTimeout(function() { $that.trigger(''change'') }, 50) }); $(''[contentEditable]'').bind(''change'', function() { console.log($(this).text()); })

Ejemplo de JSFIDDLE


Yo sugeriría adjuntar escuchas a eventos clave activados por el elemento editable, aunque debe tener en cuenta que los eventos keydown y keypress keydown que se keydown el contenido. Esto no cubrirá todos los medios posibles para cambiar el contenido: el usuario también puede usar cortar, copiar y pegar desde los menús del navegador de Edición o del contexto, por lo que es posible que también desee controlar los eventos de copy y paste . Además, el usuario puede colocar texto u otro contenido, por lo que hay más eventos allí ( mouseup , por ejemplo). Es posible que desee sondear los contenidos del elemento como una alternativa.

ACTUALIZACIÓN 29 de octubre de 2014

El evento de input HTML5 es la respuesta a largo plazo. Al momento de escribir, se admite para elementos contenteditable en los navegadores Mozilla actuales (de Firefox 14) y WebKit / Blink, pero no en IE.

Manifestación:

document.getElementById("editor").addEventListener("input", function() { console.log("input event fired"); }, false);

<div contenteditable="true" id="editor">Please type something in here</div>

Demostración: http://jsfiddle.net/ch6yn/2691/


Dos opciones:

1) Para los navegadores modernos (de hoja perenne): el evento "input" actuaría como un evento alternativo de "cambio".

developer.mozilla.org/en-US/docs/Web/Events/input

document.querySelector(''div'').addEventListener(''input'', (e) => { // Do something with the "change"-like event });

o

<div oninput="someFunc(event)"></div>

o (con jQuery)

$(''div'').on(''click'', function(e) { // Do something with the "change"-like event });

2) Para tener en cuenta los navegadores IE11 y modernos (de hoja perenne): esto vigila los cambios de elementos y su contenido dentro de la div.

Mozilla

var div = document.querySelector(''div''); var divMO = new window.MutationObserver(function(e) { // Do something on change }); divMO.observe(div, { childList: true, subtree: true, characterData: true });


const p = document.querySelector(''p'') const result = document.querySelector(''div'') const observer = new MutationObserver((mutationRecords) => { result.textContent = mutationRecords[0].target.data // result.textContent = p.textContent }) observer.observe(p, { characterData: true, subtree: true, })

<p contenteditable>abc</p> <div />