在不重置插入符号(光标)位置的情况下修改contenteditable div中的文本 [英] Modify text in a contenteditable div without reseting the caret (cursor) position

查看:183
本文介绍了在不重置插入符号(光标)位置的情况下修改contenteditable div中的文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用< b> /这里的任何东西来替换任何 / here / 中的任何东西/ b> 在飞行中,因为变化是在contenteditable div中进行的。



我当前的实施工作正常,但在每次按键时,到div的开始使实现无法使用。在更换div的内容时是否有一些方法可以保留插入位置?


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


解决方案

试试

  $('#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>)?/ 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;
} ($(this).text()。length == end){
end = end - 1;
set_range(end,end,this);
}
;
}
});

函数get_text_nodes_in(节点){
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 ]));
}
}
返回text_nodes;


函数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; $!$ b if(!foundStart&& start> = char_count&&(start< end_char_count ||(start === end_char_count&&< 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);
休息;
}
char_count = end_char_count;
}

var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
}


I am trying to replace any instances of /any thing in here/ with <b>/any thing in here/</b> on the fly, as changes are made in a contenteditable div.

My current implementation works, but at every keypress the caret is moved to the beginning of div making the implementation unusable. Is there some way to keep the caret position while replacing the div's contents?

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

解决方案

try it 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);
    }

这篇关于在不重置插入符号(光标)位置的情况下修改contenteditable div中的文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆