3

I am having this problem. I am inserting input elements in a contenteditable div. The caret is in the input at the last position. I would like some help how to move the cursor right after that input by executing some function. You will see in my code that I have to click (justInserted.click()) to make some resizing happen. If I remove the justInserted.focus() then the caret is always at the start of the contenteditable. I would like to have a function that finds that the caret is in a specific input in the contenteditable and when I call it, it will put the caret right after that specific input. Any help is appreciated :)

My insert at caret looks like this:

this.insertNodeAtCursor = function(node) {

            var sel, range, html;

            function containerIsEditable(selection) {
                return $(selection.anchorNode).parent().hasClass("editable");
            }

            if (window.getSelection) {
                sel = window.getSelection();
                // only if it is a caret otherwise it inserts
                // anywhere!
                if (containerIsEditable(sel) && sel.getRangeAt
                        && sel.rangeCount) {
                    var previousPosition = sel.getRangeAt(0).startOffset;
                    sel.getRangeAt(0).insertNode(node);
                }
            } 
            else if (document.selection
                    && document.selection.createRange) {
                range = document.selection.createRange();
                html = (node.nodeType == 3) ? node.data
                        : node.outerHTML;
                range.pasteHTML(html);  

            }

        };

and the function that adds the input is this:

this.addInput = function(suggestEntry, query) {

            var id = suggestEntry.id;
            var nodeClass = suggestEntry.nodeClass;
            var uuid = suggestEntry.uuid;
            var clause = null;
            if (nodeClass === "Entity"){
                clause = new Entity();
                clause.uuid = uuid;
                clause.id = id;
                clause.text = suggestEntry.text;
            }

            var input = clause.toEditorElementHtml();
            this.insertNodeAtCursor(input);
            var rand = Math.floor((Math.random() * 1000000) + 1);
            input.setAttribute('id', "rand-" + rand);

            $rootScope.$broadcast("remove:query",query);
            var autoSizingInputs = $('input[autosize="autosize"]');
            var justInserted = $('#rand-' + rand);
            $compile(autoSizingInputs)($scope);
            justInserted.focus();
            justInserted.click(); // a bit hacky :/
            $(justInserted).val($(justInserted).val() + "");

        };
Michail Michailidis
  • 11,792
  • 6
  • 63
  • 106
  • 1
    hmm.. i haven't tested but i found some useful looking links like: http://stackoverflow.com/questions/21881509/how-to-set-cursor-position-at-the-end-of-input-text-in-google-chrome and http://stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area I'm not sure whether those links are useful in this case but Good luck anyway! – jyrkim Jan 25 '16 at 14:59
  • Well the first one puts the cursor at the end of the input.. not right after an input.. The second suggestion needs to know the position which works well with plain text but not when html elements are involved like inputs.. – Michail Michailidis Jan 25 '16 at 15:24
  • A guess, but try setting the value before setting focus )) – tnt-rox Jan 26 '16 at 10:27

1 Answers1

2

Here's a snippet with a function that moves the caret right after the focused input. I've tested it in Chrome Version 47.0.2526.111 m, Firefox 43.0.4 and IE 11.

function setCaretAfterFocusedInput(container) {    
  var input = container.querySelector('input:focus');
  if (input) {
    container.focus(); // required for firefox
    setCaretAfter(input);
  }
}

function setCaretAfter(element) {
  if (window.getSelection) {            
    var range = document.createRange();
    range.setStartAfter(element);
    
    var selection = window.getSelection();
    selection.removeAllRanges();
    selection.addRange(range);
  }
}

// for demonstration purposes
document.addEventListener('keyup', function(e) {
  if (e.which === 16) { // on SHIFT
    var container = document.querySelector('div[contenteditable]');
    setCaretAfterFocusedInput(container);
  }
});
<p>When an input is focused, press shift to move the caret right after the input.</p>

<div contenteditable>
  <input type="text" value="input1"><input type="text" value="no whitespace before this">
  <br><br>some text<input type="text" value="input3">more text
  
  <br><br>
  <input type="text"><p>text in a paragraph, no whitespace before this</p>
  
  <input type="text">
  <p>text in a paragraph</p>
</div>
ekuusela
  • 5,034
  • 1
  • 25
  • 43
  • nice job :). I assume it is possible to not use Jquery at all right (using ```document.querySelector("div[contenteditable] input:focus");```? I am trying to drop it as a dependency.. Thanks! – Michail Michailidis Jan 27 '16 at 23:30
  • 1
    @MichailMichailidis, I've edited my answer to have no jquery dependency – ekuusela Jan 28 '16 at 07:19