首页 > 解决方案 > 将粘贴文本上的字符计数到输入字段中的正确方法是什么?

问题描述

我有一个带有输入计数器的自动扩展表单字段,其中文本区域有一个 maxLength。如果在其中键入或粘贴多行,则 onKeyUp 字段会自动扩展该区域并触发重新计算计数。这很好用,但是当我故意粘贴比允许的 1024 更长的文本(1029 个字符)时,会发生不一致。

处理输入的正确方法是什么,真正的长度是多少?

我省略了不相关的 CSS 和 PHP 部分,因为该问题独立于此代码发生。

使用计算javascript样式(len=element.value.length)时,粘贴文本后会正确显示(1024/1024),过长文本的最后五个字符会被截断。到目前为止一切顺利,但此后用户必须删除更多的包机,直到计数器显示 (1015/1024),然后他/她才能输入一个新字符。所以突然间,1016 的虚拟 maxLength 似乎有效。

http://stackoverflow.com/questions/462348/建议的解决方案不是 100% 的解决方案。这只是为了计数而替换换行符。使用此代码,计数器现在将在粘贴相同文本时显示 (1033/1024)。

编码:

update_textlen(document.getElementById('item.text'));

function update_textlen(field) {
// count the characters used of maxLenght in text
	var maxlen = field.maxLength;
	// var len = field.value.length; // old style
	var len = field.value.replace(/\n/g, "\r\n").length;
	var message = "("+len+"/"+maxlen+")";
	var target = field.id+".len"; // div id for message
	document.getElementById(target).innerHTML = message;
}

function resize_textarea(area) {
//auto expand textarea to fit new number of lines
    area.style.height = "20px";
    area.style.height = (area.scrollHeight)+"px";
}
#item-wrap { 
    width: 502px; 
	margin: 8px 8px 8px 8px; background: #eee; 
    padding: 16px;
    /* background: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#ccc)); */
	/* background: -moz-linear-gradient(top,  #eee,  #ccc); */
	-webkit-border-radius: 8px;
	-moz-border-radius: 8px;
}
.form-style-2019 input[type="text"],
.form-style-2019 textarea,
.form-style-2019 select 
{
	background: #FFF;
	margin-left: 3px;
	margin-top: 6px;
	box-sizing: border-box;
	-webkit-box-sizing: border-box;
	-moz-box-sizing: border-box;
	width: 100%;
	display: block;
	outline: none;
	border: none;
	height: 20px;
	line-height: 20px;
	font-size: 17px;
	padding: 0;
	font-family: Monaco, Courier, mono-space;
}
<div name="item" id="item-wrap">
    <div id="item">
        <form action="#" method="post" name="item.title" onsubmit="return false;" class="form-style-2019">
            text input: <div style="float:right" id="item.text.len">(128/1024)</div>
            <textarea id="item.text" 
                name="input" 
                wrap="virtual" 
                placeholder="text" 
                maxlength="1024" 
                onfocus="resize_textarea(this);update_textlen(this);" 
                onblur="update_textlen(this);resize_textarea(this);" 
                onkeyup="update_textlen(this);resize_textarea(this);" 
                tabindex="1">line1 Bla bla bla
line2 test 123</textarea>
        </form>
    </div>
</div>

粘贴的文本:

dummy text with words repeated until the maximum character count is reached. 
and a line with a tab and return
    occasionally repeated until the maximum character count is reached. 
dummy text with a long line and many words repeated until the maximum character count is reached. dummy text with a long line and many words repeated until the maximum character count is reached. dummy text with a long line and many words repeated until the maximum character count is reached. dummy text with a long line and many words repeated until the maximum character count is 
and a line with a tab and return
    occasionally repeated until the maximum character count is reached. 
and a line with a tab and return
    occasionally repeated until the maximum character count is reached. 
dummy text with a long line and many words repeated until the maximum character count is reached. dummy text with a long line and many words repeated until the maximum character count. 
and the last line with some numbers to see what goes missing 0123456789.

标签: javascriptcss

解决方案


一位线下的朋友和经验丰富的后端开发者曾这样向我解释过。由于我们必须对输入进行后处理,并且在许多编程语言中,我们可能必须稍后添加斜杠来转义这些字符,因此使用较低的“虚拟”计数作为长度限制更为明智。因此,在上面的示例中,当在平台上处理此字符串时,需要剪切更多的字符以确保安全。

在这种情况下,更新后的函数应如下所示:

function update_textlen(field) {
  // count the characters used of maxLenght in text field and report it to a div
  var maxlen = field.maxLength;
  var fval = field.value;
  var flen = fval.length;
  var tlen = fval.replace(/\n/g, "\r\n").length;
  var dlen = tlen - flen;
  var warn = 0;
  // now clip more characters of the end if neeeded 
  if (tlen > maxlen) {
    field.value = fval.substring(0, (maxlen - dlen));
    var tlen = field.value.replace(/\n/g, "\r\n").length;
    var warn = ("input exceeded the " + maxlen + " allowed characters!");
  }
  var counter = "(" + tlen + "/" + maxlen + ")";
  var target = field.id + ".len";
  document.getElementById(target).innerHTML = counter;
  if (warn) {
    alert(warn);
  }
}

update_textlen(document.getElementById('item.text'));

function resize_textarea(area) {
  //auto expand textarea to fit new number of lines
  area.style.height = "20px";
  area.style.height = (area.scrollHeight) + "px";
}
#item-wrap {
  width: 502px;
  margin: 8px 8px 8px 8px;
  background: #eee;
  padding: 16px;
  /* background: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#ccc)); */
  /* background: -moz-linear-gradient(top, #eee, #ccc); */
  -webkit-border-radius: 8px;
  -moz-border-radius: 8px;
}

.form-style-2019 input[type="text"],
.form-style-2019 textarea,
.form-style-2019 select {
  background: #FFF;
  margin-left: 3px;
  margin-top: 6px;
  box-sizing: border-box;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  width: 100%;
  display: block;
  outline: none;
  border: none;
  height: 20px;
  line-height: 20px;
  font-size: 17px;
  padding: 0;
  font-family: Monaco, Courier, mono-space;
}
<div name="item" id="item-wrap">
  <div id="item">
    <form action="#" method="post" name="item.title" onsubmit="return false;" class="form-style-2019">
      text input:
      <div style="float:right" id="item.text.len">(128/1024)</div>
      <textarea id="item.text" name="input" wrap="virtual" placeholder="text" maxlength="1024" onfocus="resize_textarea(this);update_textlen(this);" onblur="update_textlen(this);resize_textarea(this);" onkeyup="update_textlen(this);resize_textarea(this);" tabindex="1">line1 Bla bla bla
line2 test 123</textarea>
    </form>
  </div>
</div>


推荐阅读