Wenzi

如何对textarea中的每一行进行判断

蚊子前端博客
发布于 2016/05/13 00:00
textarea标签是一个多行的文本输入空间,文本区中可容纳无限数量的文本。不过如果想对textarea中某一行的内容进行判断就有点困难了,这篇文章里主要讲解如何对textarea中的某一行进行判断

我们先来看看需求:用户可以在编辑区最多输入 10 个域名,一行域名占一行,当换行时,检测上一个域名是否合法,如果不合法,则为不合法的域名加上下划线(或其他提示信息)。

使用 input 标签模拟 #

首先我们来讲解一个不太方便的方案。既然他要求的是针对每行进行判断和提示,那么我们可以用多个 input 来模拟出一个 textarea 标签来。下面的区域就是由 4 个 input[type='text']标签组成的,外层一个容器仅是给用户一个边界而已。

<style>
  .ss {
    border: 1px solid #333;
    width: 400px;
  }
  .ss input {
    border: 0;
    outline: none;
    display: block;
    width: 100%;
  }
</style>
<div class="ss">
  <input type="text" />
  <input type="text" />
  <input type="text" />
  <input type="text" />
</div>

不过毕竟是看起来像 textarea 标签,我们先来看看真实的 textarea 有哪些特性:

  • 换行方便,按 enter 键直接换行
  • 删除方便,当光标在这一行的最前时,再按删除键回到上一行
  • 能任意选择输入的内容进行编辑、删除等

第 1 个和第 2 个特性可以通过监听enterbackspace来实现,任意的选择多行内容进行编辑目前还找不到解决办法。下面我们来看看换行和删除的功能:

var isBegining = false;
$('.ss').on('keyup', function (event) {
  var $current = $('input:focus'),
    keycode = event.keyCode || event.which || event.charCode;

  if (keycode == 13) {
    // enter
    var $next = $current.next();
    if ($next.length) {
      $next.focus();
    }
  } else if (keycode == 8) {
    // delete
    var $prev = $current.prev();

    // 若当前input的光标在最前面
    if ($current[0].selectionStart == 0 && $prev.length) {
      if (isBegining) {
        isBegining = false;
        $prev.focus();
      } else {
        isBegining = true;
      }
    }
  }
});

上图中的isBegining的作用是:当删除字符光标到达最前面时,光标依然停留在当前的 input 内,再次点击删除键时才回到上一个 input 标签。

我们在enter的事件里添加上验证功能,比如如果含有uu则认为是不合法的,然后给这个 input 标签添加红色的下划线。:

/*.ss .waring{
	border-bottom: 1px solid #f00;
}*/
if (keycode == 13) {
  // enter
  var $next = $current.next();
  if ($next.length) {
    var text = $current.val();
    if (text.indexOf('uu') > -1) {
      $current.addClass('waring');
    } else {
      $current.removeClass('waring');
    }
    $next.focus();
  }
}

在接下来的的章节里我们会讲解怎么添加一个跟内容宽度一样的红色下划线。

使用 textarea 标签 #

上一章节里我们是使用的 input 标签进行模拟的,这里我们使用 textarea 标签实现一下我们刚才的需求。通常 textarea 标签里的内容都是作为一个整体来进行操作的,不过我们通过监听按键来实现把每行的内容分开。

<div class="container">
  <textarea id="textarea" class="textarea" spellcheck="false"></textarea>
  <div class="waring"></div>
  <div class="content"></div>
</div>
  • textarea : 输入内容
  • waring : 添加警告下划线
  • content : 隐藏标签,计算某一行内容的宽度,用于警告下划线的宽度

监听按键,每次都获取所有的内容,然后使用split分成一个数组,再检测数组里的内容,若不符合要求

var arr_len = 0;
$('.textarea').on('keyup', function () {
  var text = $(this).val();
  var arr = text.split('\n');

  // 当换行时
  if (arr.length != arr_len) {
    arr_len = arr.length;
    $('.container .waring').html('');

    var html = '';
    for (var i = 0, t = arr.length; i < t; i++) {
      var f = arr[i].indexOf('uu') > -1;

      if (f) {
        $('.container .content').html('<div class="s">' + arr[i] + '</div>'); // 在content中添加这一行的内容

        var width = $('.container .s').width(); // 计算这些内容的宽度
        var top = 20 * (i + 1);
        $('.container .waring').append('<p style="top:' + top + 'px; width:' + width + 'px"></p>');
      }
    }
  }
});

这种添加提示线的方法,也可以用在第一章节里。

不过这个方案也有个缺陷,当用户编辑当前的内容时,当前内容的下划线应当消失,而不是一直显示。

总结 #

当然,这两种方法都有不同的缺陷,也只能根据实际项目的需求来两者取其轻。

阅读(1934)
Simple Empty
No data