Javascript 如何将文本区域中每行的字符数限制为固定值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5236213/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to limit number of characters per line in text area to a fixed value
提问by SKumar
In my text area, I should be able to enter only 72 characters per line. If I use, cols property set to 72, it is allowing more or less number of characters depending on character width.
在我的文本区域中,我应该每行只能输入 72 个字符。如果我使用 cols 属性设置为 72,它会根据字符宽度允许更多或更少的字符数。
Can any one help how to do it?
任何人都可以帮助如何做到这一点?
回答by Juan Mendes
Duplicate of Textarea Limit characters per line Jquery or Javascript
Textarea重复每行限制字符 Jquery 或 Javascript
<TEXTAREA NAME="HARD" COLS="72" ROWS="5" WRAP="HARD">
回答by mozzbozz
I had the same problem and tried to solve it with JavaScript. Why not just take the HTML-Code suggested by Juan Mendes?
我遇到了同样的问题,并试图用 JavaScript 解决它。为什么不直接采用 Juan Mendes 建议的 HTML 代码?
Well, it's quite simple: It doesn't really work cross browser, or at least with Firefox 25 under Ubuntu, the maximum number of characters per line seems to be limited by the textarea width and depending on font size I could enter +-1 letter. But I wanted the number of characters per line limited to a specific value, no matter what the textarea's width is. So I came up with this code:
嗯,这很简单:它并不能真正跨浏览器工作,或者至少在 Ubuntu 下的 Firefox 25 中,每行的最大字符数似乎受到 textarea 宽度的限制,并且取决于我可以输入的字体大小 +-1信。但我希望每行的字符数限制为特定值,无论 textarea 的宽度是多少。所以我想出了这个代码:
var maxLength = 3;
$('#mytext').on('input focus keydown keyup', function() {
var text = $(this).val();
var lines = text.split(/(\r\n|\n|\r)/gm);
for (var i = 0; i < lines.length; i++) {
if (lines[i].length > maxLength) {
lines[i] = lines[i].substring(0, maxLength);
}
}
$(this).val(lines.join(''));
});
I have also prepared a jsFiddle. I hope this helps someone :)
我还准备了一个jsFiddle。我希望这可以帮助别人 :)
And at the end just a short explanation of how this code works:
最后只是对这段代码如何工作的简短解释:
- The function waits for one of the following events: input, focus, keydown, keyup (it may look a bit unnecessary to use this many events but I tested a lot to find this combination which works crossbrowser and always fires, no matter if only single letters are entered, the key is continually pressed or text is pasted into the textarea)
- it gets the value of the textarea
- then it splits the textarea at every linebreak into a new array element
- the for loop iterates over this array and checks for every line respectively element of the array, if it exceeds the before set maxLength
- if one line exceeds the maxLength, the line is "cut off" after maxLength characters
- at the end, when there is no line left which is longer than maxLength characters, the array elements are joined together in a string again
- 该函数等待以下事件之一:input、focus、keydown、keyup(使用这么多事件可能看起来有点不必要,但我进行了大量测试以找到这个组合,它可以跨浏览器工作并且总是触发,无论是否只有一个输入字母,连续按下该键或将文本粘贴到 textarea 中)
- 它获取 textarea 的值
- 然后它将每个换行符处的 textarea 拆分为一个新的数组元素
- for 循环遍历这个数组并检查数组的每一行和元素,如果它超过了之前设置的 maxLength
- 如果一行超过 maxLength,该行在 maxLength 个字符后被“截断”
- 最后,当没有剩下比 maxLength 个字符长的行时,数组元素再次连接到一个字符串中
EDIT: The only constrain I found out now, is that when entering an additional character at the beginning or within the line, the code "cuts off" the string at the end and not where the characters have been added. This won't matter in most cases but just keep it in mind :) Anyway, it should not be too difficult to change this function appropriately, but in most cases it will be waste of resources ;)
编辑:我现在发现的唯一限制是,当在行首或行内输入附加字符时,代码会“切断”末尾的字符串,而不是添加字符的位置。这在大多数情况下无关紧要,但请记住:) 无论如何,适当地更改此功能应该不会太困难,但在大多数情况下,这会浪费资源 ;)
回答by Kraken67
A small addition to complete a previous solution.
I also limit the number of lines.
完成先前解决方案的一个小补充。
我也限制了行数。
It serves me in old systems where a comment of 4 lines is saved in 4 database entries.
它在旧系统中为我服务,其中 4 行注释保存在 4 个数据库条目中。
<textarea id="mytext" rows = "4" style="width:300px"></textarea>
$(function() {
var maxLength = 30;
var mawRow = 4;
$('#mytext').on('input focus keydown keyup', function() {
//get Textearea text
var text = $(this).val();
//Split with \n carriage return
var lines = text.split("\n");
for (var i = 0; i < lines.length; i++) {
if (lines[i].length > maxLength) {
lines[i] = lines[i].substring(0, maxLength);
}
}
//On supprime ce qui dépasse... :)
while (lines.length > 4){
lines.pop();
}
//Join with \n.
//Set textarea
$(this).val(lines.join("\n"));
});
});
回答by Matthias Wunsch
Here is a way to restrict a textarea in both characters per line and amount of lines. To also make the input interaction feel intuitive to a user it needs to handle (1) the value of the inputand (2) the cursor position:
这是一种在每行字符和行数中限制 textarea 的方法。为了让用户感觉输入交互更直观,它需要处理(1) 输入的值和(2) 光标位置:
- (a) READ VALUE from the textarea, (b) DETECT IF TEXT PER LINE IS TOO LONG as required by the length restrictions, (c) PUSH OVERFLOWING TEXT from a line to the next line and (d) WRITE VALUE back to the textarea.
- (a) READ THE CURSOR POSITION to store the cursor position, and (b) POSITION THE CURSOR where a user would expect it after WRITE DATA.
- (a) 从 textarea 读取 VALUE,(b) 根据长度限制的要求检测每行文本是否太长,(c) 将溢出的文本从一行推送到下一行,以及 (d) 将 WRITE VALUE 写回 textarea .
- (a) 读取光标位置以存储光标位置,以及 (b) 将光标定位在用户在写入数据后预期的位置。
Check out the codepen here: https://codepen.io/MattWritingCode/pen/bmexwa
在此处查看代码笔:https://codepen.io/MattWritingCode/pen/bmexwa
This is the essential javascript code (tested on Safari and Chrome, it also works fine when pasting text into the textarea):
这是基本的 javascript 代码(在 Safari 和 Chrome 上测试,在将文本粘贴到 textarea 时也能正常工作):
var charactersPerLine=document.getElementById("charactersPerLine").value;
var maxLines=document.getElementById("maxLines").value;
var textOutput="";
var onPaste=false;
function formatTextAsRequired() {
/*
This function handles two aspects:
1. (a) READ VALUE from the textarea, (b) DETECT IF TEXT PER LINE IS TOO LONG as required by the length restrictions, (c) PUSH OVERFLOWING TEXT from a line to the next line and (d) WRITE VALUE back to the textarea.
2. (a) READ THE CURSOR POSITION to store the cursor position, and (b) POSITION THE CURSOR where a user would expect it after WRITE DATA.
*/
var textInput=document.getElementById("flexibleInputField").value;//1a: READ VALUE
var inputAsRows=textInput.split("\n");// create array from input => each element contains one row of the textarea
var inputAsOneLine=textInput.replace(/(\r\n\t|\n|\r\t)/gm,"");//remove all line-breaks
var cursorPositionOnInput=document.getElementById("flexibleInputField").selectionStart;//2a: READ CURSOR POSITION
var cursorOffsetAfterOutput=0;//set default value for cursor offset. cursor offset is needed when re-posiotioning the cursor after WRITE DATA
var totalRows=inputAsRows.length; //don't put inputAsRows.length in the for statement, as the array is growing in the loop which results in an infinite loop
var row;
var lineBreakCount=0;
var characterCount=0;
for (row = 0; row < totalRows; ++row) {
if(inputAsRows[row].length>charactersPerLine){ //1b DETECT IF TEXT PER LINE IS TOO LONG
if (inputAsRows[row+1] === undefined) {
inputAsRows[row+1]="";// the row did not exist
totalRows++;
}
//1c PUSH OVERFLOWING TEXT: move text that is too long for this row to the next row:
inputAsRows[row+1]=inputAsRows[row].substring(charactersPerLine)+inputAsRows[row+1];
inputAsRows[row]=inputAsRows[row].substring(0,charactersPerLine);
//determine, if cursor was at the end of the line that got a line-break:
var newOutput=inputAsRows.join("\n");
if(newOutput.substr(cursorPositionOnInput-1,1)=="\n"){
cursorOffsetAfterOutput=1; }
}
}
if(inputAsRows.length<=maxLines && inputAsOneLine.length<=(maxLines*charactersPerLine)){//data is within max number of rows and max total digits
textOutput=inputAsRows.join("\n");
document.getElementById("flexibleInputField").rows=inputAsRows.length;//resize textarea
document.getElementById("errors").innerHTML="";//remove error message
document.getElementById("count").innerHTML=inputAsOneLine.length+"/"+(maxLines*charactersPerLine);//show digits count
if(onPaste){ cursorOffsetAfterOutput=cursorOffsetOnPaste(textInput,cursorPositionOnInput,totalRows)
}
}
else //data would be too long
{
document.getElementById("errors").innerHTML="This field can only have "+maxLines+" lines with "+charactersPerLine+" characters per line.";//display error message
document.getElementById("count").innerHTML="";//remove digits count
cursorOffsetAfterOutput=-1;
}
document.getElementById("flexibleInputField").value=textOutput;//1d: WRITE VALUE
document.getElementById("flexibleInputField").selectionStart=cursorPositionOnInput+cursorOffsetAfterOutput; //2b: POSITION CURSOR
document.getElementById("flexibleInputField").selectionEnd=cursorPositionOnInput+cursorOffsetAfterOutput; //set a single cursor, not a selection
onPaste=false;
}
function countLineBreaks(string,lengthFromStart){
var left=string.substr(0,lengthFromStart);
var countOfLinebreaks=(left.split("\n")).length;
return countOfLinebreaks;
}
function handlePaste(){
//some improvements when pasting content can still be made (particularly on the cursor position)
onPaste=true;
}
function cursorOffsetOnPaste(textInput,cursorPositionOnInput,totalRows){
//offset the cursor by 1 for each added line break:
var countOld=countLineBreaks(textInput,cursorPositionOnInput);
var countNew=countLineBreaks(textOutput,cursorPositionOnInput+totalRows);
cursorOffsetAfterOutput=countNew-countOld;
return cursorOffsetAfterOutput;
}
回答by Kyle Joeckel
This is an old thread but i have just developed a little jQuery plugin solution. Check it out here. Find the readme for further details. My plugin has a bit more to it but the basic are as follows:
这是一个旧线程,但我刚刚开发了一个小的 jQuery 插件解决方案。检查它在这里。查找自述文件以获取更多详细信息。我的插件有更多内容,但基本如下:
$(document).ready(function(){
var linesUsed = $('#linesUsed');
var charsUsed = $('#charsUsed');
var errorreading = $('#errors');
// HANDLES PASTE EVENTS
$('.line_control').on('paste', function (e) {
var $el = $(this);
var lines = $el.attr("lines");
var chars = $el.attr("chars");
var errors = [];
setTimeout(function (e) {
var newLines = $el.val().split("\n");
console.log(newLines);
linesUsed.text(newLines.length);
charsUsed.text(newLines[newLines.length - 1].length + 1);
for (var i = 0, len = newLines.length; i < len; i++) {
if (newLines[i].length >= chars) {
let line = i + 1;
let count = newLines[i].length;
errors.push({
'line': line,
'count': count
})
}
}
if (errors.length > 0) {
var html = '<p>Errors:</p>';
var alertMessage = "Warning!\n\nYour pasted content has exceeded the line limitations. Please review the following:\n\n"
for (var i = 0, len = errors.length; i < len; i++) {
html = html + '<span>Line: ' + errors[i]['line'] + '</span></br><span>Count: ' + errors[i]['count'] + '</span></br>'
alertMessage = alertMessage + 'Line: ' + errors[i]['line'] + ' Over: ' + (errors[i]['count'] - chars) + ' Count: ' + errors[i]['count'] + '\n';
}
alert(alertMessage);
errorreading.html(html);
}
console.log(errors);
if (newLines.length >= lines) {
linesUsed.css('color', 'red');
return false;
} else {
linesUsed.css('color', '');
}
if (newLines[newLines.length - 1].length >= chars) {
charsUsed.css('color', 'red');
return false;
} else {
charsUsed.css('color', '');
}
}, 100);
});
//HANDLES AND KEYDOWN EVENTS
$('.line_control').keydown(function (e) {
var lines = $(this).attr("lines");
var chars = $(this).attr("chars");
newLines = $(this).val().split("\n");
linesUsed.text(newLines.length);
charsUsed.text(newLines[newLines.length - 1].length + 1);
if (newLines.length > lines && e.keyCode !== 8 && e.keyCode !== 46) {
linesUsed.css('color', 'red');
return false;
} else if (e.keyCode !== 13 && e.keyCode !== 8 && e.keyCode !== 46 && newLines[newLines.length - 1].length >= chars) {
charsUsed.css('color', 'red');
return false;
} else {
linesUsed.css('color', '');
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea class="line_control" lines="2" chars="8" style="resize: none;"></textarea>
回答by James
Just expanding on an existing answer by katze_sonne to cater for the needs of multiple textareas that would need a limit on characters per line.
只是扩展了 katze_sonne 的现有答案,以满足需要限制每行字符数的多个文本区域的需求。
HTML:
HTML:
<textarea data-row-maxlength = "35" data-limit-row-len = "true" rows = "4"></textarea>
The idea here would be that you set your max length in the data-row-maxlength
and your JavaScript targets any element where the data-limit-row-len = "true"
这里的想法是,您在 中设置最大长度,data-row-maxlength
并且您的 JavaScript 以任何元素为目标data-limit-row-len = "true"
JavaScript:
JavaScript:
$("textarea[data-limit-row-len=true]").on("input focus keydown keyup", function (event) {
var maxlength = $(this).data("row-maxlength");
var text = $(this).val();
var lines = text.split(/(\r\n|\n|\r)/gm);
for (var i = 0; i < lines.length; i++) {
if (lines[i].length > maxlength) {
lines[i] = lines[i].substring(0, maxlength);
}
}
$(this).val(lines.join(''));
});
回答by Jens
Try this for server side addtionally. You can do it in any language. Not just PHP.
在服务器端试试这个。您可以使用任何语言进行操作。不仅仅是PHP。
if (strlen($textareaContent) <= 72) {
// Save textareaContent
}
else {
echo "Your text is longer than 72 characters.";
}
回答by Omar Elawady
Check this:
检查这个:
var t=document.getElementById('textAreaId').value;
if(/^(?:[^\n]{0,73}\n)*$/g.test(t) !== true){
alert('input is invalid');
}
回答by JasonFruit
I would check each time there is a onkeypress event what the current line length is, and then insert a break at the nearest preceding space when it exceeds 72. The difficulty if the user pastes in a block of text; then, you'd have to check all the line lengths between the previous cursor position and the new one, which is a pain. You'd want to store the last cursor position each time there's a keypress, and watch for a jump.
每次有 onkeypress 事件时,我都会检查当前行的长度是多少,然后当它超过 72 时在最近的前一个空格处插入一个中断。用户粘贴文本块的难度;然后,您必须检查前一个光标位置和新光标位置之间的所有行长度,这很痛苦。每次有按键时,您都希望存储最后一个光标位置,并注意跳转。
There's code to get and set the cursor position here.
有代码来获取和设置光标的位置在这里。
回答by Crayon Violent
You can call this on form submit (onsubmit) or on keypress of textfield or whatever
您可以在表单提交(onsubmit)或文本字段的按键或其他任何东西上调用它
if (document.yourformname.textareaname.value.length > maxchars) {
// too many
}
edit: this is javascript. You of course will also want to validate server-side.
编辑:这是javascript。您当然还想验证服务器端。