如何实现textarea中输入@在当前文本的右下方出现一个div,里面选择人名
我想实现一个效果就是在textarea中输入一个@然后在该文字的右下方出现一个div,里面是放一个列表的,跟QQ的输入一样,不管是复制还是直接输入的@都出现这个功能!(前两天回答的那些有bug的)图片说明
亲自试了下,应该是上取整。
你看这个可不可以,有什么问题可以私信我。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
*{padding:0;margin:0;}
.box{position:relatuve;}
#ipt{
font-size:16px;
padding-left:5px;
line-height:30px;
}
#list{
position:absolute;
list-style:none;
width:150px;
display:none;
}
#list li{height:25px;line-height:25px;}
#list li:hover{background:#efefef;cursor:pointer;}
</style>
</head>
<body>
<div class='box'>
<textarea rows="3" cols="100" id='ipt'></textarea>
<ul id='list'>
<li>qq.com</li><li>sina.com</li><li>163.com</li>
</ul>
</div>
<script>
var ipt = document.getElementById('ipt');
var list = document.getElementById('list');
ipt.oninput = function(e){
//console.log(e)
//获取光标位置
var position = getPosition(ipt);
//console.log(position,(ipt.value+'').length)
//如果光标在文本最后面,且最后一个是@
if((position == (ipt.value+'').length) && /@$/.test(ipt.value)){
var iStyle = window.getComputedStyle(ipt);
//把双字节的替换成两个单字节的然后再获得长度
var len = (ipt.value || '').replace(/[^\x00-\xff]/g,"01").length/2;
var fz = parseFloat(iStyle.fontSize);
var wd = parseFloat(iStyle.width);
var lh = parseFloat(iStyle.lineHeight);
list.style.left = fz*(len%wd)>wd?wd:fz*(len%wd) + "px";
list.style.top = Math.ceil(len/wd)*lh + "px";
list.style.display = "block";
}else{
list.style.display = "none";
}
}
for(var i=0;i<list.children.length;i++){
list.children[i].onclick = function(e){
ipt.value += e.target.innerHTML;
list.style.display = "none";
}
}
//输入框获取光标
function getPosition(element) {
var cursorPos = 0;
if (document.selection) {//IE
var selectRange = document.selection.createRange();
selectRange.moveStart('character', -element.value.length);
cursorPos = selectRange.text.length;
} else if (element.selectionStart || element.selectionStart == '0') {
cursorPos = element.selectionStart;
}
return cursorPos;
}
</script>
</body>
</html>
https://github.com/yuku-t/jqu...
https://github.com/ichord/At.js (建议用这个,bug少,但不是专为Vue适配)
https://github.com/fritx/vue-at 可以参考一下,里面有源码
能不能给多行文本框添加一个事件获取文本框内容,然后用正则去匹配这个内容,匹配成功就把div设置为显示啊。
<!doctype html>
Document
<br> *{padding:0;margin:0;}<br> .box{position:relatuve;}<br> #ipt{<br> font-size:16px;<br> padding-left:5px;<br> height:30px;<br> line-height:30px;<br> }<br> #list{<br> position:absolute;<br> list-style:none;<br> width:150px;<br> display:none;<br> }<br> #list li{height:25px;line-height:25px;}<br> #list li:hover{background:#efefef;cursor:pointer;}<br>
- qq.com
- sina.com
- 163.com
<script>
var ipt = document.getElementById('ipt');
var list = document.getElementById('list');
ipt.oninput = function(e){
//console.log(e)
//获取光标位置
var position = getPosition(ipt);
console.log(position,(ipt.value+'').length)
//如果光标在文本最后面,且最后一个是@
if((position == (ipt.value+'').length) && /@$/.test(ipt.value)){
//把双字节的替换成两个单字节的然后再获得长度
var len = (ipt.value || '').replace(/[^\x00-\xff]/g,"01").length/2;
var fz = parseFloat(window.getComputedStyle(ipt).fontSize);
var wd = parseFloat(window.getComputedStyle(ipt).width);
list.style.left = fz*len>wd?wd:fz*len + "px";
list.style.display = "block";
}else{
list.style.display = "none";
}
}
for(var i=0;i<list.children.length;i++){
list.children[i].onclick = function(e){
ipt.value += e.target.innerHTML;
list.style.display = "none";
}
}
//输入框获取光标
function getPosition(element) {
var cursorPos = 0;
if (document.selection) {//IE
var selectRange = document.selection.createRange();
selectRange.moveStart('character', -element.value.length);
cursorPos = selectRange.text.length;
} else if (element.selectionStart || element.selectionStart == '0') {
cursorPos = element.selectionStart;
}
return cursorPos;
}
</script>
网上看到一个实现 还不错 基本满足你的要求 你在改一改就行了
可以用正则判断@,当出现@就显示一个下拉(有multiple属性的)或者直接一个下拉,选择完后再隐藏
js获取textbox焦点事件,当输入@符号时,用ajax调用后台方法,获取查询数据,组织成下拉框数据。
通过javascript 或jquery ,结合注册键盘事件实现。
你之前的问题是我回答的,上面那个贴代码的贴的也是我的代码,有bug可以私信我,没必要在花一次钱。
之前我是用输入框写的,不是文本域,所以少了一步,你在计算下文本域的宽度,用文字总长度除宽度,除数下取整就是行数,行数乘行高就是 列表 的top值,加上这个就可以了。
文字总长度模宽度的值就是 列表的 left值。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
*{padding:0;margin:0;}
.box{position:relatuve;}
#ipt{
font-size:16px;
padding-left:5px;
line-height:30px;
}
#list{
position:absolute;
list-style:none;
width:150px;
display:none;
}
#list li{height:25px;line-height:25px;}
#list li:hover{background:#efefef;cursor:pointer;}
</style>
</head>
<body>
<div class='box'>
<textarea rows="3" cols="20" id='ipt'></textarea>
<ul id='list'>
<li>qq.com</li><li>sina.com</li><li>163.com</li>
</ul>
</div>
<script>
var ipt = document.getElementById('ipt');
var list = document.getElementById('list');
ipt.oninput = function(e){
//console.log(e)
//获取光标位置
var position = getPosition(ipt);
ipt.value = ipt.value || '';
//如果光标后面是空格或没有内容,且光标前面最后一个是@
var s = ipt.value.charAt(position)
if((s == "" || s == " ") && ipt.value.charAt(position-1) == "@"){
var iStyle = window.getComputedStyle(ipt),
fz = parseFloat(iStyle.fontSize),//字体大小
wd = parseFloat(iStyle.width),//文本域宽度
lh = parseFloat(iStyle.lineHeight),//行高
pd = parseFloat(iStyle.paddingLeft),//左内边距
newStr = ipt.value.substr(0,position+1),
//有换行符根据换行符拆分
valArr = newStr.indexOf("\n")!==-1 ? newStr.split("\n") : [ipt.value];
for(var i=0,j=0;i<valArr.length;i++){
//把双字节的替换成两个单字节的然后再获得长度
var len = valArr[i].replace(/[^\x00-\xff]/g,"01").length/2;
j += Math.ceil((len*fz)/wd);
}
list.style.left = (len*fz)%wd==0?wd:(len*fz)%wd + pd + "px";
list.style.top = j*lh + "px";
list.style.display = "block";
}else{
list.style.display = "none";
}
}
for(var i=0;i<list.children.length;i++){
list.children[i].onclick = function(e){
ipt.value += e.target.innerHTML;
list.style.display = "none";
}
}
//输入框获取光标
function getPosition(element) {
var cursorPos = 0;
if (document.selection) {//IE
var selectRange = document.selection.createRange();
selectRange.moveStart('character', -element.value.length);
cursorPos = selectRange.text.length;
} else if (element.selectionStart || element.selectionStart == '0') {
cursorPos = element.selectionStart;
}
return cursorPos;
}
</script>
</body>
</html>
keyDown 事件,可以查一下@ 符号是那个。按键=@的时候弹出div