利用at.js实现微博@功能

直接贴出前端代码和@的交互逻辑代码

at.js官网

将页面内需要引用的js和css文件从官网下载,然后引入,直接打开这个demo就可以了

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<link rel="stylesheet" href="at/jquery.atwho.css" />
		<link rel="stylesheet" href=" https://apps.bdimg.com/libs/bootstrap/3.0.3/css/bootstrap.min.css" type="text/css"/>
		<script src="https://apps.bdimg.com/libs/jquery/1.10.2/jquery.min.js"></script> 
		<script src="https://apps.bdimg.com/libs/bootstrap/3.0.3/js/bootstrap.min.js"></script>
		<script src="at/jquery.caret.js"></script>
		<script src="at/jquery.atwho.js"></script>
		<style>
			body{
				display: flex;
				flex-direction: row;
				justify-content: center;
			}
			 .at_container{
			    width: 120px;
			    border: 1px solid rgba(0,0,0,.15);
		   		border-radius: 4px;
			    position: absolute;
			    bottom:15px;
			    display:none;
			    z-index: 9999;
			    background-color: #fff;
			    height: auto;
		    }
		    ul{
		    	margin-bottom: 0px;
		    }
		   .at_container li{
		    	display: block;
				display: flex;
		    	flex-direction: column;
		    	justify-content: center;
				padding-left:10px;
		    	font-size: 14px;
		    	font-weight: 400;
			    white-space: nowrap;
			    cursor: pointer;
			    border-bottom: 1px solid #e5e5e5;
			    height: 35px;
		    }
		   .at_container li:HOVER{
		    	background-color: #3366FF;
		    	color: #fff;
		    }
		</style>
	</head>
	<body>
		<div style="position: relative;margin-top: 200px;">
			<div class='at_container' id="at_container">
				<ul id='list' style="overflow-y:auto; padding-left: 0px">
				</ul>
			</div>
			<div id="info" class='form-control'  style="width: 400px;height: 100px; overflow-y: auto;"  contenteditable="true" >
				
			</div>
		</div>

	</body>
		<script>
			//后端返回的整个@数组列表
			var AllList = [{"name":"熊大","id":"1"},
				{"name":"熊二","id":"2"},
				{"name":"熊三","id":"3"},
				{"name":"熊四","id":"4"},
				{"name":"熊五","id":"5"},
				{"name":"熊六","id":"6"},
				{"name":"熊七","id":"7"},
				{"name":"熊八","id":"8"},
				{"name":"熊九","id":"9"},
				{"name":"熊老幺","id":"10"}];
			//后端返回的最近@过的人员列表
			var freList = [{"name":"熊二","id":"1"},
			{"name":"熊三","id":"2"},
			{"name":"熊八","id":"3"}]
			//初始化查询模式,默认在输入时处于非查询的状态下
			var searchModel = false;
			//初始化查询字符串在消息窗的index
			var searchStartIndex = 0;
			$(function(){		
					$("#info").keyup(function (e) {
					//如果按下@则此时进入查询模式,给searchModel和searchStartIndex赋值
					if(e.shiftKey&&e.keyCode==50){
						searchModel = true;
						searchStartIndex = $('#info').text().length;
					}
					//删除内容均导致退出search模式
			        if (e.keyCode == 8 || e.keyCode == 46) {
			        	searchModel = false;
			        	//关闭@列表
			            $('#at_container').css('display', 'none');
			        	//判定删除后文本最末字符是否是@,如果是则进入search模式
			        	if($("#info").text().substring($("#info").text().length-1,$("#info").text().length)=='@'){
			        		searchModel = true;
			        		searchStartIndex = $('#info').text().length;
			        	}
			        }
			        //如果不在查询模式下,直接返回
			        if(!searchModel){
			        	return;
			        }
			        //截取待查询的字符串
			        var searchString = $("#info").text().substring(searchStartIndex,$("#info").text().length);
			        if(searchString==''&&freList.length>0){
			        	//如果查询的字符串为空,即刚摁下@符号时,此时默认显示最近@过的人员列表
			        	pushToHtml(freList,function(){
			        		$('#at_container').css('display', 'block');
			        	});
			        }else{
			        	//否则从整个人员列表查询结果,查询的算法使用简单的indexOf函数
			        	var rl = new Array();
			        	for(var i in AllList){
			        		if(rl.length>=5)break;
			        		if(AllList[i].name.indexOf(searchString)!=-1)
			        			rl.push(AllList[i]);
			        	}
			        	if(rl.length>=1){//显示
			            	pushToHtml(rl,function(){
			            		$('#at_container').css('display', 'block');
			            	});	
			        	}else{//隐藏
			        		$('#at_container').css('display', 'none');
			        	} 
			        }		
			        //显示@列表并设置偏移位置
			        var offset = $('#info').caret('offset');
			        var position = $('#info').caret('position');
			        console.log(position)
			        var editorWidth = $('#info').width();
			        var atWidth = $('#at_container').width();		        
			        // 当右侧的空间不够显示@弹窗时,显示在左侧
			        // 所以需要对右侧剩余空间的大小进行判断
			        if (editorWidth - position.left < atWidth) {
			            $('#at_container').css('left', position.left - atWidth - 15);
			        } else {
			            $('#at_container').css('left', position.left+10);
			        }
			        $('#at_container').css('bottom',$('#info').height() - position.top);
			        $('#at_container').scrollTop(0);		        
				});
				//
				
				$("#info").click(function(e){
					if(searchModel){
						var searchString = $("#info").text().substring(searchStartIndex,$("#info").text().length);
						 if(searchString==''&&freList.length>0){
					        	pushToHtml(freList,function(){
					        		$('#at_container').css('display', 'block');
					        	});
					      }else{
					        	var rl = new Array();
					        	for(var i in AllList){
					        		if(rl.length>=5)break;
					        		if(AllList[i].name.indexOf(searchString)!=-1)
					        			rl.push(AllList[i]);
					        	}
					        	if(rl.length>=1){
					            	pushToHtml(rl,function(){
					            		$('#at_container').css('display', 'block');
					            	});	
					        	}else{
					        		$('#at_container').css('display', 'none');
					        	} 
					     }	
				        //显示@列表并设置偏移位置
				        var offset = $('#info').caret('offset');
				        var position = $('#info').caret('position');
				        console.log(position)
				        var editorWidth = $('#info').width();
				        var atWidth = $('#at_container').width();		        
				        // 当右侧的空间不够显示@弹窗时,显示在左侧
				        // 所以需要对右侧剩余空间的大小进行判断
				        if (editorWidth - position.left < atWidth) {
				            $('#at_container').css('left', position.left - atWidth - 15);
				        } else {
				            $('#at_container').css('left', position.left+10);
				        }
				        $('#at_container').css('bottom',$('#info').height() - position.top);
				        $('#at_container').scrollTop(0);	
					}
				})
				
					
				// 点击@窗体外的区域时,关闭@弹窗
				$(document).mouseup(function(e) { 
				    var pop = $('#at_container');    
				    if(!pop.is(e.target) && pop.has(e.target).length === 0) { 
				        $('#at_container').css('display', 'none');
				    }  
				}); 
				
			})
			
			function pushToHtml(list,callback){
				var html = "";
				for(var i in list){
					html += "<li data-id='"+list[i].id+"'>"+list[i].name+"</li>";
				}
				$("#list").html(html);
				registerClickOnLi();
				return (callback && typeof(callback)==="function") && callback();
			}
			function registerClickOnLi(){
				$('#at_container ul li').unbind('click').click(function (e) {
				    e.stopPropagation();
				    var id = $(this).data('id');
				    var name = $(this).text();
				    $('#at_container').css('display', 'none');
				    var html = $("#info").html().substring(0,$("#info").html().lastIndexOf("@")+1);
				    html += '<span contenteditable="false"  data-id="'+id+'">'+name+'</span>&nbsp;';
				    $("#info").html(html);
				   	$('#info span[data-id="'+id+'"]').attr('contenteditable', false);
				   	keepLastIndex(document.getElementById("info"));
				});
			}
			function keepLastIndex(obj) {
			    if (window.getSelection) {//ie11 10 9 ff safari
			        obj.focus(); //解决ff不获取焦点无法定位问题
			        var range = window.getSelection();//创建range
			        range.selectAllChildren(obj);//range 选择obj下所有子内容
			        range.collapseToEnd();//光标移至最后
			    }
			    else if (document.selection) {//ie10 9 8 7 6 5
			        var range = document.selection.createRange();//创建选择对象
			        range.moveToElementText(obj);//range定位到obj
			        range.collapse(false);//光标移至最后
			        range.select();
			    }
			}
		</script>
</html>

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值