...

View Full Version : Saving/restoring caret position in a contentEditable div



encoded
02-02-2005, 06:32 PM
Hello everybody, this is my first post here :)

Ok, this is what I'm trying to do:

I have a contentEditable element, and am using setTimeout() to call a function which changes the innerHTML of the div. Problem is that changing innerHTML moves the caret to the end of the text.

I need to keep the caret pos so the user can keep typing. I tried storing the caret pos with
cursorPos=document.selection.createRange().duplicate();

And then later restoring it with cursorPos.select() - which is IE only, but it doesn't work because the content of the div gets changed between calls, and the behavior is undefined (it basically selects everything)

Any ideas?

codegoboom
02-02-2005, 06:51 PM
Posting the relevant sections of code may enable other's to have a clearer picture of the problem... :)

encoded
02-02-2005, 07:06 PM
<script>
var xmlhttp=false;
/*@cc_on @*/
/*@if (@_jscript_version >= 5)
// JScript gives us Conditional compilation, we can cope with old IE versions.
// and security blocked creation of the objects.
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
xmlhttp = false;
}
}
@end @*/
if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
xmlhttp = new XMLHttpRequest();
}

var cursorPos;

var secs
var timerID = null
var timerRunning = false
var delay = 1000

function InitializeTimer()
{
// Set the length of the timer, in seconds
secs = 2
StopTheClock()
StartTheTimer()
}

function StopTheClock()
{
if(timerRunning)
clearTimeout(timerID)
timerRunning = false
}


function StartTheTimer()
{
if (secs==0)
{
StopTheClock()
xmlhttp.open("POST", "callback_asutype.aspx",true);
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4) {
//alert(xmlhttp.responseText);
document.getElementById('_ctl0').innerHTML = xmlhttp.responseText;

// THIS DOESN'T WORK RIGHT
cursorPos.select();
}
}
// THIS DOESN'T WORK RIGHT
cursorPos=document.selection.createRange().duplicate();

xmlhttp.send(document.getElementById('_ctl0').innerText);

}
else
{
document.getElementById('spellTime').innerText = 'Spell checking in: ' + secs + ' seconds'
secs = secs - 1
timerRunning = true
timerID = self.setTimeout('StartTheTimer()', delay)
}
}
</script>


This is the code.. it is used for real-time spell checking (as you type) - like in MS Word.

'_ctl0' is the editable span.

What callback_asutype.aspx does is parse the text and return a formatted HTML string with underlines for words, etc.

codegoboom
02-02-2005, 07:14 PM
Would you care to break that down to an example containing relevant sections of code: just the necessary script and markup (as if you were demonstrating only the problem areas...)?

encoded
02-02-2005, 07:21 PM
Well, all the magic happens in the StartTimer() function, note the // THIS DOESN'T WORK RIGHT comments :)

codegoboom
02-02-2005, 07:25 PM
Yeah, I noticed, but... well, perhaps someone will be kind enough to pick it apart and construct a test from there; you never know. ;)

encoded
02-02-2005, 08:47 PM
It's not really something that needs testing for this specific case. The problem is that there's no way of saving and restoring the current cursor position in a contenteditable element if you change its content between the calls to save and restore.

What I'm looking for is a workaround.

encoded
02-02-2005, 09:05 PM
So you get a better idea of what I'm trying to do, here's a demo:

http://www.softcontest.com/sharpspell/asutype.aspx

Type something in the div, and wait for it to be spell checked. The cursor position will be moved at the end of the text, I need it to stay where it was.

encoded
02-03-2005, 01:07 PM
Ok, I managed to work around it, here's the solution if anyone's interested:

Store the selection x, y:


cursorPos=document.selection.createRange().duplicate();
clickx = cursorPos.getBoundingClientRect().left;
clicky = cursorPos.getBoundingClientRect().top;

Restore the selection:


cursorPos = document.body.createTextRange();
cursorPos.moveToPoint(clickx, clicky);
cursorPos.select();

You can see it working here:

http://www.tachyon-labs.com/sharpspell/ (click on the "BETA! Spell as you type..." button)

Now, I'm not sure if this works in anything other than IE right now, can anyone suggest a fix for Firefox?

Brandoe85
02-03-2005, 01:10 PM
[edit]My bad, I didnt click the beta spell as you type button, I clicked the other one :p Doesn't work in IE Or firefox for me...in IE throws and object doesn't support this property or method...line 65

encoded
02-03-2005, 04:04 PM
That's odd, line 65 in the document should be the xmlhttp.open() method.

What version of IE have you got? It seems you don't have the XMLHttp component. I tested on some other computers and it did work...

Brandoe85
02-03-2005, 04:08 PM
Ah, that might be it, i'm using IE6

encoded
02-03-2005, 05:04 PM
Well, you should have it... it's not a custom component, it should be there on your system.... very odd :confused:



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum