2

I've seen a lot of code snippets detailing how to get and set the caret position within a contenteditable div but I cannot get it to work in my case:

I am using a WYSIWYG text editor (textAngular). I have included functionality for the user to insert a cross-reference at the cursor position. They click a button, which opens up a dialog box for them to make selections from, which in turn will insert a html node at the current cursor position.

The location of the cursor may be within child nodes within the div such as p tags and/or other formatting tags.

My issue is that the current cursor position is lost when the dialog gains focus. I have tried storing the caret position (node and offset) in memory before opening the dialog but whatever I try the caret position always returns to the start of the div. I've tried all the code snippets I can find on stackoverflow but none of them work. I assume I am missing something.

Nigel
  • 2,150
  • 3
  • 20
  • 22
  • I can see this has already been down-voted. It's very possible the question may not be clear to people or I may have missed something obvious, so if this is the case, please leave a comment here and I will correct it. If you feel this question has already been answered then please direct me to the answer and I will remove this question. Simply down-voting it without a reason is just unhelpful. – Nigel Jan 26 '15 at 12:02

2 Answers2

0

EDIT: On second thoughts, your issue is probably that when you click the button the content editable looses focus and hence the selection is lost. We handle this as so in textAngular: toolElement.attr('unselectable', 'on');

Best solution for this is to use rangy instead of roll-your-own (required in textAngular ^1.3.0).

You've probably been down voted due to this being very similar to SO questions about "save and restore" caret position in content-editables e.g. Saving and Restoring caret position for contentEditable div

In the case of textAngular we've dealt with this issue multiple times and we have some shortcuts and helpers built into the TA (textAngular) toolbar tools. Have a look at any of the issues here: https://github.com/fraywing/textAngular/search?q=modal&type=Issues

If you have TA specific questions it's often best to look through the 500+ issues on the github repository. Chances are something similar has been attempted before.

Community
  • 1
  • 1
Simeon Cheeseman
  • 1,748
  • 1
  • 13
  • 24
0

From this answer: Saving and Restoring caret position for contentEditable div

Modified to your use case. When the combo ctrl + i is pressed a popup appears. You interact with the popup and press the close button, and then the cursor position is returned to it's original.

Without any other code this is what I had to go on.
I used jquery to make coding the example less verbose, but this also works without jquery.

  function getRestorePosition(context) {
      var selection = window.getSelection();
      var range = selection.getRangeAt(0);
      range.setStart(  context, 0 );
      var len = range.toString().length;
      
      return function restore(){
          var pos = getTextNodeAtPosition(context, len);
          selection.removeAllRanges();
          var range = new Range();
          range.setStart(pos.node, pos.position);
          selection.addRange(range);

      }
  }
  function getTextNodeAtPosition(root, index){
      var lastNode = null;

      var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT,function next(elem) {
          if(index > elem.textContent.length){
              index -= elem.textContent.length;
              lastNode = elem;
              return NodeFilter.FILTER_REJECT
          }
          return NodeFilter.FILTER_ACCEPT;
      });
      var c = treeWalker.nextNode();
      return {
          node: c ? c: root,
          position: c? index:  0
      };
  }
  $('[contenteditable="true"]').on('keydown',function(e) {
     if(e.ctrlKey && e.which == 73) {
        
        var popup = $('#popup');
        var restore = getRestorePosition(e.target);
        popup.show();
        popup.find('button').one('click',function() {
           popup.hide();
           restore();
        });
        e.preventDefault();
        return false;
     }
  });
#popup {
   position:absolute;
   background-color:rgba(100,100,100,0.8);
   left:0px;
   right:0px;
   bottom:0px;
   top:0px;
   display:none;
   color:white;
   text-align:center;
   padding:0px;200px;
   font-size:3em;
}
[contenteditable="true"] {
  border:1px solid gray;
  padding:20px;
  font-size:2em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div contenteditable="true">
   How much wood could a woodchuck chuck if a woodchuck could chuck wood
</div>
<div id="popup">
   A wood chuck could chuck as much wood as a woodchuck could chuck!<BR/>
   <button>close</button>
</div>
Tschallacka
  • 27,901
  • 14
  • 88
  • 133