S.Andaur S.Andaur - 10 days ago 7x
jQuery Question

How to set the cursor in the child of a contentEditable element?

I want to know how to set the cursor in the child of an editable element. I have a content editable DIV with a SPAN inside and I want to set the cursor in the SPAN when the DIV is clicked to prevent someone typing in the DIV.

<div class="custom-input" spellcheck="true" contenteditable="true">
<span data-type="text">

I have tried to do this with .focus() in jQuery, and it works but it just highlights the SPAN and the cursor remains in the DIV.

I'm trying to make something like Facebook chat does. Facebook chat uses contenteditable elements for the chat input, and if you click anywhere in the chat box the cursor always is focused in a SPAN label that is used for the input.


I had to do this recently and the below is what I ended up with.

NOTE: This will not appear to work here or on jsFiddle due the sandboxing and whatnot. Run the code on your localhost or hosted server and you'll see it works.

  $(document).ready(function() {
    var $element = $('.type-here');
            createCaretPlacer($element, false); // set cursor and select text
            createCaretPlacer($element, true, true); // set cursor at start
            createCaretPlacer($element, true, false); // set cursor at end


  function createCaretPlacer($element, collapse, atStart) { 
    var el = $element[0]; // get the dom node of the given element
    el.focus(); // focus to the element
    // feature test to see which methods to use for given browser
    if (typeof window.getSelection != "undefined" && typeof document.createRange != "undefined") {
      // handle real browsers (not IE)
      var range = document.createRange(); // create a new range object
      range.selectNodeContents(el); // add the contents of the given element to the range
      if(collapse) range.collapse(atStart); // collapse the rage to either the first or last index based on "atStart" param
      var sel = window.getSelection(); // Returns a Selection object representing the range of text selected by the user or the current position of the caret.
      sel.removeAllRanges(); // removes all ranges from the selection, leaving the anchorNode and focusNode properties equal to null and leaving nothing selected.
      sel.addRange(range); // add the range we created to the selection effectively setting the cursor position 
    else if (typeof document.body.createTextRange != "undefined") {
      // handle IE 
      var textRange = document.body.createTextRange();
      if(collapse) textRange.collapse(atStart);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="custom-input" spellcheck="true" contenteditable="true">
  <span data-type="text" class="type-here">