0

I am using jQuery to insert a DOM node after an element, which has a contenteditable parent. I'd like to focus the cursor on the inserted DOM node, but calling focus() on the inserted element doesn't seem to work. Here is what I tried.

// HTML
<div class="foo" contenteditable>
  <h1>Foo</h1>
</div>

// jQuery
$(document).on('keydown', '.foo', function(e){
  if (e.keyCode == 13) {
    var anchor = $( document.getSelection().anchorNode.parentElement ),
    var el = $("<p></p>");

    anchor.after(el);

    el.focus();
    e.preventDefault();
  }
});
Filburt
  • 17,626
  • 12
  • 64
  • 115
Chanpory
  • 3,015
  • 6
  • 37
  • 49
  • Hmmm, is there another way to move the cursor? On this site, they are able to move the cursor to generate a P tag when hitting enter, and then move the cursor to it. This overrides normal contenteditable behavior. http://daviferreira.github.io/medium-editor/ – Chanpory Feb 03 '14 at 08:31
  • You can change the cursor position itself: http://stackoverflow.com/questions/2388164/set-focus-on-div-contenteditable-element – CodingIntrigue Feb 03 '14 at 08:32

1 Answers1

3

You can't focus on an element within a contenteditable element, only the whole contenteditable element itself. Also, you have a false assumption: the anchorNode property of the selection is not guaranteed to be a text node. It could be an element.

If you want to move the cursor into an element, you'll need to create a range and add it to the selection (except in IE <= 8, which doesn't support either Range or Selection and has a different API):

var sel = window.getSelection();
var range = document.createRange();
range.selectNodeContents(el[0]); // Assuming el is a jQuery object
sel.removeAllRanges();
sel.addRange(range);

There are still issues with this: most browsers will not allow you to place the caret within an empty inline element, so you may need to do a nasty workaround like adding a zero-width space character inside your element and selecting that. See https://bugs.webkit.org/show_bug.cgi?id=15256, for example.

Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • Thank you, I'm sure exactly what you mean by the `anchorNode` assumption. Is there a better way to get the starting node? Also, I am trying `document.execCommand('formatBlock', false, 'p');` which seems to work on keyup, but still not great. – Chanpory Feb 03 '14 at 10:03
  • @Chanpory: I was assuming that since you're using `anchorNode.parentElement`, you're trying to get the container element of the selection anchor (which could be later in the document than the selection's `focusNode`, by the way). If `anchorNode` is an element, you probably don't want its parent. – Tim Down Feb 03 '14 at 21:22
  • Ah, you're correct. It looks like I'll need to place a conditional to test if the anchor node is a text node or not, unless there is another way. Thanks! – Chanpory Feb 06 '14 at 07:01