有接到需求,需要做一個(gè)輸入#號(hào),彈出下拉框,進(jìn)行選擇并替換到里面的內(nèi)容。如下圖,支持聯(lián)想。做的不好,還望提出意見。
可能的情況
1.用戶順序輸入#號(hào),然后彈出下拉框。
2.用戶左右鍵移動(dòng),再輸入#號(hào)彈出下拉框。
3.用戶鼠標(biāo)點(diǎn)擊某個(gè)位置在輸入#號(hào),彈出下拉框。
等等
思路
最簡單的方法 -- jquery-UI 封裝的 Autocomplete() 方法,誰用誰知道,好用!
自己實(shí)現(xiàn)
項(xiàng)目中使用vue作為技術(shù)棧,交互還是比較方便的。
這里需要了解一下幾個(gè)知識(shí):
1.window.getSelection() 方法對(duì)當(dāng)前激活選中去(文本高亮處)進(jìn)行操作。移步JavaScript標(biāo)準(zhǔn)Selection操作 - Rain Man - 博客園
2.可輸入div,div的屬性 contenteditable,請(qǐng)移步?vue2 實(shí)現(xiàn) div contenteditable="true" 類似于 v-model 的效果 - acco - SegmentFault 思否
3.dom.getBoundingClientRect() 獲得頁面中某個(gè)元素的左,上,右和下分別相對(duì)瀏覽器視窗的位置。
4.插入節(jié)點(diǎn) insertNode,創(chuàng)建節(jié)點(diǎn) createElement,移除子節(jié)點(diǎn) removeChild? 了解一下JS在頁面光標(biāo)位置插入新內(nèi)容 - 精神領(lǐng)袖 - 博客園
總體思路:
? ? ? ? ? ? 首先獲取輸入框中輸入#號(hào)時(shí)光標(biāo)的位置(只能獲取到文本中第幾位,非可視區(qū)域的位置),并保存其位置。然后在當(dāng)前位置插入一個(gè)創(chuàng)建的節(jié)點(diǎn),并獲取它的可視區(qū)域位置(left,top值),保存后刪除該節(jié)點(diǎn)。然后通過簡單運(yùn)算,獲取到下拉框的絕對(duì)定位的left,top值,賦值給下拉框并讓其顯示。點(diǎn)擊下拉框中的任意一項(xiàng),根據(jù)輸入#號(hào)時(shí)的光標(biāo)位置進(jìn)行字符串的截取并添加。這樣就會(huì)插入到輸入框中。
效果如圖
code-img
注意項(xiàng)
1.Chrome 瀏覽器,input標(biāo)簽oninput事件中,有 event.data 屬性,即為輸入的值,剛開始就是使用的 這個(gè)屬性,在chrome完美運(yùn)行,退格鍵,左右鍵完美運(yùn)行,無bug。但是忽略了一點(diǎn),這個(gè)屬性在 firefox,ie不存在。故在這里,不能夠?qū)崿F(xiàn)。
2.onblur 事件觸發(fā) 比 onclick 事件快。在彈出下拉框時(shí),我們需要去點(diǎn)擊下拉框的內(nèi)容,就內(nèi)容插入到我們input輸入框內(nèi),并將下拉框隱藏。自然而然的會(huì)寫一個(gè) onblur事件來 是 show 為false,在下拉框的ul中執(zhí)行點(diǎn)擊操作。在實(shí)際中 blur 事件先觸發(fā),下拉框就會(huì)消失掉,這個(gè)時(shí)候可點(diǎn)擊的dom結(jié)構(gòu)已不存在,也就不會(huì)觸發(fā)該事件。解決方法是在 blur事件中,增加一個(gè)延時(shí)器,延時(shí) 將 show 置為 false;
3.可輸入的div,測試中不支持input事件。如有錯(cuò)誤,還望提出。