表單文本域Tab鍵不能縮進文字的解決方案

最近希望實現類似w3c school那種左邊輸入html、css代碼,右邊呈現界面功能的網頁,於是想到用兩個textarea文本域來分別實現html、css的輸入。但在敲文本時,因爲經常使用Tab鍵縮進不由自主的想用Tab鍵,但發現並沒有想要的效果。想來也是通常我們使用Tab鍵的方式是在輸入完用戶名,切換到密碼域,用來切換標籤的。但此處如果還是按照這樣的默認方式的話,用戶體驗肯定很差,這是我們不能容忍的。所以去網上查了一些資料來解決這個問題。

說起來解決方法也挺簡單的,關鍵是用到了selectionStart和selectionEnd這個屬性。IE9+/Firefox/Safari/Chrome/Opera均支持這兩個屬性。通常這兩個屬性是用在選擇文本時的,用來確定選擇的位置。這兩個屬性可讀可寫。此處摘取JavaScript高級程序設計(421頁)的原話:

雖然通過select事件,我們可以知道用戶什麼時候選擇了文本,但仍然不知道用戶選擇了什麼文本。HTML5通過一些擴展方案解決了這個問題,以便更順利的取得選擇的文本。該規範採取的方式是添加兩個屬性:selectionStart和selectionEnd。這兩個屬性中保存的是基於0的數值,表示所選擇文本的範圍(即文本選區開頭和結尾的偏移量)。因此,要取得用戶在文本框中選擇的文本,可以採用以下代碼。

function getSelectedText(textbox){
    return textbox.value.substring(textbox.selectionStart,textbox.selectionEnd);
}

縮進的原理其實也是一樣的。第一步,在我們想要縮進的位置,取得當前的文本,並在當前選擇位置添加若干個字符,重新編排文本域的內容;第二步,將selectionStart和selectionEnd兩個屬性的值置爲縮進後的位置就可以了;第三步,阻止Tab鍵的默認行爲。三步缺一不可,當然還是要監聽鍵盤事件的。其實裏面還有一個坑,馬上就講到了。先來看代碼:

$('#css').addEventListener('keydown',function(e){
  if(e.keyCode===9){
    var position=this.selectionStart+2;//此處我用了兩個空格表示縮進,其實無所謂幾個,只要和下面保持一致就好了。
    this.value=this.value.substr(0,this.selectionStart)+'  '+this.value.substr(this.selectionStart);
    this.selectionStart=position;
    this.selectionEnd=position;
    this.focus();
    e.preventDefault();
  }
},false);

代碼乍一看確實挺簡單的,我想說的坑在那裏呢?其實就在獲取縮進後的位置上。此處我是先把縮進後的位置保存在position裏面然後又賦值給selectionStart和selectionEnd,如果我不這樣做呢,比如直接this.selectionStart=this.selectionStart+4; this.selectionEnd=this.selectionStart;呢?大家先想一想。


好了,邏輯上是沒錯,但實際上卻錯了。爲什麼呢?關鍵就在於它的位置:它是放在了對文本域內容重新賦值之後。對文本域重新賦值即改變其value值後,此時的selectionStart已經變化了,變到了文本域內容的結尾,不信你可以console.log()一下試試。很不可思議對吧,其實這也很好理解。想想我們輸入的過程,當對文本域賦值後,此時我們的光標已經移到了最後。這也一樣,對文本域value重新賦值,selectionStart也移到了最後。所以用selectionStart+4得不到正確的結果,因此要在捕捉到鍵盤碼爲9時,先把當前位置或當前位置+2保存下來。

另外,還要說一點就是必須要對this.selectionStartthis.selectionEnd賦值,因爲之前說到過這兩個屬性是標記選擇文本的位置,若兩個值不一樣,那就是選擇一段文本了,這裏不賦值的話就是選中了縮進位置至末尾的片段了,而非一個閃動的光標了。好了,就是這樣。

如有不正之處,請不吝指正。

參考資料:JavaScript讓Textarea支持tab按鍵

發佈了21 篇原創文章 · 獲贊 27 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章