14

Goal: Attach a keydown event handler to a contenteditable span that is the child of a contenteditable div.

Problem: If you type in the span the parent event is triggered not the childs. What I want is the child to trigger so I can grab the text. I only want THAT contenteditable child as there will be many.

HTML/JS is below and the fiddle link is here: http://jsfiddle.net/aBYpt/4/


HTML

<div class="parent" contenteditable="true">
    Parent div text.

    <span class="child" contenteditable="true">First child span text.</span>
    <span class="child" contenteditable="true">Second child span text.</span>
    <span class="child" contenteditable="true">Third child span text.</span>
</div>

<div id="console"></div>

JavaScript/jQuery

$(document).on( 'keyup', '.parent', function() {
    $('#console').html( 'Parent keyup event fired.' );
    //do stuff
});

$(document).on( 'keyup', '.child', function() {
    $('#console').html( 'Child keyup event fired.' );
    //do stuff
});

**Note: Event handling is delegated to document because elements are dynamically added.

Joshua Robinson
  • 3,430
  • 1
  • 27
  • 35
  • review this (may be what you're after): http://stackoverflow.com/questions/1164213/how-to-stop-event-bubbling-on-checkbox-click – Duncan Sep 12 '13 at 18:27
  • 2
    I just found this one which I think is more relevant: http://stackoverflow.com/questions/5072164/keypress-event-on-nested-content-editable-jquery , seems like a hack tho... I think this is a bug. – Joshua Robinson Sep 12 '13 at 18:32

1 Answers1

9

So this is a bug. Workaround confirmed for FF23 and CHROME29 (on linux with no vm so can't test IE). You must set the wrapping spans as contenteditable false, you can't just omit declaring the contenteditable attribute, which is rediculous. Solution via Keypress event on nested content editable (jQuery)

Here is the fiddle: http://jsfiddle.net/aBYpt/14/

HTML

<div class="parent" contenteditable="true">
    Parent div text.

    <span contenteditable="false">
        <span class="child" contenteditable="true">First child span text.</span>
    <span contenteditable="false">
        <span class="child" contenteditable="true">Second child span text.</span>
    </span>
</div>

<div id="console"></div>

JavaScript/jQuery

$(document).on( 'keyup', '.parent', function() {
    //do stuff
    $('#console').html( 'Parent keyup event fired.' );
});

$(document).on( 'keyup', '.child', function(e) {
    //do stuff
    $('#console').html( 'Child keyup event fired.' );
    e.stopPropagation();
});
Community
  • 1
  • 1
Joshua Robinson
  • 3,430
  • 1
  • 27
  • 35
  • 2
    I disagree that this is a bug: key events are only fired on elements capable of receiving the focus, which includes inputs and contenteditable elements. Elements within a contenteditable element don't qualify. You can infer the element containing the caret from the browser's selection object anyway. – Tim Down Sep 13 '13 at 09:28
  • 1
    It's not a non sequitur. I admit I didn't define my terms in great detail (like this [definition of "editing host"](https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#editing-host), which is what I was getting at), but I hoped my point was clear. Elements that can receive focus can fire key events. Elements that are inside a contenteditable element **without any elements with contenteditable="false"** in between cannot receive focus, therefore do not generate key events. – Tim Down Sep 13 '13 at 22:56
  • There is text selection issue with this answer. I could not select the parent and child text continuously. – Ankur Gupta Apr 13 '21 at 06:44