【问题标题】:Insert several elements inside an editable div at cursor position在光标位置的可编辑 div 内插入多个元素
【发布时间】:2015-12-18 02:58:02
【问题描述】:

我有一个带有 contenteditable 属性的 div。用户需要能够在光标所在的位置键入和插入多个选择菜单。我设法获得了光标位置并插入了第一个选择菜单,但它只适用于第一个文本节点。

这就是我获得光标位置的方式:

function getCaretCharacterOffsetWithin(element) {
    var caretOffset = 0;
    var doc = element.ownerDocument || element.document;
    var win = doc.defaultView || doc.parentWindow;
    var sel;
    if (typeof win.getSelection != "undefined") {
            sel = win.getSelection();
            if (sel.rangeCount > 0) {
                    var range = win.getSelection().getRangeAt(0);
                    var preCaretRange = range.cloneRange();
                    preCaretRange.selectNodeContents(element);
                    preCaretRange.setEnd(range.endContainer, range.endOffset);
                    caretOffset = preCaretRange.toString().length;
                }
            } else if ( (sel = doc.selection) && sel.type != "Control") {
              var textRange = sel.createRange();
              var preCaretTextRange = doc.body.createTextRange();
              preCaretTextRange.moveToElementText(element);
              preCaretTextRange.setEndPoint("EndToEnd", textRange);
              caretOffset = preCaretTextRange.text.length;
          }
          return caretOffset;
    }

然后我在每次用户输入或点击时更新它。

function updatePos() {
    var el = document.getElementById("msg");   
    pos = getCaretCharacterOffsetWithin(el);
}
document.body.onkeyup = updatePos;
document.body.onmouseup = updatePos;

下面是我如何处理添加选择的按钮。我不确定如何在文本节点之后插入元素,所以我插入了一个 br 标记并稍后将其删除。必须有更清洁的方法,对吧?

$('#btn').click(function(){
        var selectList = document.createElement('select');
        var msg = $('#msg');
        $(msg).html(function(){
                var first = $(msg).html().substring(0, pos);
                var last =  $(msg).html().substring(pos);
                return first + '<br>' + last;
        });

        $(msg).contents().filter('br').after(selectList);

        $(msg).contents().filter('br').remove();

        $(msg).focus();
})

我想问题是我使用子字符串来拆分文本并能够在其中插入选择,并且一旦有另一个选择标签,子字符串就无法越过第一个文本节点。所以也许我应该用不同的方法重做整个事情,但我完全被困住了。

这是 jsfiddle:https://jsfiddle.net/8a63sosr/

谢谢!

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    问题在于,对于 HTML 元素,它采用 jQuery,text(),而不是 html()

    我想有一些范围参数的更好的解决方案,但这里有一些东西:

        //fix caret pos
        var temlOffset = pos;
        $('#msg').html().split(/(<[^>]+>)/g).forEach(function(el){
            if(temlOffset > 0){
                if(el.length && el[0] === '<'){
                   pos += el.length;
                } else {
                   temlOffset -= el.length;
                }
            }
        });
    

    https://jsfiddle.net/Lemz17L8/

    所以,它的作用是将 html 标记长度添加到 pos 值。

    最好的问候,亚历山大

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-05
      • 2020-10-15
      • 2016-07-05
      • 2011-02-24
      • 1970-01-01
      相关资源
      最近更新 更多