Reputation: 444
I have an auto expanding form field with input counter where the text area has a maxLength. The field onKeyUp auto expands the area if multiple lines are typed or pasted into it and triggers a recalculation of the count. This works fine but when I deliberately paste a longer text (1029 chars) than the 1024 allowed an inconsistency occurs.
What is the correct way to deal with the input, what is the true length?
I am leaving out the unrelated CSS and PHP parts because the issue occurs independently from this code.
When using the calculation javascript style (len=element.value.length), it will correctly display (1024/1024) after pasting the text and the last five characters of the too long text will be truncated. So far so good, but hereafter the user must delete more charters until the counter shows (1015/1024) before he/she can type one new character. So suddenly a virtual maxLength of 1016 seems effective.
The solution suggested by http://stackoverflow.com/questions/462348/ is not a 100% solution. This only replaces the line feeds for the purpose of counting. Using this code the counter will now display (1033/1024) when pasting the same text.
the code:
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>
the pasted text:
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.
Upvotes: 2
Views: 1898
Reputation: 444
An offline friend and experienced back-end developer has explained it to me in this way. Since we will have to post process the input and in many programming languages we probably will have to later add slashes for escaping those characters, it is simply wiser to use the lower "virtual" count as the length limit. Hence in the example above 9 more characters need to be clipped to be safe when this string is processed on a platform.
In that case the updated function should look like this:
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>
Upvotes: 1
Reputation: 21681
$(document).ready(function(){
$('button').on('click', function(){
alert($('.field').val().replace(/\s+/g, '').length);
})
});
.wrap{
margin: 10px;
}
<script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"
></script>
<div class="wrap">
<input class="field" type="text"/>
<button>Click</button>
</div>
Upvotes: -1