2

can somebody please guide me the proper way if this is possible? I was actually trying to make a text editor using iframe with designMode='on'. The buttons in the editing bar are made up of divs where the actions are being triggered by an onclick event which then utilize the execCommand function. I made the whole thing work perfectly in Firefox and other browsers except for IE. I figured that the main reason for this is the inability of IE to maintain focus and keep the range selection to the text inside iframe. This happens everytime I click the buttons to manipulate the texts. My question is, how can I prevent this from happening? I believe using the <a href="javascript:functionHere()"> method could partially solve the problem but it is only limited to a single click command like bold, italic, etc. where no further clicking is involed like clicking another text field to add link or image which causes the selection of the subject text to disappear. Please tell me if you know.

Update: A simplified version of my code can be found here: http://pastebin.com/XrZ4duCb

You can copy and test it.

I'll try your solution now. Thanks for the replies.

Update: Managed to fix the codes using different method. However, some bugs can still be observed. Check here: http://pastebin.com/qP8sYUH7

Thanks.

blackstrider
  • 33
  • 1
  • 6

3 Answers3

4

If you're not changing the editor frame's DOM between it losing and regaining focus then the following functions will do: call saveSelection(iframeWindow) before the editor document loses focus and restoreSelection(iframeWindow, sel) after it regains focus. Otherwise, I'd suggest using my Rangy library's save/restore selection module, which uses hidden marker elements.

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();
        }
    };
}
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • I'll try this one and return back for update. Thanks for sharing. – blackstrider Apr 24 '11 at 15:20
  • @pagewil: It's just the same really, but I'll amend my answer on your question. – Tim Down May 10 '11 at 23:21
  • +1 for suggesting (and writing!) Rangy. I find it very useful for stabilising the different browser range implementations. – Jason May 28 '12 at 09:44
  • @TimDown This is great. I AM editing the DOM a little in my case, is this bendable to my needs (http://stackoverflow.com/questions/16194364/maintain-cursor-position-in-contenteditable-div) – Matt Roberts Apr 24 '13 at 14:17
  • @MattRoberts: Not really. Ranges are touchy and try to update themselves when the DOM changes. I answered your question with a different approach. – Tim Down Apr 24 '13 at 16:21
1

In IE9 I fixed this problem by adding property unselectable="on" for all div-buttons.

<div onclick="onBold()" unselectable="on">Bold</div>
SasHok.Tk
  • 477
  • 5
  • 3
0

You mean your buttons are inside the iframe? If they are, just try to take them out.

If not, you should try something like:

I've done something like that for one of my projects but it was long ago so I might have forgotten something. It would be nice of you could upload your code on pastebin or something so that we can tackle the problem directly.

xavierm02
  • 8,457
  • 1
  • 20
  • 24
  • `pasteHTML` is IE-only. The approach you describe is pretty much exactly what I implemented in Rangy's selection save/restore module: http://code.google.com/p/rangy/wiki/SelectionSaveRestoreModule – Tim Down Apr 24 '11 at 11:11
  • The problem is IE-only :-° (and every property or method I use but 2 are IE-only) – xavierm02 Apr 24 '11 at 14:47
  • I tried that solution of refocusing the range to the previously selected texts inside iframe but I don't know the exact code to do it. I tried using rangeObj.moveStart(#), rangeObj.moveEnd(#) and rangeObj.select() but I it can't traverse through iframe DOM and selecting the current document instead. You can refer back to my post since I updated it just now. – blackstrider Apr 24 '11 at 15:17
  • I discovered that using document.getElementById(iframeid) to create and select range inside iframe won't work but window.frames[iframeid] will. Took me several hours. – blackstrider Apr 24 '11 at 21:53
  • In fact, I didn't see it before but my post is a fail. – xavierm02 Apr 24 '11 at 21:56
  • The HTML tags were taken out... Rather: range.pasteHTML( "" + range.htmlText + "" ); – xavierm02 Apr 24 '11 at 21:56