Câu trả lời:
Tôi khuyên bạn nên gắn người nghe vào các sự kiện chính được kích hoạt bởi yếu tố có thể chỉnh sửa, mặc dù bạn cần lưu ý rằng keydown
và keypress
các sự kiện được kích hoạt trước khi nội dung được thay đổi. Điều này sẽ không bao gồm tất cả các phương tiện có thể thay đổi các nội dung: người sử dụng cũng có thể sử dụng cắt, sao chép và dán từ Edit hoặc menu trình duyệt bối cảnh, vì vậy bạn có thể muốn để xử lý cut
copy
và paste
các sự kiện quá. Ngoài ra, người dùng có thể thả văn bản hoặc nội dung khác, vì vậy có nhiều sự kiện hơn ở đó ( mouseup
ví dụ). Bạn có thể muốn thăm dò nội dung của phần tử dưới dạng dự phòng.
CẬP NHẬT 29 tháng 10 năm 2014
Sự kiện HTML5input
là câu trả lời trong dài hạn. Tại thời điểm viết bài, nó được hỗ trợ cho contenteditable
các thành phần trong Mozilla hiện tại (từ Firefox 14) và trình duyệt WebKit / Blink, nhưng không phải IE.
Bản giới thiệu:
document.getElementById("editor").addEventListener("input", function() {
console.log("input event fired");
}, false);
<div contenteditable="true" id="editor">Please type something in here</div>
Bản trình diễn: http://jsfiddle.net/ch6yn/2691/
cut
, copy
và paste
các sự kiện trong các trình duyệt hỗ trợ họ (IE 5+, Firefox 3.0+, Safari 3+, Chrome)
input
sự kiện HTML5 .
Đây là một phiên bản hiệu quả hơn sử dụng on
cho tất cả các nội dung. Nó dựa trên các câu trả lời hàng đầu ở đây.
$('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');
}
});
Dự án ở đây: https://github.com/balupton/html5edit
document.getElementById('editor_input').innerHTML = 'ssss'
. Hạn chế là nó yêu cầu IE11
Cân nhắc sử dụng M mutObserver . Các trình quan sát này được thiết kế để phản ứng với các thay đổi trong DOM và như là một sự thay thế biểu diễn cho Sự kiện đột biến .
Ưu điểm:
Nhược điểm:
Tìm hiểu thêm:
input
sự kiện HTML5 (được hỗ trợ contenteditable
trong tất cả các trình duyệt WebKit và Mozilla hỗ trợ người quan sát đột biến), vì đột biến DOM có thể xảy ra thông qua tập lệnh cũng như đầu vào của người dùng, nhưng đó là một giải pháp khả thi cho các trình duyệt đó. Tôi tưởng tượng nó có thể gây hại cho hiệu suất nhiều hơn input
sự kiện, nhưng tôi không có bằng chứng cứng cho việc này.
input
sự kiện HTML5 sẽ kích hoạt trong từng tình huống này (cụ thể là kéo và thả, in nghiêng, sao chép / cắt / dán qua menu ngữ cảnh). Tôi cũng đã thử nghiệm bẻ cong w / cmd / ctrl + b và nhận được kết quả mong đợi. Tôi cũng đã kiểm tra và có thể xác minh rằng input
sự kiện này không kích hoạt các thay đổi theo chương trình (điều này có vẻ hiển nhiên, nhưng có thể trái ngược với một số ngôn ngữ khó hiểu trên trang MDN có liên quan; xem phần dưới cùng của trang ở đây để biết ý tôi là: nhà phát triển .mozilla.org / en-US / docs / Web / Sự kiện / đầu vào )
Tôi đã sửa đổi câu trả lời của luật sư như vậy và điều này hiệu quả với tôi. Tôi sử dụng sự kiện keyup thay vì keypress hoạt động tuyệt vời.
$('#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')});
Câu trả lời nhanh và bẩn của 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);
});
Hai lựa chọn:
1) Đối với các trình duyệt hiện đại (thường xanh): Sự kiện "đầu vào" sẽ hoạt động như một sự kiện "thay đổi" thay thế.
https://developer.mozilla.org/en-US/docs/Web/Events/input
document.querySelector('div').addEventListener('input', (e) => {
// Do something with the "change"-like event
});
hoặc là
<div oninput="someFunc(event)"></div>
hoặc (với jQuery)
$('div').on('click', function(e) {
// Do something with the "change"-like event
});
2) Để giải thích cho IE11 và các trình duyệt hiện đại (thường xanh): Đồng hồ này để thay đổi thành phần và nội dung của chúng bên trong div.
https://developer.mozilla.org/en-US/docs/Web/API/MutingObserver
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 />
Đây là những gì làm việc cho tôi:
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);
}
});
Chủ đề này rất hữu ích trong khi tôi đang điều tra chủ đề.
Tôi đã sửa đổi một số mã có sẵn ở đây thành một plugin jQuery để nó ở dạng có thể sử dụng lại, chủ yếu để đáp ứng nhu cầu của tôi nhưng những người khác có thể đánh giá cao giao diện đơn giản hơn để bắt đầu sử dụng các thẻ có thể nội dung.
https://gist.github.com/3410122
Do mức độ phổ biến ngày càng tăng, plugin đã được Makesites.org chấp nhận
Sự phát triển sẽ tiếp tục từ đây:
Đây là giải pháp tôi đã sử dụng và làm việc tuyệt vời. Tôi sử dụng $ (this) .text () thay vì tôi chỉ sử dụng div một dòng có thể chỉnh sửa nội dung. Nhưng bạn cũng có thể sử dụng .html () theo cách này mà bạn không phải lo lắng về phạm vi của biến toàn cục / không toàn cầu và trước đây thực sự được gắn vào div trình soạn thảo.
$('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!');
}
});
Để tránh bộ hẹn giờ và nút "lưu", bạn có thể sử dụng sự kiện mờ sẽ kích hoạt khi phần tử mất tiêu điểm. nhưng để chắc chắn rằng phần tử đã thực sự thay đổi (không chỉ tập trung và làm mất nét), nội dung của nó nên được so sánh với phiên bản cuối cùng của nó. hoặc sử dụng sự kiện keydown để đặt một số cờ "bẩn" trên thành phần này.
Một câu trả lời đơn giản trong JQuery, tôi chỉ tạo mã này và nghĩ rằng nó cũng hữu ích cho những người khác
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]")
sẽ chọn tất cả trẻ em của một div, trực tiếp hoặc gián tiếp, có thể nội dung được.
Câu trả lời không của JQuery ...
function makeEditable(elem){
elem.setAttribute('contenteditable', 'true');
elem.addEventListener('blur', function (evt) {
elem.removeAttribute('contenteditable');
elem.removeEventListener('blur', evt.target);
});
elem.focus();
}
Để sử dụng nó, hãy gọi (nói) một phần tử tiêu đề với id = "myHeader"
makeEditable(document.getElementById('myHeader'))
Phần tử đó bây giờ sẽ được người dùng chỉnh sửa cho đến khi mất tập trung.
Sự kiện onchange không kích hoạt khi một thành phần có thuộc tính contentEditable bị thay đổi, một cách tiếp cận được đề xuất có thể là thêm một nút, để "lưu" phiên bản.
Kiểm tra plugin này xử lý vấn đề theo cách đó:
Sử dụng DOMCharacterDataModified trong M mutEvents sẽ dẫn đến điều tương tự. Thời gian chờ được thiết lập để ngăn gửi các giá trị không chính xác (ví dụ: trong Chrome tôi gặp một số vấn đề với phím cách)
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
sẽ không kích hoạt khi người dùng sửa đổi văn bản hiện có, ví dụ như áp dụng chữ in đậm hoặc in nghiêng. DOMSubtreeModified
là thích hợp hơn trong trường hợp này. Ngoài ra, mọi người nên nhớ rằng các trình duyệt cũ không hỗ trợ các sự kiện này.
Tôi đã xây dựng một plugin jQuery để làm điều này.
(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);
Bạn chỉ có thể gọi $('.wysiwyg').wysiwygEvt();
Bạn cũng có thể xóa / thêm sự kiện nếu muốn
innerHTML
đắt tiền). Tôi sẽ khuyên bạn nên sử dụng input
sự kiện mà nó tồn tại và quay trở lại một cái gì đó như thế này nhưng với một số loại tranh luận.
Trong góc 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
}
}
Hãy làm theo các giải pháp đơn giản sau đây
Trong .ts:
getContent(innerText){
this.content = innerText;
}
trong .html:
<div (blur)="getContent($event.target.innerHTML)" contenteditable [innerHTML]="content"></div>
Kiểm tra ý tưởng này ra. http://pastie.org/1096892
Tôi nghĩ rằng nó gần. HTML 5 thực sự cần thêm sự kiện thay đổi vào thông số kỹ thuật. Vấn đề duy nhất là hàm gọi lại đánh giá if (before == $ (this) .html ()) trước khi nội dung thực sự được cập nhật bằng $ (this) .html (). setTimeout không hoạt động, và nó buồn. Cho tôi biết bạn nghĩ gì.
Dựa trên câu trả lời của @ 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() { ...}
.