javascript - 将粘贴文本上的字符计数到输入字段中的正确方法是什么?
问题描述
我有一个带有输入计数器的自动扩展表单字段,其中文本区域有一个 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.
解决方案
一位线下的朋友和经验丰富的后端开发者曾这样向我解释过。由于我们必须对输入进行后处理,并且在许多编程语言中,我们可能必须稍后添加斜杠来转义这些字符,因此使用较低的“虚拟”计数作为长度限制更为明智。因此,在上面的示例中,当在平台上处理此字符串时,需要剪切更多的字符以确保安全。
在这种情况下,更新后的函数应如下所示:
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>
推荐阅读
- azure-functions - 我可以为版本 2.x 运行时的基于 http 触发器的 azure 函数配置自定义名称吗?
- javascript - ajax 调用和控制器函数中的多个循环值
- javascript - 如何使用 javascript 将数据从 http 站点获取到 html 表中?
- c# - 如何使用索引中的刷新模型重新加载部分视图
- android - 浮动操作按钮强制图像到右下角而不是中心
- graphql - 是否可以在graphql的查询下添加一层分组?
- pagespeed-insights - 为什么 PSI API 将 originLoadingExperience 的值放在 loadingExperience 中,以防 CRuX 没有足够的页面实际速度数据?
- .net-core - 使用 Npgsql 和 CoreRT 编译 .Net Core 控制台应用程序
- git - 如何在 Azure DevOps 中为分支名称设置默认模板
- html - 如何使用 getELementsbyTagName 修复“每次”迭代?