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