Yanıtlar:
Anahtar olaylar düzenlenebilir öğe tarafından ateş etmek o farkında olması gerekir gerçi ben takılarak dinleyicileri öneririm keydown
ve keypress
içeriğin kendisi değiştirilir önce olay harekete. Bu, içeriği değiştirmek için her türlü aracı kapsamaz: kullanıcı, Düzenle veya bağlam tarayıcı menülerinden kes, kopyala ve yapıştır da kullanabilir, böylece cut
copy
ve paste
olaylarını da işlemek isteyebilirsiniz . Ayrıca, kullanıcı metin veya başka içerik bırakabilir, bu nedenle orada daha fazla etkinlik vardır ( mouseup
örneğin). Öğenin içeriğini yedek olarak yoklamak isteyebilirsiniz.
GÜNCELLEME 29 Ekim 2014
HTML5 input
olay uzun vadede cevaptır. Yazma sırasında, contenteditable
geçerli Mozilla'daki (Firefox 14'ten) ve WebKit / Blink tarayıcılarındaki öğeler için desteklenir , ancak IE için desteklenmez.
Demo:
document.getElementById("editor").addEventListener("input", function() {
console.log("input event fired");
}, false);
<div contenteditable="true" id="editor">Please type something in here</div>
cut
, copy
ve paste
tarayıcılarda olaylar onları destekleyen (IE 5+, Firefox 3.0+, Safari 3+, Chrome)
input
etkinliği tarafından kapsanmalıdır .
İşte on
tüm içerikler için kullanılan daha verimli bir sürüm . Buradaki en iyi cevaplara dayanıyor.
$('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');
}
});
Proje burada: https://github.com/balupton/html5edit
document.getElementById('editor_input').innerHTML = 'ssss'
. Dezavantajı IE11 gerektirir
MutationObserver kullanmayı düşünün . Bu gözlemciler, DOM'daki değişikliklere tepki vermek ve Mutasyon Olaylarının yerine geçmek için tasarlanmıştır .
Artıları:
Eksileri:
Daha fazla bilgi edin:
input
olayıyla ( contenteditable
mutasyon gözlemcilerini destekleyen tüm WebKit ve Mozilla tarayıcılarında desteklenir) aynı değildir, ancak bu tarayıcılar için geçerli bir çözümdür. Performansa input
olaydan daha fazla zarar verebileceğini düşünüyorum, ancak bunun için sağlam bir kanıtım yok.
input
Bu durumların her birinde HTML5 olayının tetiklendiğini (en azından Chrome 43.0.2357.130'da) (özellikle sürükle ve bırak, italikleştirme, kopyala / kes / yapıştır bağlam menüsünden) doğrulayabildim . Ayrıca kalınlık w / cmd / ctrl + b'yi test ettim ve beklenen sonuçları aldım. Ben de kontrol edilmeli ve doğrulamak başardı input
olay değil bariz görünüyor (programatik değişikliklere üzerine ateş, ancak tartışmasız ilgili MDN sayfada bazı kafa karıştırıcı dilin aykırı olduğu; ne demek istediğimi görmek için buraya sayfanın sonuna bakınız: geliştirici .mozilla.org / tr-
Lawwantsin'ın cevabını bu şekilde değiştirdim ve bu benim için işe yarıyor. Harika çalışan keypress yerine keyup olayını kullanıyorum.
$('#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')});
olmayan jQuery hızlı ve kirli cevap:
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);
});
İki seçenek:
1) Modern (herdem yeşil) tarayıcılar için: "input" olayı alternatif bir "change" olayı olarak işlev görür.
https://developer.mozilla.org/en-US/docs/Web/Events/input
document.querySelector('div').addEventListener('input', (e) => {
// Do something with the "change"-like event
});
veya
<div oninput="someFunc(event)"></div>
veya (jQuery ile)
$('div').on('click', function(e) {
// Do something with the "change"-like event
});
2) IE11 ve modern (herdem yeşil) tarayıcıları hesaba katmak için: Bu, div içindeki element değişikliklerini ve içeriklerini izler.
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 />
İşte benim için işe yarayan:
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);
}
});
Konuyu araştırırken bu konu çok yardımcı oldu.
Burada mevcut kodun bir kısmını jQuery eklentisine dönüştürdüm, bu yüzden öncelikle ihtiyaçlarımı karşılamak için yeniden kullanılabilir bir formda, ancak diğerleri içerikli etiketleri kullanarak atlamak için daha basit bir arayüzü takdir edebilir.
https://gist.github.com/3410122
Artan popülaritesi nedeniyle eklenti Makesites.org tarafından benimsenmiştir.
Gelişim buradan devam edecek:
İşte sonunda kullandım ve harika çalışıyor çözüm. Bunun yerine $ (this) .text () kullanıyorum çünkü içeriği düzenlenebilir tek satırlık bir div kullanıyorum. Ancak .html () yöntemini de kullanabilirsiniz.
$('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!');
}
});
Zamanlayıcıları ve "kaydet" düğmelerini önlemek için, öğe odağı kaybettiğinde patlayan bulanıklık olayını kullanabilirsiniz. ancak öğenin gerçekten değiştirildiğinden emin olmak için (sadece odaklanmış ve odaklanmamış değil), içeriği son sürümüyle karşılaştırılmalıdır. veya bu öğede bazı "kirli" bayrak ayarlamak için keydown olayını kullanın.
JQuery basit bir cevap, ben sadece bu kodu oluşturdu ve diğerleri için de yararlı olacağını düşündüm
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]")
Bir div'in doğrudan veya dolaylı olarak tartışılabilir tüm çocuklarını seçeceğini unutmayın .
JQuery olmayan yanıt ...
function makeEditable(elem){
elem.setAttribute('contenteditable', 'true');
elem.addEventListener('blur', function (evt) {
elem.removeAttribute('contenteditable');
elem.removeEventListener('blur', evt.target);
});
elem.focus();
}
Kullanmak için id = "myHeader" olan bir başlık öğesini çağırın (diyelim)
makeEditable(document.getElementById('myHeader'))
Bu öğe, artık odağını kaybedene kadar kullanıcı tarafından düzenlenebilir.
Onchange olayı, contentEditable özniteliğine sahip bir öğe değiştirildiğinde tetiklenmez, önerilen bir yaklaşım , baskıyı "kaydetmek" için bir düğme eklemek olabilir .
Sorunu bu şekilde ele alan bu eklentiyi kontrol edin:
Kullanılması MutationEvents altında DOMCharacterDataModified aynı yol açacaktır. Zaman aşımı yanlış değerler göndermeyi önlemek için ayarlandı (örneğin Chrome'da boşluk tuşu ile ilgili bazı sorunlar yaşadım)
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
kullanıcı varolan metni değiştirdiğinde (örneğin kalın veya italik uygulamak) tetiklenmez. DOMSubtreeModified
bu durumda daha uygundur. Ayrıca, insanlar eski tarayıcıların bu etkinlikleri desteklemediğini hatırlamalıdır.
Bunu yapmak için bir jQuery eklentisi oluşturdum.
(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);
Sadece arayabilirsiniz $('.wysiwyg').wysiwygEvt();
İsterseniz etkinlikleri kaldırabilir / ekleyebilirsiniz
innerHTML
pahalı) bu yavaş ve gecikmeli olur . input
Var olan olayı kullanmayı ve böyle bir şeye düşmeyi ancak bir tür zıplatma ile tavsiye ederim.
Açısal 2+
<div contentEditable (input)="type($event)">
Value
</div>
@Component({
...
})
export class ContentEditableComponent {
...
type(event) {
console.log(event.data) // <-- The pressed key
console.log(event.path[0].innerHTML) // <-- The content of the div
}
}
Lütfen aşağıdaki basit çözümü izleyin
.Ts içinde:
getContent(innerText){
this.content = innerText;
}
.html biçiminde:
<div (blur)="getContent($event.target.innerHTML)" contenteditable [innerHTML]="content"></div>
Bu fikri kontrol edin. http://pastie.org/1096892
Sanırım yakın. HTML 5'in gerçekten change olayını spesifikasyona eklemesi gerekiyor. Tek sorun, içeriğin $ (this) .html () içinde gerçekten güncellenmeden önce (== $ (this) .html ()) önce geri arama işlevinin değerlendirmesidir. setTimeout çalışmıyor ve üzücü. Ne düşündüğü söyle.
@ Balupton'un cevabına dayanarak:
$(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() { ...}
.