关于javascript:在iframe中,在下拉列表的当前光标位置插入文本已更改

Insert text at current cursor position on dropdown list changed inside iframe

我正在使用Microsoft ajax-toolkit提供的文本编辑器。
它在浏览器上呈现iframe。我已在该编辑器中添加了一个下拉菜单,我希望当用户更改下拉索引时,应将值添加到编辑器的当前光标位置。

我在SO上获得了一个代码,该代码为我提供了编辑器中当前选定的文本,如下所示:

1
2
3
4
5
6
7
8
9
10
11
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;
        }
 }

但是我想在当前位置添加一些文本。 html呈现如下

1
2
3
4
5
6
7
<td class="ajax__htmleditor_editor_editpanel">
            &lt;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;">

            &lt;/iframex&gt;<textarea id="Editor1_ctl02_ctl01" class="ajax__htmleditor_htmlpanel_default" style="height:100%;width:100%;display:none;"></textarea>&lt;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;">

            &lt;/iframex&gt;
        </td>

我正在尝试如下

1
2
3
4
5
6
$("#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));
        });

iframe不能使用插入文本的功能,如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$.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();
            }
        }
    })


容易,您只需要使用。

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

更新

对不起,我认为insertAtCaret函数对您有用,您只需要在iFrame中工作。您可以使用以下版本的insertAtCaret:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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);
                }
            }
        )
    }
});

并这样称呼:

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

从此处改编的功能

祝您编程愉快!


这里似乎有一些问题。

  • Microsoft ajax-toolkit编辑器创建一个iframe,其中打开了designMode属性,这就是为什么它是可编辑的,没有任何值,并且textNodes直接添加到主体,这使得这有点困难。

  • 从下拉菜单中选择内容时,焦点将集中在下拉菜单上,并且没有插入符号的位置,因为焦点已从iFrame移开。
    我假设下拉菜单位于编辑器的顶部菜单栏中,或者位于iFrame之外的其他任何位置。

  • 此外,Microsoft ajax-toolkit编辑器具有建议的更新HTMLEditorExtender。

    您必须捕获插入符号位置的代码似乎是针对常规输入/文本区域的,并且您必须修改该代码以使其与处于designMode的iframe中的任何Node一起使用。自己的窗口和文档等。

    基于以上考虑,这就是我想出的方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    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