Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maintain cursor position in contenteditable div [duplicate]

Tags:

javascript

dom

First of all, this is similar to these:

Editing Iframe Content in IE - problem in maintaining text selection

How to get caret position within contenteditable div with html child elements?

Basically, I'm writing something similar to the new tweet editor in twitter. Inside a div with contentEditable set on, I am parsing the text. When I detect what I think is a URL, I strip that text out and enter into an <a> tag inside the div (e.g. entered message of go to www.google.com becomes Go to <a href='..'>www.google.com</a>. BUT, the caret position is lost when I do that.

Using the suggestion by @Tim-Down in those other SO posts will only work as long as you don't edit the DOM (as he says). I AM editing the DOM, so the caret position is lost.

Is it possible (ideally without using the Rangy library referenced) to achieve this by working on the current code.

The code that I have at the moment (from the other SO posts):

var saveSelection, restoreSelection;
if (window.getSelection) {
    // IE 9 and non-IE
    saveSelection = function(win) {
        var sel = win.getSelection(), ranges = [];
        if (sel.rangeCount) {
            for (var i = 0, len = sel.rangeCount; i < len; ++i) {
                ranges.push(sel.getRangeAt(i));
            }
        }
        return ranges;
    };

    restoreSelection = function(win, savedSelection) {
        var sel = win.getSelection();
        sel.removeAllRanges();
        for (var i = 0, len = savedSelection.length; i < len; ++i) {
            sel.addRange(savedSelection[i]);
        }
    };
} else if (document.selection && document.selection.createRange) {
    // IE <= 8
    saveSelection = function(win) {
        var sel = win.document.selection;
        return (sel.type != "None") ? sel.createRange() : null;
    };

    restoreSelection = function(win, savedSelection) {
        if (savedSelection) {
            savedSelection.select();
        }
    };
}

And I use it like this:

$('div').on('keyup paste', function(e) {
    var ranges = saveSelection(window);
    var newContent = /* Get the new HTML content */;
    $('div').html(newContent);
    restoreSelection(window, ranges);
});
like image 619
Matt Roberts Avatar asked Apr 24 '13 14:04

Matt Roberts


1 Answers

If the text the user sees remains the same (which your question seems to imply is the case), you could use a character offset-based solution. I've posted some code for that elsewhere on Stack Overflow:

https://stackoverflow.com/a/13950376/96100

I also answered a related question quite recently:

jQuery: Convert text URL to link as typing

like image 127
Tim Down Avatar answered Oct 15 '22 16:10

Tim Down