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!
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 cut
copy
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>
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
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:
Nachteile:
Mehr erfahren:
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);
});
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')});
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
Aufgrund seiner zunehmenden Beliebtheit wurde das Plugin von Makesites.org übernommen.
Die Entwicklung wird von hier aus fortgesetzt:
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);
}
});
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 });
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!');
}
});
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 />
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.
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());
})
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
}
});
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.
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
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: