参考文章网址
1.https://segmentfault.com/a/1190000007846897?utm_source=tag-newest
2.https://www.jianshu.com/p/fff5079b1268
下边是简单的demo代码,可以复制自己在本地执行
初始版本
<!DOCTYPE html>
<html>
<head>
<title>测试</title>
<style>
*{
margin:0;
padding:0;
}
.box{
width:600px;
border:1px solid red;
height:500px;
line-height: 20px;
font-size:14px;
}
.list{
display: none;
}
button{
background: #fff;
line-height: 20px;
font-size:14px;
border:none ;
color:blue;
outline:none;
}
</style>
<!-- jquery自己下载引入 -->
<script charset="utf-8" src="jquery-3.1.1.min.js"></script>
</head>
<body>
<div class="box" contenteditable="true" id="box">
</div>
<ul id="list" class="list">
<li aid="one">1111</li>
<li aid="two">2222</li>
<li aid="three">3333</li>
<li aid="four">4444</li>
<li aid="five">5555</li>
</ul>
<script type="text/javascript">
let lastSelection=null;
$("#box").on('keydown',function(e){
console.log(e.keyCode);
if ( e.shiftKey&&e.keyCode == 50||(e.shiftKey&&e.keyCode == 229)) {//@符号-中文和英文输入法keyCode两种情况
var selection = getSelection();
var range = selection.getRangeAt(0);
// console.log(selection);
// console.log(range);//返回一个包含当前选区内容的区域对象。
// console.log(selection.focusOffset)//回一个数字,其表示的是选区终点在 focusNode 中的位置偏移量。
lastSelection={
range:range,
offset:selection.focusOffset,
selection:selection
};
$("#list").show();
}
})
$("#list li").on("click",function(){
$("#list").hide();
var ele = $('#box');
ele.focus();
var item=$(this).html();
var selection = lastSelection.selection;
var range = lastSelection.range;
var textNode=range.startContainer;
//删除页面中@符号
range.setStart(textNode,range.endOffset);
range.setEnd(textNode,range.endOffset+1);
range.deleteContents();
//创建button存放@内容,并且在button后边插入一个空格符,否则焦点不能重新获取到正确位置
var button1=document.createElement("button");
button1.setAttribute("contenteditable","false");
button1.innerHTML='@'+$(this).html()+" ";
var spanNode2=document.createElement("span");
spanNode2.innerHTML=' ';
var frag=document.createDocumentFragment();
frag.appendChild(button1);
lastNode=frag.appendChild(spanNode2.firstChild);
//填入内容并且重新设置焦点位置
range.insertNode(frag);
selection.extend(lastNode,1);
selection.collapseToEnd();
//获取当前焦点位置删除button后边增加的空格符dom,防止在执行Backspace删除键时需要点两次才能删除@内容
var selection = getSelection();
var range = selection.getRangeAt(0);
var textNode=range.startContainer;
range.setStart(textNode,range.endOffset-1);
range.setEnd(textNode,range.endOffset);
range.deleteContents();
})
</script>
</body>
</html>
2.修改后的demo代码
<!DOCTYPE html>
<html>
<head>
<title>测试</title>
<style>
*{
margin:0;
padding:0;
}
.box{
width:600px;
border:1px solid red;
height:500px;
line-height: 20px;
font-size:14px;
}
.list{
display: none;
}
button{
background: #fff;
line-height: 20px;
font-size:14px;
border:none ;
color:blue;
outline:none;
}
</style>
<!-- jquery自己下载引入 -->
<script charset="utf-8" src="jquery-3.1.1.min.js"></script>
</head>
<body>
<div class="box" contenteditable="true" id="box">
</div>
<ul id="list" class="list">
<li aid="one">1111</li>
<li aid="two">2222</li>
<li aid="three">3333</li>
<li aid="four">4444</li>
<li aid="five">5555</li>
</ul>
<script type="text/javascript">
let lastSelection=null;
$("#box").on('keydown',function(e){
console.log(e.keyCode);
if ( e.shiftKey&&e.keyCode == 50||(e.shiftKey&&e.keyCode == 229)) {//@符号-中文和英文输入法keyCode两种情况
var selection = getSelection();
var range = selection.getRangeAt(0);
// console.log(selection);
// console.log(range);//返回一个包含当前选区内容的区域对象。
// console.log(selection.focusOffset)//回一个数字,其表示的是选区终点在 focusNode 中的位置偏移量。
lastSelection={
range:range,
offset:selection.focusOffset,
selection:selection
};
$("#list").show();
}
})
$("#list li").on("click",function(){
$("#list").hide();
var ele = $('#box');
ele.focus();
var item=$(this).html();
var selection = lastSelection.selection;
var range = lastSelection.range;
var textNode=range.startContainer;
//删除页面中@符号
range.setStart(textNode,range.endOffset);
range.setEnd(textNode,range.endOffset+1);
range.deleteContents();
//创建button存放@内容,并且在button后边插入一个空格符,否则焦点不能重新获取到正确位置
var button1=document.createElement("button");
button1.setAttribute("contenteditable","false");
button1.innerHTML='@'+$(this).html()+" ";
var spanNode2=document.createElement("span");
spanNode2.innerHTML=' ';
var frag=document.createDocumentFragment();
// frag.appendChild(button1);
lastNode=frag.appendChild(button1);
//lastNode=frag.appendChild(spanNode2.firstChild);
range.insertNode(frag);
let contentRange = range.cloneRange(); //克隆选区
contentRange.setStartAfter(lastNode); //设置光标位置为插入内容的末尾
contentRange.collapse(true); //移动光标位置到末尾
selection.removeAllRanges(); //移出所有选区
selection.addRange(contentRange);//添加修改后的选区
/*//填入内容并且重新设置焦点位置
range.insertNode(frag);
selection.extend(lastNode,1);
selection.collapseToEnd();
//获取当前焦点位置删除button后边增加的空格符dom,防止在执行Backspace删除键时需要点两次才能删除@内容
var selection = getSelection();
var range = selection.getRangeAt(0);
var textNode=range.startContainer;
range.setStart(textNode,range.endOffset-1);
range.setEnd(textNode,range.endOffset);
range.deleteContents();*/
})
</script>
</body>
</html>