div
我想在用户编辑带有contenteditable
属性的内容时运行一个函数。什么相当于一个onchange
事件?
我正在使用 jQuery,因此任何使用 jQuery 的解决方案都是首选。谢谢!
div
我想在用户编辑带有contenteditable
属性的内容时运行一个函数。什么相当于一个onchange
事件?
我正在使用 jQuery,因此任何使用 jQuery 的解决方案都是首选。谢谢!
keydown
我建议将侦听器附加到由可编辑元素触发的关键事件,但您需要注意keypress
在内容本身更改之前触发事件。这不会涵盖更改内容的所有可能方式:用户还可以使用编辑或上下文浏览器菜单中的剪切、复制和粘贴,因此您可能也想处理cut
copy
和paste
事件。此外,用户可以删除文本或其他内容,因此那里有更多事件(mouseup
例如)。您可能希望轮询元素的内容作为后备。
2014 年 10 月 29 日更新
从长远来看,HTML5input
事件是答案。在撰写本文时,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/
这是一个更有效的版本,可on
用于所有 contenteditables。它基于此处的最佳答案。
$('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');
}
});
考虑使用MutationObserver。这些观察者旨在对 DOM 中的变化做出反应,并作为Mutation Events的高性能替代品。
优点:
缺点:
学到更多:
非 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);
});
我已经像这样修改了 lawwantsin 的答案,这对我有用。我使用 keyup 事件而不是 keypress,效果很好。
$('#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')});
两种选择:
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采用
开发将从这里继续:
为了避免计时器和“保存”按钮,您可以使用当元素失去焦点时触发的模糊事件。但要确保元素实际上已更改(不仅仅是聚焦和散焦),应将其内容与其上一个版本进行比较。或使用 keydown 事件在此元素上设置一些“脏”标志。
这是我最终使用的解决方案,效果非常好。我改用 $(this).text() 是因为我只使用了一个可编辑内容的单行 div。但是您也可以这样使用 .html() ,您不必担心全局/非全局变量的范围,并且之前实际上附加到编辑器 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 答案...
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'))
该元素现在可以由用户编辑,直到它失去焦点。
在角 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
}
}
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
}
});
您需要使用输入事件类型
演示
HTML
<div id="editor" contenteditable="true" >Some text here</div>
JS
const input = document.getElementById('editor');
input.addEventListener('input', updateValue);
function updateValue(e) {
console.log(e.target);
}
当具有 contentEditable 属性的元素发生更改时,不会触发 onchange 事件,建议的方法是添加一个按钮以“保存”版本。
检查以这种方式处理问题的插件:
在 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());
})
我构建了一个 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();
如果您愿意,您还可以删除/添加事件
对我来说,我想检查输入是否有效。
如果有效,则更新,否则显示错误消息并保持与以前相同的值。
技巧:当你编辑完成后,通常会触发模糊事件。
<span contenteditable="true">try input somethings.</span>
<script>
const elem = document.querySelector(`span`)
let oldValue = elem.innerText
elem.onkeydown = (keyboardEvent) => {
if (keyboardEvent.key === "Enter") {
elem.blur() // set focusout
}
}
elem.onblur = (e) => {
const curValue = elem.innerText
if (curValue === oldValue) {
return
}
if (curValue.length <= 50) { // Input your conditions.
// fail
elem.innerText = oldValue
// (Optional) Add error message
elem.insertAdjacentHTML("beforeend", `<span style="margin-left:5px;color:red">error length=${curValue.length}. Must greater than 50. undo to the previous value.</span>`)
const errMsg = elem.querySelector(`span`)
setTimeout(() => errMsg.remove(), 3500) // wait 3.5 second, and then remove it.
return
}
// OK, update
oldValue = curValue
}
</script>
看看这个想法。 http://pastie.org/1096892
我认为它很接近。HTML 5 确实需要将更改事件添加到规范中。唯一的问题是回调函数在 $(this).html() 中的内容实际更新之前评估 if (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>