自定義短信模板,要求:可以插入關鍵字,當然是可以在點擊到文本域中的任意位置,關鍵字以中括號包裹的形式出現【關鍵字】,刪除關鍵字要整個關鍵都刪掉,而不是自己全刪除。
效果圖
這里說下我的思路,要完成這樣一個功能,分為以下幾點:
1.在指定位置插入關鍵字
2.刪除關鍵字要整個刪除掉,并且關鍵字是不可編輯的,用戶也是不可以輸入中文中括號的
首先我們列一下難點
1.在任意位置插入,那肯定要拿到位置坐標,如果獲取這個位置?
2.關鍵字是用中文中括號包裹的,那么用戶就不可以去使用中文中括號,怎么阻止用戶輸入呢?
3.既然是關鍵字自然是不可以編輯的,怎么讓它不可編輯?
4.中文中括號可英文中括號keyCode是一樣的,怎么處理?
5.當編輯區域失去焦點的時候,我們立即點關鍵字肯定就是要插入,但是點擊其他地方怎么處理?
6.刪除關鍵字的時候,如何一次按鍵就整個都刪掉?
現在我們來把上面的難點一一解答
1.關于光標位置,我上一篇文章中有寫到,這里就不多說了,http://www.lxweimin.com/p/19a507cd5fd7.
2.關于第2,3,4一起來說。首先為了防止我們識別關鍵字出問題,那么就要阻止用戶自己輸入中括號,說道阻止輸入某個字符,大家很容想到,那就是在輸入的瞬間就把它刪除掉,這個沒錯。我們在判斷按鍵為左中括號時候去刪除的時候,會發現并不能完成整個中括號的刪除,因為落下一個右中括號。沒錯,第一個坑出現了,這是為什么,大家有沒有注意到,每次你輸入中文中括號的時候,其實只需要按左邊中括號就會左右都出現,大括號小括號都是這樣。
【】按下左,左右一起出現
好,我們知道了問題所在,那就在右括號按下的時候刪掉兩個字符,可是,你會發現,如果只按右中括號的時候,他就真的只出現右中括號,所以呢,分開處理。
這次沒問題了吧,可是你會發現依然是剩下右邊的括號沒刪除,而且還把前面的括號前的一個字符刪掉了,坑吧?這就是第二個坑,你在判斷keyCode的時候其實會有三次,第一次是左中括號keyCode,第二次是右中括號,第三次是左箭頭。而第二次第三次并不是你按下的,是第一按下之后自動帶出的。所以當你按下左中括號之后,其實最后光標是跑到了括號中。
【|】
obj.addEventListener('keyup', function(e) {
//每次在文本域中輸入的時候都要獲取其光標位置,以便于其他操作
cursorIndex = getFocus(obj);
//由于我們是禁止輸入中文中括號的,而中文中括號輸入左右情況不同,需要分別處理
if (e.keyCode == 219) {
e.preventDefault();
//這里獲取到光標左側的內容
var leftChar = obj.value.slice(cursorIndex - 1, cursorIndex);
//只有輸入結束的是右中括號,而且它的前一個字符是左中括號才把它刪除,防止把關鍵字刪除掉
if (/\】/g.test(leftChar) && obj.value.charAt(cursorIndex - 2) === '【') {
obj.value = obj.value.slice(0, cursorIndex - 2) + obj.value.slice(cursorIndex, obj.value.length);
}
} else if (e.keyCode == 221) {
e.preventDefault();
//右中括號就好辦多了,因為它不會自動帶出左中括號
var leftChar = obj.value.slice(cursorIndex - 1, cursorIndex);
if (/\】/g.test(leftChar)) {
obj.value = obj.value.slice(0, cursorIndex - 1) + obj.value.slice(cursorIndex, obj.value.length);
}
}
//防止上下左右鍵移動光標進入關鍵字中
if ((e.keyCode == 37 || e.keyCode == 39 || e.keyCode == 38 || e.keyCode == 40) && lastKeyCode !== 219) {
dealFocusMove(obj, cursorIndex);
} else if (e.keyCode == 8) {
//backspace刪除的時候刪除整個關鍵字
dealFocusL(obj, cursorIndex, allKeyWords);
} else if (e.keyCode == 46) {
//delete刪除的時候也是刪除整個關鍵字
dealFocusR(obj, cursorIndex, allKeyWords)
}
if (e.keyCode !== 37 && e.keyCode !== 39) {
//這里防止手動按得左右鍵影響左中括號判斷
lastKeyCode = e.keyCode;
}
}, false);
那這咋搞,還要分別刪除么?不用的,我們只要不讓他跑到中間就可以了,對就是preventDefault()。有疑問了吧?沒錯,這個無法阻止中文按鍵。
關鍵字不可編輯,但是文本怎么能不編輯?。烤庉嫷年P鍵是什么,就是有光標啊,那我們不讓光標進入關鍵字不就行了,這里還順帶解決了的防止鼠標點擊關鍵字中間。我想的思路是,關鍵字的中括號是成對出現的,那么光標進入了,光標前面的內容中中括號自然不是成對的,這就是判斷條件,把它挪出來就可以了。當然從按左右鍵要分別處理,因為是向不同方向越過整個關鍵字,上下鍵就簡單了,都放把光標設置在關鍵字左邊就可以了。
if ((e.keyCode == 37 || e.keyCode == 39) && lastKeyCode === 219) {
//這里是防止按下中文中括號左鍵的時候帶動左右鍵的按下,這樣保證光標一直在最后
e.preventDefault();
}
3.怎么處理點擊文本域,立即點擊關鍵字是插入,點擊其他地方之后再點擊關鍵字不可插入?這里我定義了一個參數存儲光標位置,當點擊其他位置的時候就讓光標置空,而點擊關鍵字的時候判斷一下光標位置是否存在就可以了
if (cursorIndex !== null) {
//這里判斷是否是我們要點擊的是不是關鍵字
if (e.target.tagName !== "TEXTAREA" && e.target.getAttribute('isFocus')) {
//插入關鍵字
} else if (e.target.tagName == "TEXTAREA" && e.target.getAttribute('isFocus')) {
//點擊文本區域操作
} else {
//點擊其他地方要將光標位置置空,防止點擊關鍵字添加
cursorIndex = null;
}
}
4.刪除整個關鍵字,這里還是用關于如何防止光標進入關鍵字的方式。只要發現不成對,就把最近的另一半到光標之間的刪除
【關鍵字| 或者 |關鍵字】
就是backspace和delete兩種,當然在處理的時候用了一些小技巧,就是正則表達式的RegExp.lastIndex,最后一次匹配到的位置,還有其他,看代碼吧。