Set focus on div contenteditable element

JqueryFocusContenteditable

Jquery Problem Overview


I have a <div contenteditable=true> where I define by a WYSIWYG some elements. For example <p>,<h1>, etc. I would like to directly put the focus on one of these elements.

For example on <p id="p_test">. But it seems that focus() function doesn't work on <div> elements, <p> elements...

Is there another means to define the focus in my case?

Jquery Solutions


Solution 1 - Jquery

Old post but none of the solutions worked for me. I figured it out eventually though:

var div = document.getElementById('contenteditablediv');
setTimeout(function() {
    div.focus();
}, 0);

Solution 2 - Jquery

In modern browsers you can use:

var p = document.getElementById('contentEditableElementId'),
    s = window.getSelection(),
    r = document.createRange();
r.setStart(p, 0);
r.setEnd(p, 0);
s.removeAllRanges();
s.addRange(r);

But if your element is empty I got some strange problems so for empty elements you can do this:

var p = document.getElementById('contentEditableElementId'),
    s = window.getSelection(),
    r = document.createRange();
p.innerHTML = '\u00a0';
r.selectNodeContents(p);
s.removeAllRanges();
s.addRange(r);
document.execCommand('delete', false, null);

After deleting nbsp cursor stays inside p element

P.S. just ordinary space doesn't work for me

Solution 3 - Jquery

I noticed that jQuery focus() did not work for my contenteditable DIV with width and height of 0. I replaced it with .get(0).focus() - the native javascript focus method - and it works.

Solution 4 - Jquery

A lot of the time if you can't call .focus() on an element, it's because the tabIndex is -1, which means the tab key can't focus on it when you're pressing tab to navigate.

Changing your tabIndex to >= 0 will let you focus on the elements. If you need to do it dynamically, you can just add a tabindex >= 0 to your element in the event listener.

Solution 5 - Jquery

You can try this code, it can auto focus in your last insert location.

let p = document.getElementById('contenteditablediv')
let s = window.getSelection()
let r = document.createRange()
r.setStart(p, p.childElementCount)
r.setEnd(p, p.childElementCount)
s.removeAllRanges()
s.addRange(r)

Solution 6 - Jquery

To build further on @Surmon answer. If you are looking to auto focus right after your last letter/number in the text instead of the last insertion location (last insertion location will move the cursor to a new line if the child nodes are enclosed in block type tags and not plain text) then apply this small modification:

r.setStart(p.lastChild, 1);
r.setEnd(p.lastChild, 1);

This is an extended function that checks if the editor/element has any child nodes and depending on the situation sets the cursor accordingly at the end:

let p = document.getElementById('contenteditablediv');
p.focus();  // alternatively use setTimeout(() => { p.focus(); }, 0);
// this is enough to focus an empty element (at least in Chrome)

if (p.hasChildNodes()) {  // if the element is not empty
  let s = window.getSelection();
  let r = document.createRange();
  let e = p.childElementCount > 0 ? p.lastChild : p;  
  r.setStart(e, 1); 
  r.setEnd(e, 1);    
  s.removeAllRanges();
  s.addRange(r);
} 

Solution 7 - Jquery

One more thing to check: If you have the browser's console window open, make sure the console does not have focus when you load the page, or else the element on the page won't get focus as expected.

This also seems to imply that you can't run document.querySelector('#your-elem').focus() in the console (tried with Chrome, Safari and Firefox on a Mac, Aug 2020).

Solution 8 - Jquery

In case someone, who uses MediumEditor that manages contenteditable element, stumbles upon this issue, the following has worked for me:

editor.selectElement(editorDOMNode);
  1. editor is an instance of MediumEditor.

  2. editorDOMNode is a reference to the actual contenteditable DOM node.

  3. It is also possible to focus on a specific child node within the editor as follows:

     editor.selectElement(editorDOMNode.childNodes[0]);
    

Solution 9 - Jquery

Bind a "click" event handler to all elements within the contenteditable div, and change the class/style on click (i.e. add class "focused" to the element);

You can identify, to the user, which element has focus by adding style such as a colorful border or an inner box-shadow. Then when you want to access the focused element in your jQuery script, just do something like this:

var focused = $('.focused');

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionsanceray3View Question on Stackoverflow
Solution 1 - Jquerychris97ongView Answer on Stackoverflow
Solution 2 - JqueryDima VidmichView Answer on Stackoverflow
Solution 3 - JqueryVladView Answer on Stackoverflow
Solution 4 - JquerywafsView Answer on Stackoverflow
Solution 5 - JquerySurmonView Answer on Stackoverflow
Solution 6 - JqueryM.CalugaruView Answer on Stackoverflow
Solution 7 - JqueryJouni KananenView Answer on Stackoverflow
Solution 8 - JqueryEyeView Answer on Stackoverflow
Solution 9 - JqueryBrian P JohnsonView Answer on Stackoverflow