contenteditable change events
2022 update
As pointed out in the comments, this doesn't answer the question asked, which wanted the equivalent of the change
event rather than the input
event. However, I'll leave it here as is.
Original answer
I'd suggest attaching listeners to key events fired by the editable element, though you need to be aware that keydown
and keypress
events are fired before the content itself is changed. This won't cover every possible means of changing the content: the user can also use cut, copy and paste from the Edit or context browser menus, so you may want to handle the cut
copy
and paste
events too. Also, the user can drop text or other content, so there are more events there (mouseup
, for example). You may want to poll the element's contents as a fallback.
UPDATE 29 October 2014
The HTML5 input
event is the answer in the long term. At the time of writing, it is supported for contenteditable
elements in current Mozilla (from Firefox 14) and WebKit/Blink browsers, but not IE.
Demo:
document.getElementById("editor").addEventListener("input", function() {
console.log("input event fired");
}, false);
<div contenteditable="true" id="editor">Please type something in here</div>
trigger an event when contenteditable is changed
Just store the contents to a variable and check if it is different after blur()
event. If it is different, store the new contents.
var contents = $('.changeable').html();
$('.changeable').blur(function() {
if (contents!=$(this).html()){
alert('Handler for .change() called.');
contents = $(this).html();
}
});
example: http://jsfiddle.net/niklasvh/a4QNB/
Listening to events of a contenteditable HTML element
Not really. There is no change
event for contenteditable
elements, and there's no HTML5 input
event either, although I think that will eventually appear. It's a pain.
UPDATE 23 June 2012
Recent WebKit supports the HTML5 input
event on contenteditable
elements, as does Firefox 14.
focus
, however, does work, as does DOMCharacterDataModified
in most browsers (though notably not IE < 9). See http://jsfiddle.net/UuYQH/112/
By the way, contenteditable
is not a Boolean attribute: it requires a value, which should be one of "true", "false", "inherit" and the empty string (which is equivalent to "true").
Angular and contenteditable
You can use the input
event, like so:
<div contenteditable (input)="onNameChange($event.target.innerHTML)">
Type your name
</div>
Here is a Stackblitz demo
How to trigger an event when there is selection inside a contentEditable div?
A relatively simplified version could look like this, depending on your needs you might need to handle browsers like old IE's etc. that do not support window.getSelection()
!
const handleSelection = function() { const btn = document.querySelector('#btn'); let selection = window.getSelection().anchorNode.textContent .substring( window.getSelection().extentOffset, window.getSelection().anchorOffset );
if (selection.length !== 0) { btn.setAttribute('disabled', true); } else { btn.removeAttribute('disabled'); }};
['mouseup', 'keyup', 'selectionchange'].forEach((e) => { document.querySelector('#editable').addEventListener(e, handleSelection);});
#btn[disabled] { cursor: default; opacity: 0.3;}
<button type="button" id="btn">Button (disabled when something is selected)</button><div id="editable" contenteditable> <p>I'm some content that is editable!</p></div>
onChange event with contenteditable
The function that I wrote:
One call of this function fixes all ContentEditable elements in the page.
function fix_onChange_editable_elements()
{
var tags = document.querySelectorAll('[contenteditable=true][onChange]');//(requires FF 3.1+, Safari 3.1+, IE8+)
for (var i=tags.length-1; i>=0; i--) if (typeof(tags[i].onblur)!='function')
{
tags[i].onfocus = function()
{
this.data_orig=this.innerHTML;
};
tags[i].onblur = function()
{
if (this.innerHTML != this.data_orig)
this.onchange();
delete this.data_orig;
};
}
}
Angular contenteditable change event not fired
The change
event does not fire on all changes to the value of the DOM element. The solution is to use the input
event.
element.on('input', function() {
scope.$evalAsync(read);
});
change
Unlike the input event, the change event is not necessarily fired for each change to an element's value.
--Mozilla Developer Network -- Events -- Change
input
The DOM input event is fired synchronously when the value of an
<input>
or<textarea>
element is changed. Additionally, it fires on contenteditable editors when its contents are changed. In this case, the event target is the editing host element. If there are two or more elements which have contenteditable as true, "editing host" is the nearest ancestor element whose parent isn't editable.
--Mozilla Developer Network -- Events -- Input
user events related to contenteditable
The exhaustive list of events on contenteditable elements is the same as for input type=text. See this list of all events (look especially at Form Events): http://www.w3schools.com/tags/ref_eventattributes.asp
"How should I code in Javascript to reject some user action?"... just put "event.preventDefault()" at the beginning of an event listener for the event of that action. Example to reject keypresses:
contenteditableElement.addEventListener('keypress', function (e) {
e.preventDefault();
// do something else, maybe...
});
To undo a user's action:
document.execCommand('undo', false, '');
As to designing rich text editors, there are many good demos available. I recommend:
https://developer.mozilla.org/en-US/docs/Rich-Text_Editing_in_Mozilla
http://www.quirksmode.org/dom/execCommand/
Make sure to view source of the last link; especially the buttons.js file. Also check out the amazing commands list on the MDN article. Good luck -- but try not to re-invent the wheel. There are many well-tested editors out there; check out this list: http://www.webdesignerdepot.com/2008/12/20-excellent-free-rich-text-editors/
React.js: onChange event for contentEditable
Edit: See Sebastien Lorber's answer which fixes a bug in my implementation.
Use the onInput event, and optionally onBlur as a fallback. You might want to save the previous contents to prevent sending extra events.
I'd personally have this as my render function.
var handleChange = function(event){
this.setState({html: event.target.value});
}.bind(this);
return (<ContentEditable html={this.state.html} onChange={handleChange} />);
jsbin
Which uses this simple wrapper around contentEditable.
var ContentEditable = React.createClass({
render: function(){
return <div
onInput={this.emitChange}
onBlur={this.emitChange}
contentEditable
dangerouslySetInnerHTML={{__html: this.props.html}}></div>;
},
shouldComponentUpdate: function(nextProps){
return nextProps.html !== this.getDOMNode().innerHTML;
},
emitChange: function(){
var html = this.getDOMNode().innerHTML;
if (this.props.onChange && html !== this.lastHtml) {
this.props.onChange({
target: {
value: html
}
});
}
this.lastHtml = html;
}
});
Related Topics
Execute PHP Function With Onclick
JavaScript Code to Stop Form Submission
How to Create a ≪Style≫ Tag With JavaScript
Custom Attributes - Yea or Nay
Google Maps API V3: How to Remove All Markers
Insert HTML With React Variable Statements (Jsx)
Jquery Load() Only Working in Firefox
Innertext VS Innerhtml VS Label VS Text VS Textcontent VS Outertext
Jquery Click Not Working For Dynamically Created Items
How to Force a Script Reload and Re-Execute
Load More Posts Ajax Button in Wordpress
How to Make JavaScript Execute After Page Load
How to Read CSS Rule Values With JavaScript
How to Specify a Suggested Filename When Using Data: Uri
Make Header and Footer Files to Be Included in Multiple HTML Pages
Fastest Method to Escape HTML Tags as HTML Entities