3

I want to attach keypress and focusout event handlers to a paragraph inside contenteditable div.

The following code doesn't seem to work:

<div contenteditable="true">
    <p id="p1">Test</p>
    <p id="p2">Test</p>
    <p id="p3">Test</p>
</div>

$('#p1').bind('keypress', function(e) {
    alert('keypress');
});

$('#p1').focusout(function(e) {
    alert('focusout');
});

JSFiddle

Regent
  • 5,142
  • 3
  • 21
  • 35
Coder
  • 3,090
  • 8
  • 49
  • 85
  • yes, Regent beat me to it! Here's the updated fiddle http://jsfiddle.net/2r8qy7bL/ – gts101 Oct 14 '14 at 05:54
  • I want to attach event to paragraph and not to div. There will be multiple paragraph and I want to monitor changes in paragraph with id p1 – Coder Oct 14 '14 at 06:01
  • 1
    @mundella you can want it, but due to `contenteditable="true"` you won't be able to do this. Use several `
    Test
    ` instead.
    – Regent Oct 14 '14 at 06:09
  • 1
    @Regent next time dont hurry to put the solution. "you won't be able to do this" these words do not belong to stackoverflow :) – Coder Oct 14 '14 at 06:21
  • @mundella once again: you can't make _keypress and focusout event handlers to a paragraph inside contenteditable div_ to work. The solution with range, that Roko C. Buljan has suggested, works with event handler, binded to `
    ` (_basically the contenteditable is the one that will respond to events_), not to `

    `. This is all about formulation of your question.

    – Regent Oct 14 '14 at 06:31
  • Exactly..so shifting ids is not a solution dude! – Coder Oct 14 '14 at 06:33
  • @mundella you can check [this](http://stackoverflow.com/questions/5072164/keypress-event-on-nested-content-editable-jquery) for solution – chanchal Oct 14 '14 at 09:33

4 Answers4

4

Basically the contenteditable is the one that will respond to events dispatched from the inner Nodes. If we get the caret position and than target it's range's parentNode - than we can retrieve the desired ID

$('[contenteditable]').on('keypress focusout', function(ev) {
  var node = window.getSelection().getRangeAt(0).commonAncestorContainer;
  var nodeParent = node.parentNode;
  
  // Do something if parent node ID is "p1"
  if( nodeParent.id === "p1") {
    console.log( nodeParent.id +' '+ ev.type ); // or whatever you need to do here
  }
});
<div contenteditable="true">
   <p id="p1">TestP1 do someting on keypress</p>
   <p id="p2">TestP2 is Not Interesting</p>
</div>

<script src="//code.jquery.com/jquery-3.1.0.js"></script>
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
  • perfect..except the typo in `console`. Tested in chrome and serves my purpose. JSFiddle http://jsfiddle.net/THPmr/183/ – Coder Oct 14 '14 at 06:16
  • great solution! better than many similar, existing and highly upvoted one's in SO!! – neophyte Jul 14 '17 at 12:19
1

There's an answer over here: https://stackoverflow.com/a/18772205/2100255

Basically, you need to wrap your inner contenteditables with non-contenteditables. The event fires off the node which declares contenteditable=true.

Community
  • 1
  • 1
-2

I have altered the solution, Refer the latest fiddle

$(document).on('keypress', '#p1[contenteditable="true"]', function(e) {
   alert("test");
});
Manoj Namodurai
  • 529
  • 2
  • 7
  • http://jsfiddle.net/THPmr/173/ Any way probably the OP wants to target exactly and only that poor `#p1` that's inside the contenteditable DIV – Roko C. Buljan Oct 14 '14 at 05:58
  • 1
    I want to attach event to paragraph and not to div. There will be multiple paragraph and I want to monitor changes in paragraph with id p1 – Coder Oct 14 '14 at 06:00
  • 1
    @mundella you didn't mention it from the beginning, and now this answer gets downvotes. It's not good at all. – Regent Oct 14 '14 at 06:07
  • It was very clear what I wanted to achieve as the id was always on paragraph. Shifting the ids is not a solution. – Coder Oct 14 '14 at 06:09
  • @mundella - No, you have appended the additional

    tags in the recent edit. Anyhow I will try to resolve this.

    – Manoj Namodurai Oct 14 '14 at 06:11
  • @ManoNamo with moving `contenteditable="true"` to `

    ` you can stay JS code "as is", without this way to add event handler (`$(document).on('keypress', '#p1[contenteditable="true"]',`).

    – Regent Oct 14 '14 at 06:19
-2

You can do it as below Instead of click event you can change it to event on which you want to track the change.I am using click for example

$("div").click(function(e){
    console.log($("#"+$(e.target)[0].id).text());
});
Sumeet
  • 27
  • 1
  • 5