ฉันต้องการที่จะเรียกใช้ฟังก์ชั่นเมื่อผู้ใช้แก้ไขเนื้อหาที่div
มีcontenteditable
แอตทริบิวต์ onchange
เหตุการณ์เท่ากับอะไร
ฉันใช้ jQuery ดังนั้นจึงควรเลือกใช้โซลูชันใด ๆ ที่ใช้ jQuery ขอบคุณ!
ฉันต้องการที่จะเรียกใช้ฟังก์ชั่นเมื่อผู้ใช้แก้ไขเนื้อหาที่div
มีcontenteditable
แอตทริบิวต์ onchange
เหตุการณ์เท่ากับอะไร
ฉันใช้ jQuery ดังนั้นจึงควรเลือกใช้โซลูชันใด ๆ ที่ใช้ jQuery ขอบคุณ!
คำตอบ:
ฉันขอแนะนำให้แนบผู้ฟังเข้ากับเหตุการณ์สำคัญที่เกิดขึ้นจากองค์ประกอบที่สามารถแก้ไขได้แม้ว่าคุณจะต้องระวังkeydown
และkeypress
เหตุการณ์นั้นจะถูกไล่ออกก่อนที่เนื้อหาจะเปลี่ยนไป สิ่งนี้จะไม่ครอบคลุมวิธีการที่เป็นไปได้ในการเปลี่ยนแปลงเนื้อหา: ผู้ใช้ยังสามารถใช้ตัดคัดลอกและวางจากเมนูแก้ไขหรือเมนูเบราว์เซอร์บริบทดังนั้นคุณอาจต้องการจัดการcut
copy
และpaste
เหตุการณ์ด้วย นอกจากนี้ผู้ใช้สามารถวางข้อความหรือเนื้อหาอื่น ๆ ดังนั้นจึงมีกิจกรรมเพิ่มเติมmouseup
ตัวอย่างเช่น) คุณอาจต้องการสำรวจความคิดเห็นเนื้อหาขององค์ประกอบว่าเป็นทางเลือก
อัปเดต 29 ตุลาคม 2557
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>
การสาธิต: http://jsfiddle.net/ch6yn/2691/
cut
, copy
และpaste
เหตุการณ์ในเบราว์เซอร์ที่สนับสนุนพวกเขา (IE 5 +, Firefox 3.0+, Safari 3+, Chrome)
input
เหตุการณ์HTML5
นี่เป็นเวอร์ชันที่มีประสิทธิภาพมากกว่าซึ่งใช้on
สำหรับเนื้อหาที่มีความน่าเชื่อถือทั้งหมด มันขึ้นอยู่กับคำตอบยอดนิยมที่นี่
$('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 และเป็นการทดแทนนักแสดงต่อเหตุการณ์การกลายพันธุ์กลายพันธุ์เหตุการณ์
ข้อดี:
จุดด้อย:
เรียนรู้เพิ่มเติม:
input
เหตุการณ์HTML5 (ซึ่งรองรับcontenteditable
ในเบราว์เซอร์ WebKit และ Mozilla ทั้งหมดที่รองรับผู้สังเกตการณ์การกลายพันธุ์) เนื่องจากการกลายพันธุ์ของ DOM อาจเกิดขึ้นผ่านสคริปต์เช่นเดียวกับการป้อนข้อมูลของผู้ใช้ แต่เป็นโซลูชั่นที่ทำงานได้สำหรับเบราว์เซอร์เหล่านั้น ฉันคิดว่ามันอาจเป็นอันตรายต่อการแสดงมากกว่าinput
เหตุการณ์ด้วย แต่ฉันก็ไม่มีหลักฐานที่ชัดเจนสำหรับเรื่องนี้
input
เหตุการณ์HTML5 เริ่มขึ้นในแต่ละสถานการณ์ (โดยเฉพาะการลาก & วาง, ตัวเอียง, คัดลอก / ตัด / วางผ่านเมนูบริบท) ฉันยังทดสอบการใช้ตัวควบคุม w / cmd / ctrl + b และได้ผลลัพธ์ที่คาดหวัง ฉันยังตรวจสอบและสามารถตรวจสอบได้ว่าinput
เหตุการณ์ไม่ได้เกิดขึ้นจากการเปลี่ยนแปลงเชิงโปรแกรม (ซึ่งดูเหมือนชัดเจน แต่มีเนื้อหาที่ตรงกันข้ามกับภาษาที่สับสนในหน้า MDN ที่เกี่ยวข้องดูที่ด้านล่างของหน้านี่เพื่อดูว่าฉันหมายถึงอะไร: นักพัฒนา .mozilla.org / en-US / เอกสาร / เว็บ / กิจกรรม / ข้อมูลเข้า )
ฉันได้แก้ไขคำตอบของ lawwantsin เช่นนี้และได้ผลสำหรับฉัน ฉันใช้เหตุการณ์ 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);
});
สองตัวเลือก:
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 ดังนั้นจึงอยู่ในรูปแบบที่สามารถนำกลับมาใช้ใหม่ได้เพื่อตอบสนองความต้องการของฉัน แต่คนอื่น ๆ อาจชื่นชมอินเตอร์เฟสที่ง่ายกว่าในการเริ่มต้นอย่างรวดเร็ว
https://gist.github.com/3410122
เนื่องจากความนิยมที่เพิ่มขึ้นจึงมีการนำปลั๊กอินมาใช้ Makesites.org
การพัฒนาจะดำเนินต่อจากที่นี่:
นี่เป็นวิธีแก้ปัญหาที่ฉันใช้และทำงานได้อย่างบ้าคลั่ง ฉันใช้ $ (นี่). text () แทนเพราะฉันแค่ใช้ div หนึ่งบรรทัดที่สามารถแก้ไขเนื้อหาได้ แต่คุณอาจใช้. html () ด้วยวิธีนี้คุณไม่ต้องกังวลเกี่ยวกับขอบเขตของตัวแปรโกลบอล / ไม่ใช่โกลบอลและก่อนหน้านั้นแนบกับ div editor จริงๆ
$('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!');
}
});
เพื่อหลีกเลี่ยงตัวจับเวลาและปุ่ม "บันทึก" คุณอาจใช้เหตุการณ์ที่ไม่ชัดเจนซึ่งไฟไหม้เมื่อองค์ประกอบขาดโฟกัส แต่เพื่อให้แน่ใจว่าองค์ประกอบนั้นมีการเปลี่ยนแปลงจริง ๆ (ไม่ใช่แค่เน้นและไม่โฟกัส) เนื้อหาของมันควรจะถูกเปรียบเทียบกับเวอร์ชั่นล่าสุด หรือใช้เหตุการณ์ keydown เพื่อตั้งค่าสถานะ "สกปรก" บางอย่างในองค์ประกอบนี้
คำตอบง่ายๆใน 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 เปลี่ยนไปแนวทางที่แนะนำอาจเพิ่มปุ่มเพื่อ"บันทึก"รุ่น
ตรวจสอบปลั๊กอินนี้ซึ่งจัดการปัญหาด้วยวิธีดังกล่าว:
การใช้DOMCharacterDataModified ภายใต้ MutationEventsจะนำไปสู่สิ่งเดียวกัน การหมดเวลามีการตั้งค่าเพื่อป้องกันการส่งค่าที่ไม่ถูกต้อง (เช่นใน 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
เหตุการณ์ที่มีอยู่และย้อนกลับไปที่สิ่งนี้ แต่มีการโต้แย้งบางอย่าง
ในเชิงมุม 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
}
}
โปรดปฏิบัติตามวิธีแก้ปัญหาง่ายๆดังต่อไปนี้
ใน. ts:
getContent(innerText){
this.content = innerText;
}
ใน. html:
<div (blur)="getContent($event.target.innerHTML)" contenteditable [innerHTML]="content"></div>
ตรวจสอบความคิดนี้ http://pastie.org/1096892
ฉันคิดว่ามันใกล้ HTML 5 จำเป็นต้องเพิ่มเหตุการณ์การเปลี่ยนแปลงไปยังข้อมูลจำเพาะ ปัญหาเดียวก็คือฟังก์ชั่นการโทรกลับจะประเมินว่า (ก่อน == $ (นี้) .html ()) ก่อนที่เนื้อหาจะได้รับการอัปเดตใน $ (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() { ...}
ฉันมักจะทำสิ่งนี้: