admin管理员组

文章数量:1323323

I am using a text editor provided by Microsoft ajax-toolkit.
It renders iframe on browser. I have added a dropdown in that editor and I want that when user changes the drop-down index the value should be added in the editor current cursor position.

I got a code on SO which gives me the current selected text inside editor is as follows

function getIframeSelectionText(iframe) {
        var win = iframe.contentWindow;
        var doc = iframe.contentDocument || win.document;

        if (win.getSelection) {
            return win.getSelection().toString();

        } else if (doc.selection && doc.selection.createRange) {
            return doc.selection.createRange().text;
        }
 }

But I want to add some text at the current position. The html is rendering as below

<td class="ajax__htmleditor_editor_editpanel"><div id="Editor1_ctl02" style="height:100%;width:100%;">
            <iframe id="Editor1_ctl02_ctl00" name="Editor1_ctl02_ctl00" marginheight="0" marginwidth="0" frameborder="0" style="height:100%;width:100%;display:none;border-width:0px;">

            </iframe><textarea id="Editor1_ctl02_ctl01" class="ajax__htmleditor_htmlpanel_default" style="height:100%;width:100%;display:none;"></textarea><iframe id="Editor1_ctl02_ctl02" name="Editor1_ctl02_ctl02" marginheight="0" marginwidth="0" frameborder="0" style="height:100%;width:100%;display:none;border-width:0px;">

            </iframe>
        </div></td>

I am trying as follow

$("#imgDropdown").change(function () {
            //var iframeBody =    $(window.Editor1_ctl02_ctl00.document.getElementsByTagName("body")[0]);
            var iframe = document.getElementById("Editor1_ctl02_ctl00");
            $("#Editor1_ctl02_ctl00").find("body").insertAtCaret("value");
            //alert(getIframeSelectionText(iframe));
        });

the function for inserting text is not working with iframe is as follow

$.fn.extend({
        insertAtCaret: function (myValue) {
            if (document.selection) {
                this.focus();
                sel = document.selection.createRange();
                sel.text = myValue;
                this.focus();
            }
            else if (this.selectionStart || this.selectionStart == '0') {
                var startPos = this.selectionStart;
                var endPos = this.selectionEnd;
                var scrollTop = this.scrollTop;
                this.value = this.value.substring(0, startPos) + myValue + this.value.substring(endPos, this.value.length);
                this.focus();
                this.selectionStart = startPos + myValue.length;
                this.selectionEnd = startPos + myValue.length;
                this.scrollTop = scrollTop;
            } else {
                this.value += myValue;
                this.focus();
            }
        }
    })

I am using a text editor provided by Microsoft ajax-toolkit.
It renders iframe on browser. I have added a dropdown in that editor and I want that when user changes the drop-down index the value should be added in the editor current cursor position.

I got a code on SO which gives me the current selected text inside editor is as follows

function getIframeSelectionText(iframe) {
        var win = iframe.contentWindow;
        var doc = iframe.contentDocument || win.document;

        if (win.getSelection) {
            return win.getSelection().toString();

        } else if (doc.selection && doc.selection.createRange) {
            return doc.selection.createRange().text;
        }
 }

But I want to add some text at the current position. The html is rendering as below

<td class="ajax__htmleditor_editor_editpanel"><div id="Editor1_ctl02" style="height:100%;width:100%;">
            <iframe id="Editor1_ctl02_ctl00" name="Editor1_ctl02_ctl00" marginheight="0" marginwidth="0" frameborder="0" style="height:100%;width:100%;display:none;border-width:0px;">

            </iframe><textarea id="Editor1_ctl02_ctl01" class="ajax__htmleditor_htmlpanel_default" style="height:100%;width:100%;display:none;"></textarea><iframe id="Editor1_ctl02_ctl02" name="Editor1_ctl02_ctl02" marginheight="0" marginwidth="0" frameborder="0" style="height:100%;width:100%;display:none;border-width:0px;">

            </iframe>
        </div></td>

I am trying as follow

$("#imgDropdown").change(function () {
            //var iframeBody =    $(window.Editor1_ctl02_ctl00.document.getElementsByTagName("body")[0]);
            var iframe = document.getElementById("Editor1_ctl02_ctl00");
            $("#Editor1_ctl02_ctl00").find("body").insertAtCaret("value");
            //alert(getIframeSelectionText(iframe));
        });

the function for inserting text is not working with iframe is as follow

$.fn.extend({
        insertAtCaret: function (myValue) {
            if (document.selection) {
                this.focus();
                sel = document.selection.createRange();
                sel.text = myValue;
                this.focus();
            }
            else if (this.selectionStart || this.selectionStart == '0') {
                var startPos = this.selectionStart;
                var endPos = this.selectionEnd;
                var scrollTop = this.scrollTop;
                this.value = this.value.substring(0, startPos) + myValue + this.value.substring(endPos, this.value.length);
                this.focus();
                this.selectionStart = startPos + myValue.length;
                this.selectionEnd = startPos + myValue.length;
                this.scrollTop = scrollTop;
            } else {
                this.value += myValue;
                this.focus();
            }
        }
    })
Share edited Aug 2, 2017 at 15:35 Cœur 38.8k26 gold badges205 silver badges277 bronze badges asked Mar 29, 2014 at 12:45 शेखरशेखर 17.6k14 gold badges63 silver badges122 bronze badges 5
  • Any console errors (for example, security problems)? – Adrian Preuss Commented Apr 1, 2014 at 4:39
  • What specifically is not working? Can you test that the function is being called correctly with the correct parameters, etc. for us? – Cyassin Commented Apr 1, 2014 at 5:58
  • The $("#Editor1_ctl02_ctl00").find("body").insertAtCaret("value"); is not working it should insert the values in the body where the current pointer is. – शेखर Commented Apr 1, 2014 at 6:17
  • Could you provide a jsfiddle? – A. Wolff Commented Apr 2, 2014 at 12:02
  • Is the code even correctly entering into the .insertAtCaret() function? Can you successfully place an alert in there to test it gets inside that function? – Cyassin Commented Apr 4, 2014 at 3:31
Add a ment  | 

2 Answers 2

Reset to default 8 +100

Easy, you just have to use.

$("#Editor1_ctl02_ctl00").contents().find('textarea').insertAtCaret('value');

Updated

Sorry, I thought the insertAtCaret function is working for you, you just needed to work inside iFrame. You can use this version of insertAtCaret:

jQuery.fn.extend({
    insertAtCaret: function (html) {
        var winObject = function (el){
            var doc = el.ownerDocument;
            return doc.defaultView || doc.parentWindow
        };
        return this.each(function (i) {
                var sel, range, w = this;
                w = winObject(w);
                if (w.getSelection) {
                    // IE9 and non-IE
                    sel = w.getSelection();
                    if (sel.getRangeAt && sel.rangeCount) {
                        range = sel.getRangeAt(0);
                        range.deleteContents();

                        // Range.createContextualFragment() would be useful here but is
                        // only relatively recently standardized and is not supported in
                        // some browsers (IE9, for one)
                        var el = w.document.createElement("div");
                        el.innerHTML = html;
                        var frag = w.document.createDocumentFragment(), node, lastNode;
                        while ((node = el.firstChild)) {
                            lastNode = frag.appendChild(node);
                        }
                        range.insertNode(frag);

                        // Preserve the selection
                        if (lastNode) {
                            range = range.cloneRange();
                            range.setStartAfter(lastNode);
                            range.collapse(true);
                            sel.removeAllRanges();
                            sel.addRange(range);
                        }
                    }
                } else if (w.document.selection && w.document.selection.type != "Control") {
                    // IE < 9
                    w.document.selection.createRange().pasteHTML(html);
                }
            }
        )
    }
});

and call it like:

$("#Editor1_ctl02_ctl00").contents().find('body').insertAtCaret($val);

Function adapted from here

Happy coding!

There seem to be a few issues here.

  1. The Microsoft ajax-toolkit editor creates an iframe where the designMode property is turned on, and that's why it's editable, it has no value, and textNodes are added straight to the body, which makes it a little more difficult.

  2. When you're selecting something from a dropdown, the focus is on the dropdown, and there is no caret position, as the focus is shifted away from the iFrame.
    I'm assuming that the dropdown is in the top menubar for the editor or anywhere else that is outside the iFrame.

Also, the Microsoft ajax-toolkit editor has a remended update, the HTMLEditorExtender.

The code you have to capture the caret position seems to be for a regular input / textarea, and you'd have to adapt that code to work with any Node inside an iframe that is in designMode, with it's own window and document etc.

Given the above considerations, this is what I came up with to do this

var frameID  = 'Editor1_ctl02_ctl00',
    selectID = 'imgDropdown',
    iframe   = document.getElementById(frameID),
    iWin     = iframe.contentWindow ? iframe.contentWindow : window.frames[frameID];

$(iWin).on('blur', function() {
    $(iframe).data('range', getRange(iWin));
});

$('#' + selectID).on('change', function() {
    var range = $(iframe).data('range');
    addText(iWin, range, this.value);
});


function getRange(win) {
    var sel, range, html;
    if (win.getSelection) {
        sel = win.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = sel.getRangeAt(0);
            range.deleteContents();
        }
    } else if (win.document.selection && win.document.selection.createRange) {
        range = win.document.selection.createRange();
    }
    return range;
}

function addText(win, range, text) {
    if (win.getSelection) {
       range.insertNode(win.document.createTextNode(text));
    } else if (win.document.selection && win.document.selection.createRange) {
        range.text = text;
    }
}

FIDDLE

本文标签: javascriptInsert text at current cursor position on dropdown list changed inside iframeStack Overflow