看完圖就直接上代碼吧,其中有幾處寫死的地方,我有提示,你們自己改下就是了。
//@顯示用戶列表(function($) {
$.fn.showAtUsers = function() { if($("#at_textarea").length == 0){ $("body").append("<pre id='at_textarea'></pre><div id='at_userslist'></div>");
//首先模擬一個(gè)輸入框和顯示用戶列表的div,有人說pre會(huì)把有回車的內(nèi)容,跟原先一樣的展示,但測(cè)試后,算出@的位置還是不對(duì),難道pre一說是傳說嗎。。。 } return this.each(function(){ var t = null,li_Index=1, $at_textarea=$("#at_textarea"), $at_userslist=$("#at_userslist"); $(this).on("keydown click", function(e) { //必須用keydown,否則上下鍵使光標(biāo)會(huì)移動(dòng) var _key=e.keyCode, Textarea = this; if($at_userslist.is(":visible") && (_key==40 || _key==38 || _key==13)){ TipLiSelect(Textarea,_key); return false; }else{ if(t !==null){ clearTimeout(t); } t = setTimeout(function(){ drawTextarea(Textarea); getAt(Textarea); },300); } }); $("body").on("click",function(e){ if(!isParent(e.target,$at_userslist[0])){ hiddenTip(); } }); //獲取光標(biāo) var getCursor = function(textarea) { var rangeData={ start: 0, end: 0, text: "" }; textarea.focus(); if (textarea.setSelectionRange) { // W3C rangeData.start= textarea.selectionStart; rangeData.end = textarea.selectionEnd; rangeData.text = textarea.value.substring(0, rangeData.end); } else if (document.selection) { // IE var i, oS = document.selection.createRange(), oR = document.body.createTextRange(); oR.moveToElementText(textarea); rangeData.text = oS.text; rangeData.bookmark = oS.getBookmark(); for (i = 0; oR.compareEndPoints('StartToStart', oS) < 0 && oS.moveStart("character", -1) !== 0; i ++) { if (textarea.value.charAt(i) == '\n') { i ++; } } rangeData.start = i; rangeData.end = rangeData.text.length + rangeData.start; rangeData.text = textarea.value.substring(0,i); } return rangeData; }, //設(shè)置光標(biāo) setCursor = function(textarea, rangeData) { textarea.focus(); if (textarea.setSelectionRange) { // W3C textarea.setSelectionRange(rangeData.start, rangeData.end); } else if (textarea.createTextRange) { // IE var oR = textarea.createTextRange(); if(textarea.value.length === rangeData.start) { oR.collapse(false); oR.select(); } else { oR.moveToBookmark(rangeData.bookmark); oR.select(); } } },
//插入選擇的用戶名稱 add = function(txtData,Object) { var oValue,atPos,nStart,nEnd,nValue,st,sR, textarea = Object.textarea; setCursor(textarea, Object.rangeData); oValue = textarea.value; //@符所在的位置 atPos = parseInt(Object.pos) - parseInt(Object.len); nValue = oValue.substring(0,atPos) + "@" +txtData + " " + oValue.substring(Object.rangeData.end); nStart = nEnd = atPos + txtData.length +2; st = textarea.scrollTop; textarea.value = nValue; // 賦值后,scrollTop會(huì)變回0,重新設(shè)置scrollTop if(textarea.scrollTop != st) { textarea.scrollTop = st; } if (textarea.setSelectionRange) { // W3C textarea.setSelectionRange(nStart, nEnd); } else if (textarea.createTextRange) {
// IE下測(cè)試坑爹,又要插入,又要光標(biāo)插入到姓名+空格后面,不是最末尾哦,我對(duì)TextRange不熟悉,所以寫成下面這樣,還好測(cè)試OK。
//如果高人有更好的方法,望誠(chéng)心討教,回復(fù)我下,先謝謝了。 oValue = oValue.substring(Object.rangeData.end);//光標(biāo)后面的字符 st = oValue.replace(/\n/g,'').length;//替換掉換行 sR = document.selection.createRange(); sR.moveEnd("character", -st); sR.select(); } }, //匹配@符 getAt = function(textarea) { var _rangeData=getCursor(textarea); var k=_value=_rangeData.text; var _reg=/@[^@\s]{0,20}$/g;//匹配@符后面0至20個(gè)字符 if(_value.indexOf("@")>= 0 && _value.match(_reg)) { var _postion=_rangeData.start; var _oValue=_value.match(_reg)[0];//找到value中最后匹配的數(shù)據(jù) var _AT={};//存儲(chǔ)輸入內(nèi)容被截取后的字段信息 if(_oValue==="@"){ _AT['m'] = "namihui";//自己改喜歡的標(biāo)記字符,說明此次輸入@后面沒有字,我因?yàn)槭墙o娜米匯做網(wǎng)站,所以這樣寫了。 _AT['l'] = _value.slice(0, -1).replace(/\n/g,'<br>'); //@前面的文字,把回車轉(zhuǎn)為br _AT['r'] = '';//@后面的文字 _AT['pos']=_postion;//光標(biāo)位置 _AT['len']=1;//光標(biāo)位置至@的長(zhǎng)度 _AT['rangeData']=_rangeData; _AT['textarea']=textarea; showTip(_AT); }else if(/^@[a-zA-Z0-9\u4e00-\u9fa5_-]+$/.test(_oValue) && !/\s/.test(_oValue)) { _AT['m'] = _oValue.slice(1);//用戶輸入的字符 如@娜米匯,即"娜米匯" _AT['l'] = _value.slice(0, -_oValue.length).replace(/\n/g,'<br>'); //@前面的文字 _AT['r'] = k.slice(_postion - _oValue.length+1, k.length);//@后面的文字 _AT['pos']=_postion;//光標(biāo)位置 _AT['len']=_oValue.length;//光標(biāo)位置至@的長(zhǎng)度 _AT['rangeData']=_rangeData; _AT['textarea']=textarea; showTip(_AT); } else { hiddenTip(); } } else { hiddenTip(); } }, drawTextarea= function(textarea){ var _left=$(textarea).offset().left + parseInt($(textarea).css("padding-left")) + "px", _top=$(textarea).offset().top + parseInt($(textarea).css("padding-top")) +"px", _width=$(textarea).width() +"px", _lineHeight=$(textarea).css("line-height"), Tstyle="line-height:"+_lineHeight+";width:"+_width+";left:"+_left+";top:"+_top; $at_textarea.attr("style",Tstyle); } showTip = function(obj){ var url = 'json2.html';//url你們改成后臺(tái)拉數(shù)據(jù)的地址就行,格式在此文章的后面,我有說明 if(obj.m == "namihui"){//這里寫另外個(gè)地址是為了演示@最近聯(lián)系人與根據(jù)輸入后臺(tái)返回匹配的數(shù)據(jù),2種不同情況寫的死數(shù)據(jù) url = 'json.html'; } $.ajax({ url: url, type:'post', data:{"key":obj.m}, success: function(result){ buidTip(result,obj); } }) }, //創(chuàng)建tip,設(shè)置tip的位置 buidTip = function(html,obj) { var _left, _top, Ttop, citeOfs, _string="<span>"+obj['l']+"</span>"+"<cite>@</cite>"+"<span>"+obj['r']+"</span>"; $at_textarea.html(_string); citeOfs=$at_textarea.find("cite").offset(); _left=citeOfs.left; _top=citeOfs.top+parseInt($at_textarea.css("line-height")); Ttop = parseInt($at_textarea.offset().top+$(obj.textarea).height()); if(_top > Ttop) { _top = Ttop; } $at_userslist.css({ "left":_left, "top":_top, "display":"block" }).html('<ul>'+html+'</ul>').find("li").eq(1).addClass("on"); TipLiEvent(obj); $(obj.textarea).data("at",obj); }, hiddenTip = function() { $at_userslist.hide().find("li").off(); }, //鍵盤選擇列表操作 TipLiSelect = function(textarea,key){ var li = $at_userslist.find("li"), _len=li.length; switch(key) { case 40: //向下鍵選擇 li_Index++; if(li_Index>_len-1) { li_Index=1; } li.removeClass("on").eq(li_Index).addClass("on"); break; case 38: //向上鍵選擇 li_Index--; if(li_Index<1) { li_Index=_len-1; } li.removeClass("on").eq(li_Index).addClass("on"); break; case 13: //enter鍵 var txtData=li.filter(".on").text(), obj = $(textarea).data("at"); add(txtData,obj); hiddenTip(); break; default: }; }, //添加列表綁定事件 TipLiEvent = function(obj) { $at_userslist.find("li").on("click", function() { if($(this).index() == 0) { obj.textarea.focus(); } else { var txtData=$(this).text(); add(txtData,obj); } hiddenTip(); return false; }).not(":first").hover( function() { li_Index=$(this).index(); $(this).addClass("on").siblings().removeClass("on"); return false; }, function() { return false; }); }; }); }})(jQuery);
json2.html的格式一樣,就文字不一樣而已,上面圖就是顯示不同情況。
聯(lián)系客服