利用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>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章