2

Can someone please shed some light on this problem in Chrome? The removeChild() function makes the caret jump to the end of the div. Anyone got a workaround?

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
var caretX = 0

function keypress(event){
    insertAtCaret('<span id="caretpos"></span>');
    var caretpos = document.getElementById('caretpos')
    //caretX = getX(caretpos) //finds the X position of the element
    removeNode(caretpos)
    return(true)
}

//Functions used:
function insertAtCaret(text,replaceContents) {
    if(!text){return(false);}
    if(replaceContents==null){replaceContents=false;}
    if(!replaceContents){//collapse selection:
        var sel = document.getSelection()
        sel.collapseToStart()
    }
    return(document.execCommand('insertHTML', false, text))
}; 
function removeNode(el){
    el.parentNode.removeChild(el);
}
</script>
</head>

<body contentEditable="true" onkeypress="return(keypress(event))">
<div>Type some content somewhere here   &gt; &lt; and watch what happens in chrome</div>
</body>
</html>

Update: I'm actually trying to get the pixel location of the user's caret by inserting a dummy element, finding its position and then removing it. That said, the problem is a fundamental one in chrome, manipulating the DOM in this way causes the caret to jump to the end of the element

cronoklee
  • 6,482
  • 9
  • 52
  • 80
  • What do you actually want to do? – Tim Down Oct 12 '11 at 00:13
  • Sorry Tim I'm trying to get the pixel location of the user's caret by inserting a dummy element, finding its position and then removing it. That said, the problem is a fundamental one in chrome, manipulating the DOM in this way causes the caret to jump to the end of the element – cronoklee Oct 12 '11 at 00:24

1 Answers1

1

Exactly what should happen to the caret after calling document.execCommand('insertHTML') is undefined, but I agree that Chrome's behaviour is unhelpful. You could get round it by using the insertNode() method of Range to add your dummy element:

var sel = window.getSelection();
sel.collapseToStart();
var span = document.createElement("span");
var range = sel.getRangeAt(0);
range.insertNode(span);

// Get the position here...

span.parentNode.removeChild(span);

An alternative approach to the whole thing is to use Range's getBoundingClientRect() method in browsers that support it. See my answer here:

Coordinates of selected text in browser page

Finally, I've been writing a module to do this for my Rangy library. It's not quite finisihed but there's a demo here: http://rangy.googlecode.com/svn/trunk/demos/position.html

Community
  • 1
  • 1
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • This is sweet! Thanks a lot Tim. Rangy looks brilliant too! I'm rewriting my insertAtCaret function using the createElement approach you detailed here. Can you let me know how to remove the selected text before inserting the new node? – cronoklee Oct 12 '11 at 12:26
  • Do you mean removing the selected text from the document? `sel.deleteFromDocument()` if so. By the way, if you need to suport IE < 9, you'll need a different approach for all of this since those browsers don't support `Range` or `Selection`. – Tim Down Oct 12 '11 at 13:54
  • Yes exactly. I cant get deleteFromDocument() to work tho: http://collabedit.com/4phyt. Am I doing something wrong? – cronoklee Oct 12 '11 at 14:54
  • @cronoklee: `replaceContents` is undefined, therefore `sel.deleteFromDocument()` never runs. – Tim Down Oct 12 '11 at 15:12
  • Oops - Yes just spotted the typo in the setTimeout code! Thanks a lot for the help Tim - Really useful stuff I will surely use again. – cronoklee Oct 12 '11 at 15:22