javascript - 如何将输入的文本包装在跨度的 contenteditable 元素中?

标签 javascript html contenteditable

我有一个将“contenteditable”设置为 true 的 div。

我现在希望将所有新输入的文本包装在跨度中。这意味着我可以突出显示已编辑的文本。

这就是我现在所处的位置 - http://jsfiddle.net/ug4xr9x0/

HTML

<div contenteditable="true" id="myContent">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi suscipit tincidunt leo, non volutpat lectus sodales non. Phasellus id felis ultrices, egestas enim nec, ornare quam. Ut at posuere felis, vitae sodales risus. Suspendisse velit nibh, facilisis et ante et, vehicula facilisis velit.</div>

Javascript

document.getElementById('myContent').addEventListener('keydown',function(evt){
    var range = window.getSelection().getRangeAt(0);
    if(range.startContainer.parentNode.className!=='highlight'){
        var newElement = document.createElement('span');
        newElement.className = 'highlight';
        newElement.innerHTML = String.fromCharCode(evt.which);
        range.insertNode(newElement);
        range.setStartAfter(newElement);
        evt.preventDefault();
    }
});

CSS

.highlight{
    background-color:yellow;
}

这会将跨度包裹在字符周围,但不会将插入符号移动到跨度中,从而导致向后键入。我完全不确定 keydown 是否是要监听的适当事件,甚至不确定阻止按键并插入元素是否正确。 range.setStartAfter 行试图移动插入符号,但无论有没有它,其行为都是相同的。

我还希望在他们开始输入时删除所有选定的文本,但目前并没有发生。

任何帮助将不胜感激。谢谢。

最佳答案

我现在已经成功地在 Chrome 和 Firefox 中实现了这一点。以下是修改内容

document.getElementById('myContent').addEventListener('keypress',function(evt){
    var range = window.getSelection().getRangeAt(0),
        modifiers = [0,8]; // List of keys to ignore (0 is arrows & 8 is delete in firefox)

    if(range.startContainer.parentNode.className!=='highlight' && modifiers.indexOf(evt.which) <  0){
        if(!range.collapsed){
            range.deleteContents();
        }
        var el =  document.createElement('span');
        el.appendChild(document.createTextNode('A'));
        el.className = 'highlight';
        range.insertNode(el);

        var sel = window.getSelection();        
        range.setStartBefore(el.childNodes[0]);
        range.setEndAfter(el.childNodes[0]);
        sel.removeAllRanges();
        sel.addRange(range);
    }
});

还有 fiddle http://jsfiddle.net/ug4xr9x0/8/

与“keydown”相反,“keypress”会停止在 Chrome 中触发箭头键等,Firefox 需要忽略 0 和 8 处的“evt.which”属性。

插入一个带有包含字母“A”的文本节点的跨度。然后,我使用 setStartBefore 和 setEndAfter 设置范围以包裹该节点,并使用 addRange 更新窗口选择。文本节点“A”被覆盖(不需要防止默认)。

我确信有一种更优雅的方法可以实现这一目标,但它对我有用。

感谢您的帮助。

关于javascript - 如何将输入的文本包装在跨度的 contenteditable 元素中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26409137/

相关文章:

javascript - 如何检查页面上的所有 JavaScript 函数是否已正确加载?

javascript - 使用 jasmine 运行 $.getJSON 时脚本不安全

javascript - 如果 id 消失,提交按钮可以工作

html - 如何防止 IE 内容可编辑 div 中的自动换行?

javascript - 世博会如何分发包裹? (.web.js、.js 配置)

html - 定位 <li> 属性?

html - 我的自定义样式表不会覆盖 foundation.css 样式表?

javascript - jQuery $(this) 不会将文本插入到我的元素中

css - 用户选择 :none breaking Safari contenteditable

contenteditable - vue.js 从输入的 contenteditable 元素中获取 innerhtml