javascript - 在不重置插入符号(光标)位置的情况下修改内容可编辑的 div 中的文本

标签 javascript jquery html regex contenteditable

我正在尝试替换 /any thing in here/ 的所有实例与 <b>/any thing in here/</b>即时,因为在内容可编辑的 div 中进行了更改。

我当前的实现有效,但在每次按键时,插入符都会移动到 div 的开头,从而使实现无法使用。有没有办法在替换 div 的内容时保持插入符号的位置?

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

最佳答案

尝试一下 demo

    $('#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);
    }

关于javascript - 在不重置插入符号(光标)位置的情况下修改内容可编辑的 div 中的文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24845254/

相关文章:

javascript - 当旧浏览器不接受 jquery 时的替代方案

JavaScript/JQuery - 如何在使用后暂时禁用功能?

javascript - jQuery 暂时禁用点击

jquery - 为什么这些 jquery 事件会同步触发?

脚本完全加载并执行时的 jquery .getscript() 回调

javascript - 为此,将 WordPress 发布信息分配给 PHP 数组并将 php 数组值分配给 javascript 数组

html - 使用 :focus to create a CSS toggle 时忽略光标样式

javascript - 在 Meteor 和 Iron Router 中支持具有嵌套属性的多个参数

javascript - 在可以从 promise 中收集结果之前响应终止

javascript - 单选按钮更改事件并改进类似功能