Frage

Ich möchte eine Funktion ausführen, wenn ein Benutzer den Inhalt von a bearbeitet div mit contenteditable Attribut. Was ist das Äquivalent von einem onchange Veranstaltung?

Ich verwende JQuery, sodass Lösungen, die JQuery verwenden, bevorzugt. Vielen Dank!

War es hilfreich?

Lösung

Ich würde vorschlagen, die Zuhörer an wichtige Ereignisse zu binden, die vom bearbeitbaren Element abgefeuert wurden, obwohl Sie sich bewusst sein müssen keydown und keypress Ereignisse werden entlassen, bevor der Inhalt selbst geändert wird. Dies umfasst nicht jedes mögliche Mittel zum Ändern des Inhalts: Der Benutzer kann auch Schnitt-, Kopier- und Einfügen der Bearbeitungs- oder Kontext -Browser -Menüs verwenden cut copy und paste Ereignisse auch. Außerdem kann der Benutzer Text oder andere Inhalte fallen lassen, daher gibt es dort mehr Ereignisse (mouseup, zum Beispiel). Möglicherweise möchten Sie den Inhalt des Elements als Fallback befragen.

Update 29. Oktober 2014

Das HTML5 input Veranstaltung ist die Antwort langfristig. Zum Zeitpunkt des Schreibens wird es für unterstützt contenteditable Elemente in aktuellem Mozilla (von Firefox 14) und Webkit/Blink -Browsern, aber nicht dh.

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/

Andere Tipps

Hier ist eine effizientere Version, die verwendet on Für alle zufriedenen Funktionen. Es basiert auf den Top -Antworten hier.

$('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/balupon/html5edit

Erwägen Sie zu verwenden MutationObserver. Diese Beobachter reagieren auf Veränderungen im DOM und als leistungsfähiger Ersatz für Mutationsereignisse.

Profis:

  • Feuer wann irgendein Veränderungen treten auf, was durch das Hören von wichtigen Ereignissen schwer zu erreichen ist, wie dies durch andere Antworten vorgeschlagen wird. Zum Beispiel funktionieren all diese gut: Drag & Drop, kursiv, kopieren/schneiden/einfügen über das Kontextmenü.
  • Entworfen mit der Leistung.
  • Einfacher, einfacher Code. Es ist viel einfacher, Code zu verstehen und zu debuggen, der auf ein Ereignis hört als auf Code, der 10 Ereignisse hört.
  • Google hat eine ausgezeichnete Zusammenfassungsbibliothek der Mutation Dies macht die Verwendung von MutationObserver sehr einfach.

Nachteile:

  • Erfordert eine sehr aktuelle Version von Firefox (14,0+), Chrome (18+) oder IE (11+).
  • Neue API zu verstehen
  • Noch nicht viele Informationen zu Best Practices oder Fallstudien verfügbar

Mehr erfahren:

  • Ich habe ein wenig geschrieben Snippet Vergleiche der Verwendung von MutationObsers mit einer Vielzahl von Ereignissen. Ich habe Baluptons Code seit seinem benutzt Antworten Hat die meisten Aufpackungen.
  • Mozilla hat eine ausgezeichnete Seite auf der API
  • Schauen Sie sich das an die MutationsmutationSummary Bibliothek

Nicht JQuery schnell und schmutzig Antworten:

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 verändert und das funktioniert für mich. Ich benutze das KeyUp -Ereignis anstelle von Schlüsselpress, was hervorragend 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')});

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

Zwei Optionen:

1) für moderne (immergrüne) Browser:Das "Input" -Ereignis würde als alternatives "Änderung" -Ereignis 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) IE11 und moderne (immergrüne) Browser zu berücksichtigen:Dies beobachtet sich nach Elementwechsel 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, was für mich funktioniert hat:

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

Dieser Thread war sehr hilfreich, als ich das Thema untersuchte.

Ich habe einige der hier verfügbaren Code in ein JQuery-Plugin geändert, sodass es in einer wiederverwendbaren Form ist, um meine Bedürfnisse zu erfüllen, aber andere können eine einfachere Schnittstelle zu Jumpstart mit inhaltlichen Tags schätzen.

https://gist.github.com/3410122

Aktualisieren:

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

Die Entwicklung wird von hier aus fortgesetzt:

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

Hier ist die Lösung, die ich verwendet habe und arbeitet fabelhaft. Ich benutze $ (this) .Text () stattdessen, weil ich nur ein Zeilen -Div verwende, das inhaltlich bearbeitet wird. Sie können jedoch auch .html () auf diese Weise verwenden, dass Sie sich keine Sorgen um den Umfang einer globalen/nicht-globalen Variablen machen müssen, und der zuvor ist der Editor Div tatsächlich beigefügt.

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

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 verwenden, rufen Sie ein Header -Element mit id = "myheader" an (sagen wir).

makeEditable(document.getElementById('myHeader'))

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

Das OnChange -Ereignis feuert nicht aus, wenn ein Element mit dem inhaltlichen Attribut geändert wird. Ein vorgeschlagener Ansatz könnte darin bestehen, eine Taste zu hinzufügen, zu hinzuzufügen "sparen" die Ausgabe.

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

Um Timer zu vermeiden und Schaltflächen zu "speichern", können Sie Blur Event verwenden, wenn das Element den Fokus verliert. Um sicher zu sein, dass das Element tatsächlich geändert wurde (nicht nur fokussiert und defokoliert), sollte sein Inhalt mit seiner letzten Version verglichen werden. Oder verwenden Sie das Schlüsseldown -Ereignis, um dieses Element "schmutziges" Flag zu setzen.

Verwendung Domaracterdatamodifiziert unter mutationEvents wird zum gleichen führen. Das Timeout wird eingerichtet, um zu verhindern, dass falsche Werte gesendet werden (z. B. in Chrome Ich hatte einige Probleme mit dem Space -Schlüssel).

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

Ich habe dazu ein JQuery -Plugin gebaut.

(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 anrufen $('.wysiwyg').wysiwygEvt();

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

Eine einfache Antwort in jQuery, ich habe diesen Code gerade erstellt und dachte, er wird auch für andere hilfreich sein

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

Überprüfen Sie diese Idee.http://pastie.org/1096892

Ich denke, es ist nah. HTML 5 muss das Änderungsereignis wirklich zur Spezifikation hinzufügen. Das einzige Problem ist, dass die Rückruffunktion bewertet, ob (vor == $ (this) .html ()), bevor der Inhalt tatsächlich in $ (this) .html () aktualisiert wird. SetTimeout funktioniert nicht und es ist traurig. Lass mich wissen was du denkst.

Basierend auf @Baluptons Antwort:

$(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>

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top