天天看點

textarea的中文輸入判斷與搜狗輸入法的特殊行為

雖然要講解的知識點是通用的,但是還是要介紹下我的應用場景和測試環境。

我的應用是一塊使用Html Canvas開發的黑闆,在黑闆上實作簡單的文字編輯功能。

textarea的中文輸入判斷與搜狗輸入法的特殊行為

1.png

使用Canvas實作文字編輯器的細節這裡就不講了,原理大緻都相同。一個必要條件是需要一個隐藏的textarea監聽文字輸入,因為canvas是無法記錄文字選中、換行等資訊的,也沒有辦法直接激活輸入法和軟鍵盤。textarea 如下:

很多情況下,我們需要實時監控文字輸入的變化,下面是幾種選擇。

監聽keydown 和 keyup事件是最直接的方法,通過keyCode我們可以擷取按鍵值。

input事件在keydown事件觸發之後被觸發,這是input類型元素使用的标準事件,表示有文字輸入。

textarea的中文輸入判斷與搜狗輸入法的特殊行為

2.png

從上圖中我們可以看到,觸發的事件為InputEvent,從該事件對象的data屬性中可以擷取到目前輸入的按鍵值。

正常情況下,每一次按鍵都會觸發oninput事件。

該事件主要是為了相容IE9及以下浏覽器對oninput事件的處理。

在監聽到 onpropertychange 事件後,可以使用 event 的 propertyName 屬性來擷取發生變化的屬性名稱。

我們把及時響應鍵盤按鍵輸入單個按鍵代表的字元到文本框的行為稱為直接輸入模式,相對的非直接輸入模式,通常是輸入法攔截了按鍵消息之後的輸入,以中文輸入法為例,通常是回車或者空格後完成輸入。

textarea的中文輸入判斷與搜狗輸入法的特殊行為

3.png

在非直接輸入模式下,我們期待的結果是當使用者完成輸入的時候(按了空格或者Enter鍵)觸發一次oninput事件。但是很不幸,每次按鍵都會觸發oninput事件,這會導緻我們不知道使用者正在輸入的是不是中文,也不知道什麼時候結束的輸入,也就沒辦法及時對輸入的中文進行處理。 為了解決這個問題,我們看一下非直接輸入情況下幾個有用的屬性和事件。

這兩個屬性是textarea對文字選中區域的辨別,從0開始,簡化分析,我們隻考慮正常文字輸入,不考慮有選中的情況,首先是直接輸入模式。

textarea的中文輸入判斷與搜狗輸入法的特殊行為

4.png

上圖是我在oninput事件中打的日志,可以明顯的看到每次oninput觸發之後,selectionStart和selectionEnd的值都相同而且表示最後一個文本,視覺上是我們看到的光标所在的位置,如果我們挪動光标,這兩個值也會變化。這裡我們提取兩個關鍵特征,在及時輸入的情況下:

selectionStart和selectionEnd随光标位置變化而變化

selectionStart和selectionEnd值相等

下面我們再看非直接輸入模式。

textarea的中文輸入判斷與搜狗輸入法的特殊行為

5.png

從上圖中,我們可以看到在非直接輸入模式下,在未完成輸入之前,selectionStart一直為0,selectonEnd随着輸入一直變化。完成輸入時,selectionStart與selectonEnd值會相等。

從0.3.1的圖中我們可以看到拼音輸入法輸入過程中,value值的變化,在完成輸入之前這個值是由輸入法控制的,完成之後,value的值會變為輸入的文字内容。

這是一對事件,當非直接輸入開始第一個按鍵的時候,觸發compositionstart事件,非直接輸入結束的時候觸發compositionend事件, 在直接輸入情況下,這兩個事件都不會觸發。我們添加對這兩個事件的監聽:

textarea的中文輸入判斷與搜狗輸入法的特殊行為

6.png

觀察上圖的輸出内容,各個事件的執行順序為:

keydown-->compositionstart-->input-->keyup....-->input-->compositionend-->keyup。

現在我們觀察下在非直接模式下,按鍵的值。

textarea的中文輸入判斷與搜狗輸入法的特殊行為

7.png

通過上圖,我們可以看到不論你按下的是什麼鍵,keycode都被重置為229了。當然這并不是什麼标準,不同輸入法的行為還是不一樣的。不過目前我們能接觸到的中文輸入法,正常情況下都是229。

通過上面的分析,我們重新整理下及時響應非直接輸入的思路。

響應compositionstart事件和compositionend事件

比較selectionStart 和 selectionEnd是否相等。通常需要一個變量來辨別開始和結束,考慮有選中的情況,這兩個值可能會經曆“相等--不等--相等”(或者 “不等--不等(相差為1)--不等(值增加)--相等”)的流程。

*判斷按鍵的code是否為229,當然這也需要額外的變量來記錄開始,還需要結合electionStart 和 selectionEnd才能判斷出結束。

下面以selectionStart 和 selectionEnd為例,判斷中文輸入的開始和結束(非完整代碼)。

上面的代碼引入了isCompositionsting變量,結合selectionStart和selectionEnd來做文字處理。其他方法同理,這裡就不過多講解了。下面我們來分析點異常情況。

textarea的中文輸入判斷與搜狗輸入法的特殊行為

8.png

這是我安裝的最新的搜狗輸入法,下面要說的非正常情況,隻在這一個版本下會出現。

我們在代碼中對keydown,keyup,input,compositionstart和compositionend同時做事件監聽,然後使用這個版本的搜狗輸入法做輸入。結果如下:

textarea的中文輸入判斷與搜狗輸入法的特殊行為

9.png

在未按下回車或者空格鍵之前,我們看到:

textarea隻響應了keydown和keyup事件

keyup時keyCode并不是229

過程中沒有觸發input事件

再看結束輸入時的情況:

textarea的中文輸入判斷與搜狗輸入法的特殊行為

10.png

上圖紅框内的内容為結束輸入時的記錄,此時觸發一次input事件,selectionStart和selectionEnd相等。

這種情況,結束輸入觸發一次input,我倒是認為很合理的做法,這樣很多情況我們不用關心是否是中文輸入了,input的時候擷取新的value,記錄上一次的selectionstart就可以了。

這種特殊行為我沒有具體研究是輸入法本身的問題,還是和浏覽器、作業系統共同作用的結果。如果你編寫類似的程式,需要額外注意下。

本篇文章隻是分析記錄了一些現象,并沒有什麼技術含量,歡迎留言讨論。

textarea的中文輸入判斷與搜狗輸入法的特殊行為

玄魂工作室

本文轉自玄魂部落格園部落格,原文連結:http://www.cnblogs.com/xuanhun/p/7053782.html,如需轉載請自行聯系原作者