回答:
私はあなたがいることを認識する必要がありますけれども、キーイベントにアタッチリスナーは、編集可能な要素により解雇をお勧めしたいkeydown
とkeypress
、イベント自体が変更されたコンテンツの前に解雇されています。これは、コンテンツを変更するすべての可能な手段をカバーするわけではありません。ユーザーは編集またはコンテキストブラウザメニューから切り取り、コピー、貼り付けを使用することもできるため、cut
copy
およびpaste
イベントも処理することができます。また、ユーザーはテキストやその他のコンテンツをドロップできるので、そこにはより多くのイベントがあります(mouseup
たとえば)。フォールバックとして要素のコンテンツをポーリングすることができます。
2014年10月29日更新
HTML5のinput
イベントは、長期的に答えています。執筆時点ではcontenteditable
、現在のMozilla(Firefox 14以降)およびWebKit / Blinkブラウザーの要素でサポートされていますが、IEではサポートされていません。
デモ:
document.getElementById("editor").addEventListener("input", function() {
console.log("input event fired");
}, false);
<div contenteditable="true" id="editor">Please type something in here</div>
cut
、それらをサポートするブラウザー(IE 5 +、Firefox)でイベントcopy
とpaste
イベントを処理する必要があります。3.0以降、Safari 3以降、Chrome)
input
イベントでカバーされるはずです。
これはon
、すべてのcontenteditableに使用するより効率的なバージョンです。ここでのトップアンサーに基づいています。
$('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');
}
});
プロジェクトはここにあります: https //github.com/balupton/html5edit
document.getElementById('editor_input').innerHTML = 'ssss'
。コンソールで試してください。欠点は、IE11が必要なことです
MutationObserverの使用を検討してください。これらのオブザーバーは、DOMの変更に対応するように設計されており、Mutation Eventsのパフォーマンスに代わるものです。
長所:
短所:
もっと詳しく知る:
input
ため、HTML5 イベント(contenteditable
ミューテーションオブザーバーをサポートするすべてのWebKitおよびMozillaブラウザーでサポートされています)とはまったく異なりますが、これらのブラウザーでは実行可能なソリューションです。input
イベントよりもパフォーマンスに悪影響を与える可能性があると思いますが、これについて明確な証拠はありません。
input
これらの状況(具体的には、ドラッグアンドドロップ、斜体、コンテキストメニューからのコピー/切り取り/貼り付け)でHTML5 イベントが発生することを確認できました。また、cmd / ctrl + bを使用して太字をテストし、期待どおりの結果を得ました。また、プログラムによる変更でinput
イベントが発生しないことを確認し、確認できました(これは明白なようですが、関連するMDNページの混乱する言語に間違いなく矛盾しています。このページの下部を参照して、意味を確認してください:開発者.mozilla.org / en-US / docs / Web / Events / input)
私はlawwantsinの答えをそのように変更しましたが、これは私にとってはうまくいきます。うまく機能するkeypressの代わりにkeyupイベントを使用します。
$('#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')});
非jQueryの迅速かつ汚い答え:
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);
});
2つのオプション:
1)最新(常緑)ブラウザーの場合: 「入力」イベントは、代替の「変更」イベントとして機能します。
https://developer.mozilla.org/en-US/docs/Web/Events/input
document.querySelector('div').addEventListener('input', (e) => {
// Do something with the "change"-like event
});
または
<div oninput="someFunc(event)"></div>
または(jQueryを使用)
$('div').on('click', function(e) {
// Do something with the "change"-like event
});
2)IE11および最新の(常緑)ブラウザーを考慮する: これは、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 });
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 />
これが私のために働いたものです:
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);
}
});
このスレッドは、対象を調査しているときに非常に役立ちました。
ここで使用可能なコードの一部をjQueryプラグインに変更しました。これは、主に私のニーズを満たすために再利用可能な形式になるが、他の人はcontenteditableタグを使用してジャンプスタートするためのよりシンプルなインターフェースを高く評価する場合があります。
https://gist.github.com/3410122
その人気の高まりにより、プラグインはMakesites.orgに採用されました
ここから開発が続きます:
これが私が最終的に使用したソリューションで、すばらしい働きをします。代わりに$(this).text()を使用しています。これは、コンテンツの編集が可能な1行のdivを使用しているためです。ただし、この方法で.html()を使用しても、グローバル変数または非グローバル変数のスコープを気にする必要がなく、beforeが実際にエディターのdivにアタッチされます。
$('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!');
}
});
JQueryで簡単な答え、私はこのコードを作成し、他の人にも役立つと思いました
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
}
});
$("div [contenteditable=true]")
は、コンテンツ編集可能なdivの子を直接または間接的にすべて選択することに注意してください。
JQuery以外の回答...
function makeEditable(elem){
elem.setAttribute('contenteditable', 'true');
elem.addEventListener('blur', function (evt) {
elem.removeAttribute('contenteditable');
elem.removeEventListener('blur', evt.target);
});
elem.focus();
}
それを使用するには、(たとえば)id = "myHeader"を含むヘッダー要素を呼び出します
makeEditable(document.getElementById('myHeader'))
その要素は、フォーカスを失うまでユーザーが編集できるようになります。
onchangeイベントは、contentEditable属性を持つ要素が変更されても発生しません。推奨されるアプローチは、ボタンを追加してエディションを「保存」することです。
その方法で問題を処理するこのプラグインを確認してください:
MutationEventsでDOMCharacterDataModifiedを使用すると、同じ結果になります。タイムアウトは、誤った値を送信しないように設定されています(たとえば、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());
})
DOMCharacterDataModified
ユーザーが既存のテキストを変更した場合、たとえばボールドやイタリックを適用した場合は発生しません。 DOMSubtreeModified
この場合、より適切です。また、レガシーブラウザはこれらのイベントをサポートしていないことを覚えておいてください。
これを行うためのjQueryプラグインを作成しました。
(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);
あなたは単に呼び出すことができます $('.wysiwyg').wysiwygEvt();
必要に応じて、イベントを削除/追加することもできます
innerHTML
コストがかかります)、速度が遅くなり、時間がかかります。input
それが存在するイベントを使用して、このような何かにフォールバックすることをお勧めしますが、何らかのデバウンスを伴います。
このアイデアをチェックしてください。 http://pastie.org/1096892
近いと思います。HTML 5では、変更イベントを仕様に追加する必要があります。唯一の問題は、コンテンツが実際に$(this).html()で更新される前に(before == $(this).html())かどうかをコールバック関数が評価することです。setTimeoutが機能せず、悲しいです。どう考えているか教えてください。
@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>
document.getElementById("editor").oninput = function() { ...}
。