Search code examples
javascripthtmlcursor-position

Why is cursor not being positioned at end in FireFox only?


I am using some JavaScript to place cursor at end of text in editable paragraph and textarea elements.

A sample of my code in action can be seen at :Demo of my code

What I am finding strange is that in Chrome clicking on the button to set cursor position at end of textarea fails but in latest FireFox clicking on same button places cursor at start of textarea.

Question

What is wrong with the JavaScript code that its not behaving consistently across Chrome and FireFox?

The same demo code is as given below.

<button onclick="placeCursorAtEndofTextArea(); return false;">Place cursor at end of text area</button>

<button onclick="placeCursorAtEndofParagraph(); return false;">Place cursor at end of paragraph</button>

<br>
<br>
<textarea id="txtDescription" rows="10" cols="50">I am some text. I am some text. I am some text. I am some text.</textarea>

<br>
<br>
<p contentEditable>foo bar </p>

<style>
   p {
   border:1px solid green;
   }
   textarea {
   border: 1px solid red;
   }
</style>

<script>
   function placeCaretAtEnd(el) {
       el.focus();
       if (typeof window.getSelection != "undefined"
               && typeof document.createRange != "undefined") {
           var range = document.createRange();
           range.selectNodeContents(el);
           range.collapse(false);
           var sel = window.getSelection();
           sel.removeAllRanges();
           sel.addRange(range);
       } else if (typeof document.body.createTextRange != "undefined") {
           var textRange = document.body.createTextRange();
           textRange.moveToElementText(el);
           textRange.collapse(false);
           textRange.select();
       }
   }

   function placeCursorAtEndofTextArea() {
   placeCaretAtEnd( document.querySelector('#txtDescription'))
   }
   function placeCursorAtEndofParagraph() {
    placeCaretAtEnd( document.querySelector('p'))
   }

</script>

Solution

  • in short answer, it is because textarea and contentEditable use different selection model.

    I use this for modern browser and IE9+

    function placeCaretAtEnd(el) {
      if (el.value) {
        // for textarea
        el.focus();
        el.setSelectionRange(el.value.length, el.value.length);
      }
      else {
        // contentEditable
        range = document.createRange();
        range.selectNodeContents(el);
        range.collapse(false);
        selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);
      }
    }
    
    function placeCursorAtEndofTextArea() {
      placeCaretAtEnd(document.querySelector('#txtDescription'))
    }
    
    function placeCursorAtEndofParagraph() {
      placeCaretAtEnd(document.querySelector('p'))
    }
    p {border: 1px solid green;}
    textarea {border: 1px solid red;}
    textarea:focus::-webkit-input-placeholder{color: transparent;}
    textarea:focus::-webkit-textarea-placeholder {content: "";}
    <button onclick="placeCursorAtEndofTextArea(); return false;">Place cursor at end of text area</button>
    
    <button onclick="placeCursorAtEndofParagraph(); return false;">Place cursor at end of paragraph</button>
    
    <br><br>
    <textarea id="txtDescription" rows="10" cols="50">I am some text. I am some text. I am some text. I am some text.</textarea>
    
    <br><br>
    <p contentEditable>foo bar </p>