如何在tinymce中找到准确的光标位置

时间:2017-03-18 15:56:05

标签: tinymce

我试图获得准确的位置来删除内容。但是无法找到光标位置并且无法获取数据值。它只能在以前的位置获取值。

请帮帮我。

我试过下面的代码,

tinymce.activeEditor.selection.getRng() - 在这里我们无法找到确切的位置。它只取得了前所未有的地位。

         ed.on("drop", function($event) {
            if($event.preventDefault) {
                $event.preventDefault();
            }
            if($event.stopPropagation()) {
                $event.stopPropagation();
            }

            if ($event.dataTransfer) {
                var data = $event.dataTransfer.getData("Text");
                var $data = angular.fromJson(data);
            }
        });

在下降中我们也无法找到确切的位置。

请给我解决方案。

1 个答案:

答案 0 :(得分:0)

这是一个棘手的问题。

我写了两个函数。一个用于获取tinymce中的绝对光标位置,另一个用于将光标设置为指定的光标位置。另外还有两个有用的函数可以在编辑器中设置插入符号,另外一个用于获取实际插入符号的块元素。

我将这些功能放在我自己的自定义tinymce插件 myownplugin 中,但你可以将这些功能放在你喜欢的地方。

他们是:

    // gets the caret offset to the editor start
    get_caret_offset: function()
    {
        var ed = this.editor;

        var range = ed.selection.getRng(1);
        var copied_range = range.cloneRange();
        var subtract_from_index = 0;

        // count returns
        var index = $(ed.plugins.myownplugin.p_of(range.startContainer)).index();
        var add_to_offset = 0;

        // add 1 for each empty paragraph
        var $children = $(ed.getBody()).children();

        // some node contents need to be subtracted from the offset later on.
        // free paragraphs count for example
        var subtract = 0;
        var rte_starts = 0;
        for (var i=0; i < index; i++)
        {
            var child_node = $children.eq(i).get(0);
            if (child_node)
            {
                if (child_node.nodeName == 'RTEPHTAG')
                {
                    subtract_from_index++;

                    if (child_node.className == "start")
                    {
                        subtract = 0;
                    }
                    else subtract = 0;
                }

                if (subtract && (child_node.nodeName == 'P' || child_node.nodeName == 'OL' || child_node.nodeName == 'UL'))
                {
                    subtract_from_index += child_node.textContent.replace(re_exspaces,'')
                        .replace( /\ufeff/g, '' )
                        .replace( /\u00ad/g, '' )
                        .replace( /&#65279;/g, '')
                        .replace( /&#173;/g, '')
                        .replace( /&shy;/g, '').length + 1;
                }
                // count bBRs
                else if(child_node.nodeName == 'P' || child_node.nodeName == 'OL' || child_node.nodeName == 'UL')
                {
                    add_to_offset += $(child_node).find('br').length;
                }
            }
        }

        // copy range to be able to calculate characters to the start of the initial range
        copied_range.setStart(ed.getBody().firstChild, 0);

        // caret paragraph needs to be counted too?
        if(subtract)
        {
            if (index)
            {
                var endnode = $children.eq(index - 1).get(0);
                if (endnode) copied_range.setEndAfter(endnode);
                else copied_range.setEnd(range.endContainer, range.endOffset);
            }
            else return 0;
        }
        else copied_range.setEnd(range.endContainer, range.endOffset);

        var str = copied_range.toString();
        subtract_from_index += ( str.match(/[\uD800-\uDBFF]/g) || [] ).length;

        var caret_offset = str
            .replace(re_exspaces,'')
            .replace( /\ufeff/g, '' )
            .replace( /\u00ad/g, '' )
            .replace( /&#65279;/g, '')
            .replace( /&#173;/g, '')
            .replace( /&shy;/g, '').length + index + add_to_offset + rte_starts - subtract_from_index;

        // add BRs in the actual paragraph?
        var p_end = ed.plugins.myownplugin.p_of(range.endContainer);
        if(range.endContainer && range.endContainer.nodeName != 'BODY')
        {
            if (p_end){
                copied_range.setStartBefore(p_end);
            }
        }

        return caret_offset;
    },

    // sets the caret according to the offset
    set_caret_offset: function(offset, scroll_into_view)
    {
        function get_count(where_str, search_str) {
            var m = where_str.match(new RegExp(search_str.toString().replace(/(?=[.\\+*?[^\]$(){}\|])/g, "\\"), "g"));
            return m ? m.length:0;
        }

        var ed = this.editor;


        // Check: enough content to set caret?
        if (!offset)
            ed.plugins.myownplugin.setCursor(ed, ed.getBody().firstChild, 1);

        var $body = $(ed.getBody());
        var content = ed.getContent({format : 'text', no_events : 1})
            .replace(re_exspaces,'')
            .replace( /\ufeff/g, '' )
            .replace( /\u00ad/g, '' )
            .replace( /&#65279;/g, '')
            .replace( /&#173;/g, '')
            .replace( /&shy;/g, '');
        var content_length = content.length + $body.find('br').length - ( content.match(/[\uD800-\uDBFF]/g) || [] ).length;

        if (content_length <= offset)
        {
            // set caret to the end of the editor
            ed.plugins.myownplugin.setCursor(ed, ed.getBody().lastChild, 0);
        }
        else
        {
            var offset_till_now = 0;
            var node = ed.getBody().firstChild;
            var rng;
            var counter = 0;
            while (node && offset > offset_till_now)
            {
                var br_count = 0;

                // Offset muss verringert werden, da Indesign Ps und BRs als Zeichen zählt
                if (counter && (node.nodeName == "BR" || node.nodeName == "P" || node.nodeName == "OL" || node.nodeName == "UL"))
                {
                    offset = offset - 1;
                }
                counter++;

                if (node.nodeName == "P" || node.nodeName == "OL" || node.nodeName == "UL")
                {
                    br_count = $(node).find('br').length;
                }

                var textContent = node.textContent
                    .replace(re_exspaces,'')
                    .replace( /\ufeff/g, '' )
                    .replace( /\u00ad/g, '' )
                    .replace( /&#65279;/g, '')
                    .replace( /&#173;/g, '')
                    .replace( /&shy;/g, '');

                var length = textContent.length + br_count - ( textContent.match(/[\uD800-\uDBFF]/g) || [] ).length;

                // textnode?
                if (node && node.nodeType == 3)
                {
                    if (offset <= offset_till_now + length)
                    {
                        rng = ed.selection.getRng(1);
                        rng.setStart(node, offset - offset_till_now);
                        rng.setEnd(node, offset - offset_till_now);

                        offset_till_now = offset; // fertig
                    }
                    else
                    {
                        node = node.nextSibling;
                        offset_till_now += length;
                    }
                }
                else
                {
                    // caret to be inserted here ?
                    if (offset < offset_till_now + length)
                    {
                        // nur text nodes als Kinder?
                        // dann schreibe den textknoten neu und setze die Range entsprechend
                        // ansonsten weiter mit dem ersten Kind
                        if (!node.children.length)
                        {
                            var textnode = ed.getDoc().createTextNode(node.textContent);
                            node.innerHTML = '';
                            node.appendChild(textnode);

                            rng = ed.selection.getRng(1);
                            rng.setStart(textnode, offset - offset_till_now);
                            rng.setEnd(textnode, offset - offset_till_now);

                            var copied_range = rng.cloneRange();
                            copied_range.setStart(textnode, 0);
                            copied_range.setEnd(textnode, offset - offset_till_now);

                            var t = copied_range.toString();
                            var add_to_index = ( t.match(/[\uD800-\uDBFF]/g) || [] ).length;

                            rng.setStart(textnode, offset - offset_till_now + add_to_index);
                            rng.setEnd(textnode, offset - offset_till_now + add_to_index);

                            offset_till_now = offset; // fertig
                        }
                        node = node.firstChild;
                    }
                    // caret needs to be set after this node
                    else
                    {
                        if (offset == offset_till_now + length)
                        {
                            // set caret to start of node
                            ed.plugins.myownplugin.setCursor(ed, node, 0);
                            offset_till_now = offset; // fertig
                        }
                        else
                        {
                            // get following node
                            node = node.nextSibling;
                            offset_till_now += length;
                        }
                    }
                }
            }
        }

        // scrollinto view
        if (scroll_into_view)
        {
            ed.execCommand('mceInsertContent', false, '<span class="set_caret_marker">\ufeff</span>');
            setTimeout(function() {
                var $marker = $(ed.getBody()).find('.set_caret_marker');
                if ($marker.length)
                {
                    $marker.get(0).scrollIntoView();
                    ed.selection.select($marker.get(0));
                    $marker.remove();
                }
            }, 500);
        }
    },

    // sets the cursor position (start defines if the caret is to be placed at the start)
    setCursor: function (ed, element, start)
    {
        // caret may appear inside lis only
        if (element.nodeName == "UL" || element.nodeName == "OL")
        {
            $element = $(element);
            element = start ? $element.find('li:first').get(0) : $element.find('li:last').get(0);
        }

        var doc = ed.getDoc();
        var edwin = ed.getWin();

        var range = ed.selection.dom.createRng();
        range.selectNodeContents(element);
        range.collapse(start);
        var sel = ed.selection.getSel();
        sel && sel.removeAllRanges();
        sel && sel.addRange(range);
    },

    // returns the block parent element of the actual element
    // stopper defines a node at which we will stop
    p_of: function (node, stopper)
    {
        stopper = stopper ? stopper.toUpperCase() : null;

        while (node)
        {
            if (node.nodeName == 'BODY') { return null; }
            if (node.nodeName == 'P' || node.nodeName == 'UL' || node.nodeName == 'OL' || node.nodeName == stopper) { return node; }
            else { node = node.parentNode; }
        }
        return null;
    },

我希望这对你们中的一些人有用。