<textarea>: 允许使用TAB键进行缩进

陪她去流浪 桃子 2015年03月26日 编辑 阅读次数:5023

现状

默认情况下,<textarea> 元素本身并不处理TAB键,一旦你按下TAB键,输入焦点就会被浏览器切换到下一个元素,导致你无法在其中输入TAB键。

要想插入TAB键的话,也就只能通过JavaScript来手动处理按键消息了。

需求

通常,按下TAB的效果有以下几种:

  • 仅按下 TAB
    • 如果没有选中文本,在当前光标处插入一个TAB字符,光标后移。
    • 如果只选中一行文本,则选中的文本被替换为一个TAB字符,光标后移一个。
    • 如果选中了多行文本,则所有选中文本的行前面被插入一个TAB字符,整体后移一个TAB字符宽。
  • 按下了Shift+TAB
    • 如果没有选中文本,如果光标前面有TAB字符,则删除光标前面最近的那个TAB。
    • 如果有选中文本,这个没有固定的操作,看实现者。
    • 如果选中多行文本,则多行文本中行首字符是TAB的行最前面的那个TAB字符被删除,整体前移。

实现

大致的操作就是上面所列出的,以下是新手我的实现:

function enableTabIndent(t,e){
	if(e.keyCode === 9){
		var start = t.selectionStart;
		var end = t.selectionEnd;

		var that = jq(t);

		var value = that.val();
		var before = value.substring(0, start);
		var after = value.substring(end);
		var selArray = value.substring(start, end).split('\n');

		var isIndent = !e.shiftKey;

		if(isIndent){
			if(start === end || selArray.length === 1){
				that.val(before + '\t' + after);
				t.selectionStart = t.selectionEnd = start + 1;
			} else {
				var sel = '\t' + selArray.join('\n\t');
				that.val(before + sel + after);
				t.selectionStart = start + 1;
				t.selectionEnd = end + selArray.length; 
			}
		} else {
			var reduceEnd = 0;
			var reduceStart = false;

			if(selArray.length > 1) {
				selArray.forEach(function(x, i, a){
					if(i>0 && x.length>0 &&  x[0]==='\t'){
						a[i] = x.substring(1);
						reduceEnd++;
					}
				});
				sel = selArray.join('\n');
			} else {
				sel = selArray[0];
			}

			var b1 = '',b2 = '';
			if(before.length){
				var npos = before.lastIndexOf('\n');
				if(npos !== -1){
					b1 = before.substring(0, npos+1);
					b2 = before.substring(npos+1);
				} else {
					b1 = '';
					b2 = before;
				}

				sel = b2 + sel;
			}

			if(sel.length && sel[0]==='\t'){
				sel = sel.substring(1);
				reduceStart = true;
			}

			that.val(b1 + sel + after);
			t.selectionStart = start + (reduceStart ? -1 : 0);
			t.selectionEnd = end - (reduceEnd + (reduceStart ? 1 : 0));
		}
		return true;
	}
	return false;
}

效果

对于下面的代码:

<div>
	<textarea style="width: 50%; height: 100px;"></textarea><br>
	<textarea style="width: 50%; height: 100px;" id="tabbed"></textarea>
</div>
<script type="text/javascript">
	document.getElementById('tabbed').onkeydown = function(e){
		if(enableTabIndent(this, e)){
			e.preventDefault();
		}
	};
</script>

所产生的效果如下,可以输入点文本,然后感受下:


标签:javascript · 代码片段 · HTML