如何处理textarea中的<tab>?

IT技术 javascript jquery html
2021-03-06 04:52:16

我想要一个处理按Tab情况的 textarea

默认情况下,如果您按Tab键,则焦点会离开 textarea。但是当用户想在 textarea 中输入tab的情况下呢?

我可以捕获此事件并将焦点返回到 textarea 并将选项卡添加到当前光标位置吗?

6个回答

您可以:http : //jsfiddle.net/sdDVf/8/


$("textarea").keydown(function(e) {
    if(e.keyCode === 9) { // tab was pressed
        // get caret position/selection
        var start = this.selectionStart;
        var end = this.selectionEnd;

        var $this = $(this);
        var value = $this.val();

        // set textarea value to: text before caret + tab + text after caret
        $this.val(value.substring(0, start)
                    + "\t"
                    + value.substring(end));

        // put caret at right position again (add one for the tab)
        this.selectionStart = this.selectionEnd = start + 1;

        // prevent the focus lose
        e.preventDefault();
    }
});
不知道如何/为什么会错过这个,在最后一个子字符串调用start应该作为第一个参数给出:+ value.substring(start, end));-- 否则在选择文本时使用 Tab 键会擦除文本。
2021-04-19 04:52:16
@sergzach:我的解决方案在 IE8 中根本不起作用,因为它不支持selectionStart/ selectionEnd您必须创建文本范围,但我仍然不明白这是如何工作的,恐怕...
2021-04-23 04:52:16
@Amine:防止浏览器默认的tab功能。我现在认为没有必要。我将对此进行搜索。编辑:return false似乎包括preventDefaultstackoverflow.com/questions/1357118/...
2021-04-26 04:52:16
也实现了选择覆盖。
2021-04-30 04:52:16
这会阻止浏览器撤消功能 (Ctrl+z)
2021-05-11 04:52:16

这是不需要 JQuery 的 pimvdb 答案的修改版本:

document.querySelector("textarea").addEventListener('keydown',function(e) {
    if(e.keyCode === 9) { // tab was pressed
        // get caret position/selection
        var start = this.selectionStart;
        var end = this.selectionEnd;

        var target = e.target;
        var value = target.value;

        // set textarea value to: text before caret + tab + text after caret
        target.value = value.substring(0, start)
                    + "\t"
                    + value.substring(end);

        // put caret at right position again (add one for the tab)
        this.selectionStart = this.selectionEnd = start + 1;

        // prevent the focus lose
        e.preventDefault();
    }
},false);

我在 Firefox 21.0 和 Chrome 27 上测试过。不知道它是否适用于其他任何地方。

要使这种方法发挥作用,您需要将eventListener附加各个 DOM 元素。要做到这一点:1) 获取所有元素document.querySelectorAll("textarea")2) 遍历数组以将事件侦听器附加到每个元素。那么它应该工作
2021-04-17 04:52:16
打破撤消功能作为接受的答案。
2021-05-11 04:52:16
要将其应用于所有 textarea 使用 querySelectorAll,枚举返回的列表,并将事件侦听器添加到每个元素。
2021-05-13 04:52:16

天哪,以前的所有答案都未能提供通常体面的(即对于程序员)选项卡控件。

也就是说,点击TAB选择的行将缩进这些行,并SHIFTTAB取消它们的缩进。

_edited(2016 年 11 月):keyCode 替换为 charCode || keyCode,每个KeyboardEvent.charCode - Web APIs | MDN

(function($) {
  $.fn.enableSmartTab = function() {
    var $this;
    $this = $(this);
    $this.keydown(function(e) {
      var after, before, end, lastNewLine, changeLength, re, replace, selection, start, val;
      if ((e.charCode === 9 || e.keyCode === 9) && !e.altKey && !e.ctrlKey && !e.metaKey) {
        e.preventDefault();
        start = this.selectionStart;
        end = this.selectionEnd;
        val = $this.val();
        before = val.substring(0, start);
        after = val.substring(end);
        replace = true;
        if (start !== end) {
          selection = val.substring(start, end);
          if (~selection.indexOf('\n')) {
            replace = false;
            changeLength = 0;
            lastNewLine = before.lastIndexOf('\n');
            if (!~lastNewLine) {
              selection = before + selection;
              changeLength = before.length;
              before = '';
            } else {
              selection = before.substring(lastNewLine) + selection;
              changeLength = before.length - lastNewLine;
              before = before.substring(0, lastNewLine);
            }
            if (e.shiftKey) {
              re = /(\n|^)(\t|[ ]{1,8})/g;
              if (selection.match(re)) {
                start--;
                changeLength--;
              }
              selection = selection.replace(re, '$1');
            } else {
              selection = selection.replace(/(\n|^)/g, '$1\t');
              start++;
              changeLength++;
            }
            $this.val(before + selection + after);
            this.selectionStart = start;
            this.selectionEnd = start + selection.length - changeLength;
          }
        }
        if (replace && !e.shiftKey) {
          $this.val(before + '\t' + after);
          this.selectionStart = this.selectionEnd = start + 1;
        }
      }
    });
  };
})(jQuery);

$(function() {
  $("textarea").enableSmartTab();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea rows="10" cols="80">
/* Just some code to edit with our new superTab */
(function($) {
    $.fn.enableSmartTab = function() {
        $this = $(this);
        $this.keydown(function(e) {
            if ((e.charCode === 9 || e.keyCode === 9) && !e.metaKey && !e.ctrlKey && !e.altKey) {
                e.preventDefault();
            }
        }
    }
}
</textarea>

我刚刚编写了代码来实现此功能。在您不能使用 jQuery 的情况下,请考虑使用我的代码。
2021-04-15 04:52:16
@K._ 如果你看看我写的代码,实际上里面没有太多的 jQuery。排除监听器的添加,jQuery 唯一的实际使用是$.fn.val. 处理程序本身已经使用了本机事件属性。
2021-04-18 04:52:16
~ 和 !~ 是什么意思?
2021-05-06 04:52:16
@K._ 不错的代码,但我建议通过 babel 或 google 关闭运行它以删除 ES6 组件。ES6 很棒,但是有太多用户没有使用兼容 ES6 的浏览器。event.key没有(IIRC)跨浏览器一致的,钥匙在不同的浏览器可能有不同的叫法,和Safari完全不支持该属性。这是人们使用 jQuery另一个原因,虽然经常被遗忘,但它是为了保证跨浏览器的兼容性。我不是在批评你的努力,我认为你做得很好,但它必须是跨浏览器的
2021-05-13 04:52:16
@1.21gigawatts 它是按位非运算符,这里有一个很好的解释为什么在这里使用它
2021-05-13 04:52:16

在香草(默认)JS 中,这将是:

var textareas = document.getElementsByTagName('textarea');

if ( textareas ) {
  for ( var i = 0; i < textareas.length; i++ ) {
textareas[i].addEventListener( 'keydown', function ( e ) {
  if ( e.which != 9 ) return;

  var start             = this.selectionStart;
  var end                 = this.selectionEnd;

  this.value            = this.value.substr( 0, start ) + "\t" + this.value.substr( end );
  this.selectionStart = this.selectionEnd = start + 1;

  e.preventDefault();
  return false;
});
  }
}
textarea {
   border: 1px solid #cfcfcf;
   width: 100%;
   margin-left: 0px;
   top: 0px;
   bottom: 0px;
   position: absolute;
}
<textarea>
var x = 10;
var y = 10;
</textarea>

这是否更好?
2021-05-02 04:52:16
谢啦。人们没有意识到并不是每个人都在使用 jQuery。
2021-05-08 04:52:16
@Mark 你能减小标签大小吗?
2021-05-11 04:52:16

在(多个)textarea 元素内启用制表符

更正@alexwells 答案并启用现场演示

var textAreaArray = document.querySelectorAll("textarea");
    for (var i = textAreaArray.length-1; i >=0;i--){
        textAreaArray[i].addEventListener('keydown',function(e) {
            if(e.keyCode === 9) { // tab was pressed
                // get caret position/selection
                var start = this.selectionStart;
                var end = this.selectionEnd;

                var target = e.target;
                var value = target.value;

                // set textarea value to: text before caret + tab + text after caret
                target.value = value.substring(0, start)
                            + "\t"
                            + value.substring(end);

                // put caret at right position again (add one for the tab)
                this.selectionStart = this.selectionEnd = start + 1;

                // prevent the focus lose
                e.preventDefault();
            }
        },false);
    }
<textarea rows="10" cols="80"></textarea>
   <textarea rows="10" cols="80"></textarea>

使用 vanilla javascript 在 textarea 元素中启用选项卡
2021-04-25 04:52:16