Solution 1:

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>

Demo: http://jsfiddle.net/ch6yn/2691/

Solution 2:

Here is a more efficient version which uses on for all contenteditables. It's based off the top answers here.

$('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');
    }
});

The project is here: https://github.com/balupton/html5edit

Solution 3:

Consider using MutationObserver. These observers are designed to react to changes in the DOM, and as a performant replacement to Mutation Events.

Pros:

  • Fires when any change occurs, which is difficult to achieve by listening to key events as suggested by other answers. For example, all of these work well: drag & drop, italicizing, copy/cut/paste through context menu.
  • Designed with performance in mind.
  • Simple, straightforward code. It's a lot easier to understand and debug code that listens to one event rather than code that listens to 10 events.
  • Google has an excellent mutation summary library which makes using MutationObservers very easy.

Cons:

  • Requires a very recent version of Firefox (14.0+), Chrome (18+), or IE (11+).
  • New API to understand
  • Not a lot of information available yet on best practices or case studies

Learn more:

  • I wrote a little snippet to compare using MutationObserers to handling a variety of events. I used balupton's code since his answer has the most upvotes.
  • Mozilla has an excellent page on the API
  • Take a look at the MutationSummary library