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