it-swarm.com.de

inhaltlich editierbare Änderungsereignisse

Ich möchte eine Funktion ausführen, wenn ein Benutzer den Inhalt einer div mit dem Attribut contenteditable bearbeitet. Was ist das Äquivalent eines onchange-Ereignisses?

Ich verwende jQuery, so dass Lösungen, die jQuery verwenden, bevorzugt werden. Vielen Dank!

307
Jourkey

Ich würde vorschlagen, Listener mit wichtigen Ereignissen zu verknüpfen, die von dem bearbeitbaren Element ausgelöst werden, obwohl Sie wissen müssen, dass keydown und keypress-Ereignisse ausgelöst werden, bevor der Inhalt selbst geändert wird. Dies deckt nicht alle Möglichkeiten ab, den Inhalt zu ändern: Der Benutzer kann auch Ausschneiden, Kopieren und Einfügen über die Menüs Bearbeiten oder Kontextbrowser verwenden. Daher möchten Sie möglicherweise auch die Ereignisse cutcopy und paste behandeln. Der Benutzer kann auch Text oder anderen Inhalt ablegen, so dass dort weitere Ereignisse vorhanden sind (z. B. mouseup). Möglicherweise möchten Sie den Inhalt des Elements als Fallback abfragen.

UPDATE 29. Oktober 2014

Das HTML5 input -Ereignis ist die Antwort auf lange Sicht. Zum Zeitpunkt des Schreibens wird es für contenteditable-Elemente in aktuellen Mozilla-Browsern (von Firefox 14) und WebKit/Blink-Browsern unterstützt, nicht jedoch im IE.

Demo:

document.getElementById("editor").addEventListener("input", function() {
    console.log("input event fired");
}, false);
<div contenteditable="true" id="editor">Please type something in here</div>

Demo: http://jsfiddle.net/ch6yn/2691/

249
Tim Down

Hier ist eine effizientere Version, die on für alle inhaltbaren Dateien verwendet. Es basiert auf den besten Antworten.

$('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');
    }
});

Das Projekt ist hier: https://github.com/balupton/html5edit

173
balupton

Erwägen Sie die Verwendung von MutationObserver . Diese Beobachter reagieren auf Änderungen im DOM und sind ein leistungsfähiger Ersatz für Mutation Events .

Pros:

  • Wird ausgelöst, wenn any geändert wird. Dies ist schwer zu erreichen, wenn Schlüsselereignisse abgehört werden, wie in anderen Antworten vorgeschlagen. Zum Beispiel funktionieren alle diese Funktionen gut: Drag & Drop, Kursivieren, Kopieren/Ausschneiden/Einfügen über das Kontextmenü.
  • Entwickelt für Leistung.
  • Einfacher, unkomplizierter Code. Es ist viel einfacher, Code zu verstehen und zu debuggen, der auf ein Ereignis wartet, als auf Code, der auf 10 Ereignisse wartet.
  • Google verfügt über eine ausgezeichnete Mutationszusammenfassungsbibliothek , die die Verwendung von MutationObservers sehr einfach macht.

Nachteile:

  • Erfordert eine aktuelle Version von Firefox (14.0+), Chrome (18+) oder IE (11+).
  • Neue API zum Verständnis
  • Noch nicht viele Informationen zu bewährten Verfahren oder Fallstudien verfügbar

Mehr erfahren:

  • Ich habe ein kleines snippet geschrieben, um MutationObserers mit einer Vielzahl von Ereignissen zu vergleichen. Ich habe den Code von Balupton verwendet, seit er answer die meisten Upvotes hat.
  • Mozilla hat eine ausgezeichnete Seite in der API
  • Sehen Sie sich die Bibliothek MutationSummary an
49
jrullmann

Nicht jQuery schnell und dirty Antwort:

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);
});
20
Developia

Ich habe die Antwort von lawwantsin so modifiziert, und das funktioniert für mich. Ich benutze das keyup-Ereignis anstelle von Tastendruck, was großartig funktioniert.

$('#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')});
19
Dennkster

Dieser Thread war sehr hilfreich, während ich das Thema untersuchte. 

Ich habe einen Teil des hier verfügbaren Codes in ein jQuery-Plugin geändert, sodass es in wiederverwendbarer Form vorliegt, hauptsächlich um meine Bedürfnisse zu erfüllen. Andere Benutzer schätzen vielleicht eine einfachere Schnittstelle für den Start mit contenteditable-Tags. 

https://Gist.github.com/3410122

Aktualisieren:

Aufgrund seiner zunehmenden Beliebtheit wurde das Plugin von Makesites.org übernommen.

Die Entwicklung wird von hier aus fortgesetzt:

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

3
tracend

Folgendes hat für mich funktioniert:

   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);
            }
   });
3

Zwei Optionen:

1) Für moderne (immergrüne) Browser: Das Ereignis "input" würde als alternatives Ereignis "change" fungieren.

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

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

oder

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

oder (mit jQuery)

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

2) Um IE11 und moderne (immergrüne) Browser zu berücksichtigen: Dies überwacht Elementänderungen und deren Inhalt im div.

https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

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 });
2
bit-less

Hier ist die Lösung, die ich am Ende verwendet habe und die hervorragend funktioniert. Ich verwende stattdessen $ (this) .text (), weil ich nur ein einzeiliges Div benutze, das inhaltlich editierbar ist. Sie können jedoch auch .html () verwenden, um sich nicht um den Gültigkeitsbereich einer globalen/nicht-globalen Variablen zu kümmern, und das Vorher ist tatsächlich mit dem Editor div verbunden.

$('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!');
    }
});
2
user740433

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 />

1
superwf

Um Timer und "Speichern" -Schaltflächen zu vermeiden, können Sie ein Unschärfe-Ereignis verwenden, das ausgelöst wird, wenn das Element den Fokus verliert. Um jedoch sicher zu sein, dass das Element tatsächlich geändert wurde (nicht nur fokussiert und defokussiert), sollte der Inhalt mit der letzten Version verglichen werden. oder verwenden Sie das keydown-Ereignis, um ein "schmutziges" Flag für dieses Element zu setzen.

0
joox

Die Verwendung von DOMCharacterDataModified unter MutationEvents führt zu demselben Ergebnis. Das Zeitlimit ist so eingerichtet, dass falsche Werte nicht gesendet werden (z. B. hatte ich Probleme mit dem Leerzeichen in Chrome).

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());
})

JSFIDDLE Beispiel

0
janfabian

Eine einfache Antwort in JQuery. Ich habe diesen Code gerade erstellt und dachte, er wäre auch für andere hilfreich

    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
        }           
    });
0
sarath

Nicht JQuery-Antwort ...

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

Um es zu benutzen, rufen Sie (sagen wir) ein Header-Element mit id = "myHeader" auf

makeEditable(document.getElementById('myHeader'))

Dieses Element kann jetzt vom Benutzer bearbeitet werden, bis es den Fokus verliert.

0
DrMcCleod

Ich habe dazu ein jQuery-Plugin erstellt.

(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);

Sie können einfach $('.wysiwyg').wysiwygEvt(); aufrufen.

Sie können Ereignisse auch entfernen/hinzufügen, wenn Sie möchten

0
Blowsie

Das onchange-Ereignis wird nicht ausgelöst, wenn ein Element mit dem contentEditable-Attribut geändert wird. Ein vorgeschlagener Ansatz könnte das Hinzufügen einer Schaltfläche zu "save" der Edition sein.

Überprüfen Sie dieses Plugin, das das Problem auf diese Weise behandelt:

0
CMS