轉載:https://www.cnblogs.com/cheerfulCoder/p/4323930.html
寫在前面
最近在segmentfault上看到它的日期輸入控件,感覺挺有意思。好吧,動手寫一個,加到自己的代碼庫裏吧。
然後問題來了,在上面圖片中,我們很明顯的看得出這裏涉及光標位置的控制。比如說當我輸入1993的3之後,光標必須要得插入到-中劃線的下個輸入點。
在網上找了找獲取和設置光標位置的方法,發現是資料是相當的破碎,並沒有一個詳細的介紹。 所以我來一個詳細的。 好了,不要囉嗦。
基本的認識
文本選中區域
光標 頁面中閃爍的光標其實就是特殊的寬度爲0的選區。 簡單理解就是選區的左右邊界交叉形成了光標。 有了這個概念下面的內容就很好理解了。
非IE瀏覽器下的實現
這裏需要用到input元素的兩個屬性。
selectionStart、selectionEnd 選區開始位置,選區結束位置。
二者代表了選中區域的左右邊界。
兩個值默認都是0,所以當我們使用input.focus()方法時,默認光標在文本的開頭。(注意這裏並不是說每次focus調用光標都出現在開頭。是因爲selectionStart的和selectionEnd的值隨着文本輸入而改變,因而光標的位置隨之改變。)
文本選中
我們設置
input.selectionStart = 0; //選中區域左邊界
input.selectionEnd = input.value.length; //選中區域右邊界
上面的代碼可以選中輸入框的全部內容。 等同於input.select();
input.selectionStart = 1; //選中區域左邊界
input.selectionEnd = 4; //選中區域右邊界
上面的代碼選中了234三個字符。
我們如何獲取選中的文本內容呢? 因爲已經知道了selectionStart和selectionEnd,所以用字符串的substring方法
var selection = input.value.substring(input.selectionStart,input.selectionEnd);
光標位置
設置光標
input.selectionStart = 5; //選中區域左邊界
input.selectionEnd = 5; //選中區域右邊界
上面的代碼把光標放到5的後面。
獲取光標位置
直接使用selectionStart和selectionEnd中的任意一個值即光標的位置。
IE瀏覽器下的實現
IE下對於文本流的處理提供了更加強大的支持,不過這裏我只着重於這篇文章的主旨。
用到的方法和屬性先彙總到下面。
createTextRange()、 document.selection.createRange()
moveStart() 、moveEnd() 、move() 、collapse() 、text 、select()
----------------- ---- - - - 下面是詳細的介紹 -----------------------
var range = input.createTextRange(); //創建一個文本選區對象。
這個選區對象默認包含了input的全部文本內容。需要注意的是,這個選區對象是一個抽象的區域。,在調用range.select()方法之前,選區對象的內容並不會被添加選中效果。
range.select(); //將選區對象包含的內容選中。
我們可以用 range.text屬性得到選區包含的文字
選區有兩個類似於其他瀏覽器中selectionStart和selectionEnd屬性的方法, moveStart和moveEnd。
上面我們說過,默認這個選區對象包含input的全部文本內容,所以它的左右邊界分別就是文本的開頭和結尾位置。
moveStart方法用來移動左邊界。 像這樣調用
range.moveStart("character",2); //左邊界右移兩個字符 。 character--字符
range.select(); //將range包含的區域選中。
結果
moveStart和moveEnd都要傳入兩個參數,第一個參數可選值有 character、word、sentence、textedit. 這裏我們只用到character,即根據字符來偏移。 第二個參數代表偏移的多少,正負表示方向。
我們知道左邊界最初默認是0,右邊界默認是文本內容長度值。
我們注意到每次選中range包含區域文本的操作都需要調用range.select()方法,通過select方法來把range對象包含的內容區域選中。這與上面的其他瀏覽器的實現方式貌似有了大的差異,相比之下似乎並沒有那麼方便。但是創建一個包含抽象文字區域的選區對象其實提供了更大的靈活性。 我們甚至於可以創建多個選區對象。
還有一個很有用的方法 collapse, 見名知意,就是將選區對象的範圍壓縮,下面詳細介紹。
collapse可以傳入一個布爾值作爲參數,參數默認值爲true,指示向左還是向右壓縮。
var range = input.createTextRange(); //創建選區對象
//此時選區對象的左邊界爲0,右邊界爲input.value.length;
range.collapse();
//此時選區對象左邊界爲0,右邊界爲0; 相當於將選區向左收縮了,即使右邊界下標等於左邊界下標。
range.select(); //左右邊界重合,可以顯示光標。
效果如圖: collapse(true)相當於讓右邊界下標等於左邊界下標。
再試看看collapse(false)
var range = input.createTextRange(); //創建選區對象
//此時選區對象的左邊界爲0,右邊界爲input.value.length;
range.collapse(false);
//此時選區對象左邊界爲input.value.length,右邊界爲input.value.length; 相當於將選區向右收縮了,即使左邊界下標等於右邊界下標。
//左右邊界重合,可以顯示光標。
range.select();
效果如圖 可以看到,我們使用collapse(false)結合select方法可以很方便的把光標focus到文本框的末尾。
還有一個move方法
var range = input.createTextRange();
range.moveStart("character",2);
range.select(); //圖一
range.move("character",3);
//等價於 range.collpase(true); range.moveStart("character",3);range.moveEnd("character",3); 三步。合一
range.select(); //圖二
這個方法和moveStart有一樣的參數,不過有點難以理解。 上面的代碼相當於------先將選區向左收縮,這時候就相當於一個光標咯,然後將光標右移三個字符。
上面的代碼的兩個圖, 圖一 圖二
當我們要移動光標時,move函數必然是一個非常不錯的選擇。
document.selection.createRange()
這個方法根據當前頁面中的選中文字區域來創建一個選區對象,這個選區對象與createTextRange方法的到選區對象的區別在於,它的選區範圍爲頁面選中文字的區域,即它的左右邊界不再是默認的左最小右最大。
通過這個方法我們可以輕鬆獲取光標在輸入框中的位置。 首先你得理解咯光標和選區的關係。
var range = document.selection.createRange(); //根據頁面中選中區域創建選區對象。 光標也是特殊的選區
range.moveStart("character",-elem.value.length); //移動左邊界到0
var cursorIndex = range.text.length; //選區對象包含文本長度即光標位置
下面剩下的就是對函數的封裝咯。 getCursorKey() , setCursorKey() , getSelection(),setSelection().
function getCursor(elem) {
//IE 9 ,10,其他瀏覽器
if (elem.selectionStart !== undefined) {
return elem.selectionStart;
} else { //IE 6,7,8
var range = document.selection.createRange();
range.moveStart("character", -elem.value.length);
var len = range.text.length;
return len;
}
}
function setCursor(elem, index) {
//IE 9 ,10,其他瀏覽器
if (elem.selectionStart !== undefined) {
elem.selectionStart = index;
elem.selectionEnd = index;
} else { //IE 6,7,8
var range = elem.createTextRange();
range.moveStart("character", -elem.value.length); //左邊界移動到起點
range.move("character", index); //光標放到index位置
range.select();
}
}
function getSelection(elem) {
//IE 9 ,10,其他瀏覽器
if (elem.selectionStart !== undefined) {
return elem.value.substring(elem.selectionStart, elem.selectionEnd);
} else { //IE 6,7,8
var range = document.selection.createRange();
return range.text;
}
}
function setSelection(elem, leftIndex, rightIndex) {
if (elem.selectionStart !== undefined) { //IE 9 ,10,其他瀏覽器
elem.selectionStart = leftIndex;
elem.selectionEnd = rightIndex;
} else { //IE 6,7,8
var range = elem.createTextRange();
range.move("character", -elem.value.length); //光標移到0位置。
//這裏一定是先moveEnd再moveStart
//因爲如果設置了左邊界大於了右邊界,那麼瀏覽器會自動讓右邊界等於左邊界。
range.moveEnd("character", rightIndex);
range.moveStart("character", leftIndex);
range.select();
}
}