摘要:我們算出這個(gè)相對(duì)于頁(yè)面左上角的和,就是等下選框相對(duì)于文本框的和的距離,因?yàn)槲覀冞x框是絕對(duì)定位相對(duì)于,所以在加上文本框相對(duì)于的和就是我們選框所要定位的和了。
最近接到了一個(gè)業(yè)務(wù)需求,讓用戶能夠通過(guò)網(wǎng)頁(yè)聊天框的方式在線完成交易,一個(gè)用戶可能有多個(gè)業(yè)務(wù)群,其中一個(gè)功能就是要@人,@這個(gè)功能在現(xiàn)實(shí)的應(yīng)用中經(jīng)常可以遇到,比如微博、QQ都有@功能,今天我們就以前端的方式談?wù)勗趺匆徊讲綄?shí)現(xiàn)一個(gè)@功能。
@功能涉及到的原生APIobj.selectionStart獲取光標(biāo)位置
obj.setSelectionRange(n, n)設(shè)置光標(biāo)位置
keyup事件和keydown事件
1.搭建我們的html文件幾個(gè)地方特別說(shuō)明下:實(shí)際操作中,我們出現(xiàn)了@選框要實(shí)時(shí)更新列表數(shù)據(jù),在這個(gè)dome中我們先用靜態(tài)列表代替,效果是一樣的。然后這個(gè)pre是用來(lái)定位@選框用的,注意pre大小,字體要和輸入框一樣,并將pre絕對(duì)定位到頁(yè)面的左上角,并設(shè)置不可見(jiàn)。
2、實(shí)現(xiàn)@選框出現(xiàn),并將@選框定位到當(dāng)前光標(biāo)右下角
具體實(shí)現(xiàn)思路:檢測(cè)鍵盤(pán)的左邊是否是@字符,如果有的話,將輸入框光標(biāo)前面的內(nèi)容復(fù)制一份到pre,并在pre后面增加一個(gè)span,這個(gè)sapn用來(lái)協(xié)助定位@選框的。我們算出這個(gè)span相對(duì)于頁(yè)面左上角的left和top,就是等下@選框相對(duì)于文本框的left和top的距離,因?yàn)槲覀傽選框是絕對(duì)定位相對(duì)于body,所以在加上文本框相對(duì)于body的offsetLeft和offsetTop就是我們@選框所要定位的left和top了。
//全局定義一個(gè)變量為光標(biāo)位置 var cursor; //文本框綁定keyup事件,檢測(cè)輸入 textapp.addEventListener("keyup", function(e){ //獲取光標(biāo) cursor = textapp.selectionStart; // 當(dāng)前光標(biāo)所在位置的前一位為@字符,出現(xiàn)@選框 if(textapp.value.substring(0,cursor).charAt(cursor-1) === "@"){ // 判斷最后一個(gè)字符是否為@ pre_text.innerHTML = textapp.value.substring(0,cursor); pre_text.innerHTML += ""; var span = document.getElementById("proxy"); var conX = textapp.offsetLeft; var conY = textapp.offsetTop; var spanX = span.offsetLeft + conX; var spanY = span.offsetTop + conY; selectuser.style.left = spanX + "px"; selectuser.style.top = spanY + "px"; selectuser.style.display = "block"; //設(shè)置@選框的默認(rèn)樣式 listSet(); }else{ selectuser.style.display = "none"; } }) // @框默認(rèn)設(shè)置 function listSet() { var list = $("#selectlist"); list.focus(); $("#selectlist").find("li").eq(0).addClass("hover").siblings("li").removeClass("hover"); $("#selectuser").scrollTop(0); }3.鍵盤(pán)直接操作@選框
當(dāng)我們的@選框出現(xiàn)了,并且定位好了,出現(xiàn)在我們想要的位置了,我們直接用鍵盤(pán)上下去選擇所要@的人了(鼠標(biāo)點(diǎn)擊選中情況等下介紹)。這里我們要考慮的點(diǎn)有兩個(gè):1.當(dāng)我們光標(biāo)在輸入框最后,我們按上下左右光標(biāo)就會(huì)變化位置。2.選擇之后光標(biāo)位置的變化。
1的解決辦法是:我們光標(biāo)位置的變化是在keydown的時(shí)候執(zhí)行的,keydown是先于我們的keyup之前執(zhí)行的,所以我們就要在keydown的時(shí)候就阻止默認(rèn),防止光標(biāo)移動(dòng)
textapp.addEventListener("keydown", function(e){ //建立在@選框出現(xiàn)的情況下 if(selectuser.style.display == "block"){ var code = e.keyCode; //左右回車(chē)時(shí)阻止默認(rèn),防止光標(biāo)移動(dòng) if(code == 38 || code == 40 || code == 13){ e.preventDefault(); } } })
2.選中@人后,我們用setSelectionRange來(lái)設(shè)置光標(biāo)的位置,將下面這段代碼輸入框keyup綁定事件里面,放在最前面
// 當(dāng)@選框存在時(shí),判斷鍵盤(pán)上移,下移,以及回車(chē)選中事件 if(selectuser.style.display == "block"){ var code = e.keyCode; if(code == 38){ // 上移 preCode(); return; }else if (code == 40){ // 下移 nextCode(); return; }else if(code == 13){ //回車(chē)選中@人 var textname = ""; $("#selectlist").find("li").each(function(){ if($(this).hasClass("hover")){ textname = $(this).html(); } }); //@完后文本框顯示內(nèi)容 $("#app").val(getText($("#app").val(), cursor, textname)); //添加后光標(biāo)的位置 var n = textname.length + 1 + cursor; //設(shè)置光標(biāo)的位置 textapp.setSelectionRange(n, n); //選中后隱藏@選框 $("#selectuser").hide(); return; } }
上面這段代碼我們用到了三個(gè)函數(shù)
// 鍵盤(pán)上移 function preCode() { var index = $("#selectlist").find(".hover").index(); if(index == 0){ return; }else{ index--; $("#selectuser").scrollTop(index * 26); $("#selectlist").find("li").eq(index).addClass("hover").siblings("li").removeClass("hover"); } } // 鍵盤(pán)下移 function nextCode() { var len = $("#selectlist").find("li").length; var index = $("#selectlist").find(".hover").index(); if(index == len-1){ return; }else{ index++; $("#selectuser").scrollTop(index * 26); $("#selectlist").find("li").eq(index).addClass("hover").siblings("li").removeClass("hover"); } } //@人的文本格式,為后面加一個(gè)空格,后面用到 function getText(app, cursor, textname) { var text1 = app.substring(0, cursor); var text2 = app.substring(cursor); return text1 + textname + " " + text2; }4.提交操作時(shí),取出有效的@人
當(dāng)我們消息輸入完成后,點(diǎn)擊發(fā)送(我們這里用個(gè)提交按鈕)。我們要檢測(cè)這個(gè)消息中是否有@人,并把當(dāng)前這條消息有效的@人取出來(lái),這里注意并不是說(shuō)我們之前選中了@某個(gè)人后就有效了,可能在這個(gè)人的名字中我又輸入了其他的字符。所以我們要在發(fā)送消息的時(shí)候做一次檢查,把有效的@人提取出來(lái),并且以后臺(tái)規(guī)定的數(shù)據(jù)格式。(我們暫且規(guī)定為數(shù)組吧)。
// 提交 $("#submit").on("click", function() { var msg = $("#app").val(); //檢測(cè)輸入框是否為空 if(msg === ""){ alert("內(nèi)容不能為空!"); return; } //返回有效@人列表 var arr = handleMsg(msg); }); //操作信息提取有效@人 function handleMsg(msg) { //存放有效@人id的數(shù)組 var At = []; //正則驗(yàn)證吧以@開(kāi)頭空格結(jié)束的選出來(lái)已數(shù)組的形式 var arrAt = msg.match(/@{1}([u4e00-u9fa5]|w)+s{1}/g); //說(shuō)明沒(méi)有@人,直接韓慧 if(arrAt === null){ console.log("沒(méi)有選中@的人!"); return At; } // 對(duì)arrAt數(shù)組即當(dāng)前信息@人的列表進(jìn)行遍歷 for (var i = 0; i < arrAt.length; i++) { var username = arrAt[i].replace("@", "").trim(); // 對(duì)比當(dāng)前群組人選 var grounpuser = $("#selectlist").find("li"); for (var j = 0; j < grounpuser.length; j++) { //如果名字相同,則把id放進(jìn)數(shù)組內(nèi)容 if(username == grounpuser.eq(j).html()){ var uid = grounpuser.eq(j).attr("uid"); At.push(uid); break; } }; }; return At; }完結(jié)
好了,一個(gè)@的功能已經(jīng)基本實(shí)現(xiàn)了,剩下的就是通過(guò)ajax與后臺(tái)的交互了。如果你覺(jué)得本篇文章對(duì)你有收獲請(qǐng)贊下,也可以關(guān)注下我,分享工作,學(xué)習(xí)的前端個(gè)人感悟分享。github
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/79783.html
摘要:我們的功能需要用到的接口事件讀取完成,無(wú)論成功與否,還有方法將文件讀取為。檢測(cè)是否為圖片類(lèi)型圖片的編碼這里設(shè)置獲取的數(shù)據(jù)獲取后臺(tái)的給的將文件讀取為上傳事件當(dāng)?shù)臅r(shí)候說(shuō)明我們成功的把圖片傳上七牛了,并且七牛給我們返回了一個(gè)字符串。 最近在做的一個(gè)聊天消息的功能。有個(gè)圖片上傳的功能,可以通過(guò)按鈕上傳也可以通過(guò)Ctrl+V上傳。按鈕上傳的我們可以通過(guò)七牛的API就可以做了,我們現(xiàn)在來(lái)說(shuō)說(shuō)Ctr...
摘要:我們算出這個(gè)相對(duì)于頁(yè)面左上角的和,就是等下選框相對(duì)于文本框的和的距離,因?yàn)槲覀冞x框是絕對(duì)定位相對(duì)于,所以在加上文本框相對(duì)于的和就是我們選框所要定位的和了。 最近接到了一個(gè)業(yè)務(wù)需求,讓用戶能夠通過(guò)網(wǎng)頁(yè)聊天框的方式在線完成交易,一個(gè)用戶可能有多個(gè)業(yè)務(wù)群,其中一個(gè)功能就是要@人,@這個(gè)功能在現(xiàn)實(shí)的應(yīng)用中經(jīng)常可以遇到,比如微博、QQ都有@功能,今天我們就以前端的方式談?wù)勗趺匆徊讲綄?shí)現(xiàn)一個(gè)@功能...
摘要:函數(shù)式編程與面向?qū)ο缶幊叹幊痰谋举|(zhì)之劍目錄編程的本質(zhì)讀到兩篇文章寫(xiě)的不錯(cuò)綜合摘錄一下復(fù)合是編程的本質(zhì)函數(shù)式程序員在洞察問(wèn)題方面會(huì)遵循一個(gè)奇特的路線。在面向?qū)ο缶幊讨校?lèi)或接口的聲明就是表面。 函數(shù)式編程與面向?qū)ο缶幊蘙5]:編程的本質(zhì) 之劍 2016.5.6 01:26:31 編程的本質(zhì) 讀到兩篇文章,寫(xiě)的不錯(cuò), 綜合摘錄一下 復(fù)合是編程的本質(zhì) 函數(shù)式程序員在洞察問(wèn)題方面會(huì)遵循...
摘要:區(qū)塊鏈科技原罪還是交往理性迄今為止,我們尚未見(jiàn)到從中本聰開(kāi)始的任何一位區(qū)塊鏈開(kāi)發(fā)者提及哈貝馬斯,但區(qū)塊鏈卻奇妙契合了哈貝馬斯對(duì)理想話語(yǔ)情境的描述。 生活在我們這個(gè)時(shí)代的人,不可避免的活在消費(fèi)控制之下。著名的哲學(xué)家馬爾庫(kù)塞說(shuō),人們似乎是為商品而生活。小轎車(chē)、高清晰度的傳真裝置、錯(cuò)層式家庭住宅以及廚房設(shè)備成了人們生活的靈魂。人們被被消費(fèi)欲望所控制,自主性喪失,個(gè)性泯滅,成為單向度的人。 s...
摘要:靜態(tài)變量序列化情境查看清單的代碼。之所以打印的原因在于序列化時(shí),并不保存靜態(tài)變量,這其實(shí)比較容易理解,序列化保存的是對(duì)象的狀態(tài),靜態(tài)變量屬于類(lèi)的狀態(tài),因此序列化并不保存靜態(tài)變量。解決要想將父類(lèi)對(duì)象也序列化,就需要讓父類(lèi)也實(shí)現(xiàn)接口。 原文 https://www.ibm.com/developer... 引言 將 Java 對(duì)象序列化為二進(jìn)制文件的 Java 序列化技術(shù)是 Java 系...
閱讀 533·2023-04-26 01:39
閱讀 4485·2021-11-16 11:45
閱讀 2610·2021-09-27 13:37
閱讀 882·2021-09-01 10:50
閱讀 3579·2021-08-16 10:50
閱讀 2217·2019-08-30 15:55
閱讀 2979·2019-08-30 15:55
閱讀 2259·2019-08-30 14:07