I'm looking for a javascript that can limit the number of lines (by line I mean some text ended by user pressing enter on the keyboard) the user is able to enter in textarea. I've found some solutions but they simply don't work or behave really weird. The best solution would be a jquery plugin that can do the work - something like CharLimit, but it should be able to limit text line count not character count.
This might help (probably be best using jQuery, onDomReady and unobtrusively adding the keydown event to the textarea) but tested in IE7 and FF3:
<html>
<head><title>Test</title></head>
<body>
<script type="text/javascript">
var keynum, lines = 1;
function limitLines(obj, e) {
// IE
if(window.event) {
keynum = e.keyCode;
// Netscape/Firefox/Opera
} else if(e.which) {
keynum = e.which;
}
if(keynum == 13) {
if(lines == obj.rows) {
return false;
}else{
lines++;
}
}
}
</script>
<textarea rows="4" onkeydown="return limitLines(this, event)"></textarea>
</body>
</html>
*Edit - explanation: It catches the keypress if the ENTER key is pressed and just doesn't add a new line if the lines in the textarea are the same number as the rows of the textarea. Else it increments the number of lines.
Edit #2: Considering people are still coming to this answer I thought I'd update it to handle paste, delete and cut, as best as I can.
<html>
<head>
<title>Test</title>
<style>
.limit-me {
height: 500px;
width: 500px;
}
</style>
</head>
<body>
<textarea rows="4" class="limit-me"></textarea>
<script>
var lines = 1;
function getKeyNum(e) {
var keynum;
// IE
if (window.event) {
keynum = e.keyCode;
// Netscape/Firefox/Opera
} else if (e.which) {
keynum = e.which;
}
return keynum;
}
var limitLines = function (e) {
var keynum = getKeyNum(e);
if (keynum === 13) {
if (lines >= this.rows) {
e.stopPropagation();
e.preventDefault();
} else {
lines++;
}
}
};
var setNumberOfLines = function (e) {
lines = getNumberOfLines(this.value);
};
var limitPaste = function (e) {
var clipboardData, pastedData;
// Stop data actually being pasted into div
e.stopPropagation();
e.preventDefault();
// Get pasted data via clipboard API
clipboardData = e.clipboardData || window.clipboardData;
pastedData = clipboardData.getData('Text');
var pastedLines = getNumberOfLines(pastedData);
// Do whatever with pasteddata
if (pastedLines <= this.rows) {
lines = pastedLines;
this.value = pastedData;
}
else if (pastedLines > this.rows) {
// alert("Too many lines pasted ");
this.value = pastedData
.split(/\r\n|\r|\n/)
.slice(0, this.rows)
.join("\n ");
}
};
function getNumberOfLines(str) {
if (str) {
return str.split(/\r\n|\r|\n/).length;
}
return 1;
}
var limitedElements = document.getElementsByClassName('limit-me');
Array.from(limitedElements).forEach(function (element) {
element.addEventListener('keydown', limitLines);
element.addEventListener('keyup', setNumberOfLines);
element.addEventListener('cut', setNumberOfLines);
element.addEventListener('paste', limitPaste);
});
</script>
</body>
</html>
How to do it with jQuery:
Bind to keyDown event of textarea.
function limitTextareaLine(e) {
if(e.keyCode == 13 && $(this).val().split("\n").length >= $(this).attr('rows')) {
return false;
}
}
This solution works:
<script type="text/javascript">
function limitTextarea(textarea, maxLines, maxChar) {
var lines = textarea.value.replace(/\r/g, '').split('\n'), lines_removed, char_removed, i;
if (maxLines && lines.length > maxLines) {
lines = lines.slice(0, maxLines);
lines_removed = 1
}
if (maxChar) {
i = lines.length;
while (i-- > 0) if (lines[i].length > maxChar) {
lines[i] = lines[i].slice(0, maxChar);
char_removed = 1
}
if (char_removed || lines_removed) {
textarea.value = lines.join('\n')
}
}
}
</script>
and text area would be
<asp:TextBox ID="myWishTB" runat="server" Height="185px" TextMode="MultiLine"
Style="overflow: auto;" Width="95%"
onkeyup="limitTextarea(this,10,80)">
</asp:TextBox>
in regular HTML:
<textarea id="textareaID" onkeyup="limitTextarea(this,5,100)" cols="20" rows="5"> </textarea>
jQuery example. This works for both typing and pasting.
//Limit to # of rows in textarea or arbitrary # of rows
$('#yourtextarea').bind('change keyup', function(event) {
//Option 1: Limit to # of rows in textarea
rows = $(this).attr('rows');
//Optiion 2: Limit to arbitrary # of rows
rows = 6;
var value = '';
var splitval = $(this).val().split("\n");
for(var a=0;a<rows && typeof splitval[a] != 'undefined';a++) {
if(a>0) value += "\n";
value += splitval[a];
}
$(this).val(value);
});
(Done with jquery). It's not perfect but cares about wrapping. Not deppending only of the end of line (\n).
jquery scroll event have problems in mozilla and firefox if css overflow property in textarea is not auto, otherwise remove the corresponding lines and set overflow hidden. Could help the css resize:none and fixed height.
$('#textarea').scroll(function () {
$(this).css("overflow", "hidden"); /* for the mozilla browser problem */
$(this).animate({scrollTop: $(this).outerHeight()});
while ($(this).scrollTop() > 0) { /* for the copy and paste case */
lines=$(this).val().slice(0,-1);
$(this).val(lines);
}
$(this).css("overflow", "auto"); /* For the mozilla browser problem */
});
The number of visible/display lines for a given block of text would vary with different browsers, fonts used, etc. You'd have to set a specific font and font-size, at a minimum, to be able to semi-reliably count display lines.
UPDATE: I see the edit. Then something like kevchadders code should do fine for you. You'll need js that counts chars and '\r\n's and checks against a user-defined limit. Also, if you don't use his script, make sure you use one that involves either a time interval check and/or the onKeyDown/onKeyUp events of the textarea. This may be why some scripts you have tested seem to "behave strangely".
This is basically the same as Ivan's answer, using jQuery. I tested it for a project of my own; seems to work fine.
<script type="text/javascript" charset="utf-8">
$(function()
{
function getLines(id)
{
return $('#' + id).val().split("\n").length
}
$('#testing').keyup(function()
{
var allowedNumberOfLines = 4;
if(getLines('testing') > allowedNumberOfLines)
{
modifiedText = $(this).val().split("\n").slice(0, allowedNumberOfLines);
$(this).val(modifiedText.join("\n"));
}
});
});
</script>
I extended it a bit to detect even overflow without a manual linebreak. This is for fixed size textarea with "overflow: hidden".
At the moment my solution makes the font smaller if it doesn't fit to textarea. And makes it larger again if possible.
var keynum, allowedLines = 5, defaultFontSize = 13/*px*/;
$(document).ready(function() {
$("textarea").keydown(function(e, obj) {
if(window.event)
keynum = e.keyCode;
else if (e.which)
keynum = e.which;
if (keynum == 13 && allowedLines <= $(this).val().split("\n").length)
return false;
});
$("textarea").keyup(function(e, obj) {
// Avoid copy-paste
if (allowedLines < $(this).val().split("\n").length) {
lines = $(this).val().split("\n").slice(0, allowedLines);
$(this).val( lines.join('\n') );
}
// Check overflow
if ((this.clientHeight < this.scrollHeight)) {
while ((this.clientHeight < this.scrollHeight)) {
currFontSize = $(this).css('font-size');
finalNum = parseFloat(currFontSize, 11);
stringEnding = currFontSize.slice(-2);
$(this).css('font-size', (finalNum-1) + stringEnding);
}
} else if ($(this).css('fontSize') != defaultFontSize+'px') {
while ($(this).css('font-size') != defaultFontSize+'px') {
// First lets increase the font size
currFontSize = $(this).css('font-size');
finalNum = parseFloat(currFontSize, 11);
stringEnding = currFontSize.slice(-2);
$(this).css('font-size', (finalNum+1) + stringEnding);
// lets loop until its enough or it gets overflow again
if(this.clientHeight < this.scrollHeight) {
// there was an overflow and we have to recover the value
$(this).css('font-size', currFontSize);
break;
}
}
}
});
});
© 2022 - 2024 — McMap. All rights reserved.