表单文本域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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章