修改contenteditable div中的文本而不重置插入符(光标)位置

sly*_*lyv 8 html javascript regex jquery contenteditable

我试图取代的任何实例/any thing in here/<b>/any thing in here/</b>上飞,因为变化在CONTENTEDITABLE DIV制作.

我当前的实现工作正常,但是在每个按键时,插入符被移动到div的开头,使得实现无法使用.在替换div的内容时是否有某种方法可以保持插入位置?

$('.writer').on('keyup', function(e) {
     $(this).html($(this).html().replace(/\/(.*)\//g, '<b>\/$1\/<\/b>'));
});
Run Code Online (Sandbox Code Playgroud)

小智 6

尝试演示

    $('#writer').on('keyup', function(e) {
        var range = window.getSelection().getRangeAt(0);
        var end_node = range.endContainer;
        var end = range.endOffset;
        if(end_node != this){
            var text_nodes = get_text_nodes_in(this);
            for (var i = 0; i < text_nodes.length; ++i) {
                if(text_nodes[i] == end_node){
                    break;
                }
                end += text_nodes[i].length;
            }
        }
        var html = $(this).html();
        if(/\&nbsp;$/.test(html) && $(this).text().length == end){
            end = end - 1;
            set_range(end,end,this);
            return;
        }
        var filter = html.replace(/(<b>)?\/([^<\/]*)(<\/b>)?/g, '\/$2');
        console.log(filter);
        filter = filter.replace(/(<b>)?([^<\/]*)\/(<\/b>)?/g, '$2\/');
        console.log(filter);
        filter = filter.replace(/(<b>)?\/([^<\/]*)\/(<\/b>)?/g, '<b>\/$2\/<\/b>');
        console.log(filter);
        if(!/\&nbsp;$/.test($(this).html())){
            filter += '&nbsp;';
        }
        $(this).html(filter);
        set_range(end,end,this);

    });

    $('#writer').on('mouseup', function(e) {
        if(!/\&nbsp;$/.test($(this).html())){
            return;
        }
        var range = window.getSelection().getRangeAt(0);
        var end = range.endOffset;
        var end_node = range.endContainer;
        if(end_node != this){
            var text_nodes = get_text_nodes_in(this);
            for (var i = 0; i < text_nodes.length; ++i) {
                if(text_nodes[i] == end_node){
                    break;
                }
                end += text_nodes[i].length;
            }
        }
        if($(this).text().length == end){
            end = end - 1;
            set_range(end,end,this);
        }
    });

    function get_text_nodes_in(node) {
        var text_nodes = [];
        if (node.nodeType === 3) {
            text_nodes.push(node);
        } else {
            var children = node.childNodes;
            for (var i = 0, len = children.length; i < len; ++i) {
                var text_node
                text_nodes.push.apply(text_nodes, get_text_nodes_in(children[i]));
            }
        }
        return text_nodes;
    }

    function set_range(start, end, element) {
        var range = document.createRange();
        range.selectNodeContents(element);
        var text_nodes = get_text_nodes_in(element);
        var foundStart = false;
        var char_count = 0, end_char_count;

        for (var i = 0, text_node; text_node = text_nodes[i++]; ) {
            end_char_count = char_count + text_node.length;
            if (!foundStart && start >= char_count && (start < end_char_count || (start === end_char_count && i < text_nodes.length))) {
                range.setStart(text_node, start - char_count);
                foundStart = true;
            }
            if (foundStart && end <= end_char_count) {
                range.setEnd(text_node, end - char_count);
                break;
            }
            char_count = end_char_count;
        }

        var selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);
    }
Run Code Online (Sandbox Code Playgroud)