17

I have a jQuery dialog for making links in a contentEditable span. The problem is that clicking a button to open the dialog causes the selection to be lost, text input inside the dialog also causes the selection to be lost.

I can fix the button with -moz-user-select:none; but -webkit-user-select:none doesn't work in Chrome.

I can fix the input by wrapping it in an iframe, but that's messy and clicking anywhere else also kills the selection, for example, dragging the dialog around.

I've seen the solution at How to preserve text selection when opening a jQuery dialog, but that doesn't work in many browsers in a contenteditable element, only real inputs.

Is there a nice solution to my problem?

Community
  • 1
  • 1
Jake
  • 12,713
  • 18
  • 66
  • 96

1 Answers1

42

You could save and restore the selection using simple functions such as the following when the dialog is opened and closed. I am not familiar enough with jQuery dialogs to know the mechanism for hooking into the dialog opening and closing. The first, saveSelection, returns you a Range or TextRange object that you should store in a variable which you later pass to restoreSelection:

function saveSelection() {
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            return sel.getRangeAt(0);
        }
    } else if (document.selection && document.selection.createRange) {
        return document.selection.createRange();
    }
    return null;
}

function restoreSelection(range) {
    if (range) {
        if (window.getSelection) {
            sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
        } else if (document.selection && range.select) {
            range.select();
        }
    }
}
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • 2
    How do we use these function in practice. On a div item let's say
    test test
    – Hussein Jan 14 '11 at 04:46
  • 6
    Thanks Tim. You are the range master! – Josiah Ruddell Oct 29 '11 at 05:09
  • I used the selectionChange event. See here http://stackoverflow.com/questions/21730134 I used Dart but you should get the idea. – Günter Zöchbauer Feb 12 '14 at 17:32
  • @GünterZöchbauer: That's certainly a more viable option than it was in 2010 because WebKit has since implemented the `selectionchange` event on contenteditable. Firefox still hasn't though: https://bugzilla.mozilla.org/show_bug.cgi?id=571294 – Tim Down Feb 12 '14 at 17:57
  • Have you found suitable events for this use case that work on more browsers? – Günter Zöchbauer Feb 12 '14 at 17:59
  • 2
    @GünterZöchbauer: No, but using `mousedown` instead of `click` on the button gets round the issue. – Tim Down Mar 31 '14 at 21:19
  • Thanks you so much – Sajan Jul 20 '17 at 15:05
  • @TimDown when I restore selection the focus is transferred back to the conteneditable div. So in my case the user is typing the color value in the color picker but as soon as the user types something the divs takes focus from the color input textbox which breaks functionality :( – supersan Apr 05 '19 at 07:02