简体   繁体   English

如何将文本区域中每行的字符数限制为固定值

[英]How to limit number of characters per line in text area to a fixed value

In my text area, I should be able to enter only 72 characters per line.在我的文本区域中,我应该每行只能输入 72 个字符。 If I use, cols property set to 72, it is allowing more or less number of characters depending on character width.如果我使用 cols 属性设置为 72,它会根据字符宽度允许更多或更少的字符数。

Can any one help how to do it?任何人都可以帮助如何做到这一点?

Textarea重复每行限制字符 Jquery 或 Javascript

<TEXTAREA NAME="HARD" COLS="72" ROWS="5" WRAP="HARD">

I had the same problem and tried to solve it with JavaScript.我遇到了同样的问题,并试图用 JavaScript 解决它。 Why not just take the HTML-Code suggested by Juan Mendes?为什么不直接采用 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.嗯,这很简单:它并不能真正跨浏览器工作,或者至少在 Ubuntu 下的 Firefox 25 中,每行的最大字符数似乎受到 textarea 宽度的限制,并且取决于我可以输入的字体大小 +-1信。 But I wanted the number of characters per line limited to a specific value, no matter what the textarea's width is.但我希望每行的字符数限制为特定值,无论 textarea 的宽度是多少。 So I came up with this code:所以我想出了这个代码:

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 .我还准备了一个jsFiddle I hope this helps someone :)我希望这可以帮助别人 :)

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)该函数等待以下事件之一:input、focus、keydown、keyup(使用这么多事件可能看起来有点不必要,但我进行了大量测试以找到这个组合,它可以跨浏览器工作并且总是触发,无论是否只有一个输入字母,连续按下该键或将文本粘贴到 textarea 中)
  • it gets the value of the textarea它获取 textarea 的值
  • then it splits the textarea at every linebreak into a new array element然后它将每个换行符处的 textarea 拆分为一个新的数组元素
  • the for loop iterates over this array and checks for every line respectively element of the array, if it exceeds the before set maxLength for 循环遍历这个数组并检查数组的每一行和元素,如果它超过了之前设置的 maxLength
  • if one line exceeds the maxLength, the line is "cut off" after maxLength characters如果一行超过 maxLength,该行在 maxLength 个字符后被“截断”
  • 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最后,当没有剩下比 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 ;)这在大多数情况下无关紧要,但请记住:) 无论如何,适当地更改此功能应该不会太难,但在大多数情况下,这会浪费资源 ;)

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"));
    });
});

Here is a way to restrict a textarea in both characters per line and amount of lines.这是一种在每行字符和行数中限制 textarea 的方法。 To also make the input interaction feel intuitive to a user it needs to handle (1) the value of the input and (2) the cursor position :为了让用户感觉输入交互更直观,它需要处理(1) 输入的值(2) 光标位置

  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. (a) 从 textarea 读取 VALUE,(b) 根据长度限制的要求检测每行文本是否太长,(c) 将溢出的文本从一行推送到下一行,以及 (d) 将 WRITE VALUE 写回 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. (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;
}

This is an old thread but i have just developed a little jQuery plugin solution.这是一个旧线程,但我刚刚开发了一个小的 jQuery 插件解决方案。 Check it out here .在这里查看 Find the readme for further details.查找自述文件以获取更多详细信息。 My plugin has a bit more to it but the basic are as follows:我的插件有更多内容,但基本如下:

 $(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>

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(''));
});

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.";
}

Check this:检查这个:

var t=document.getElementById('textAreaId').value;
if(/^(?:[^\n]{0,73}\n)*$/g.test(t) !== true){
alert('input is invalid');
}

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;每次有 onkeypress 事件时,我都会检查当前行的长度是多少,然后当它超过 72 时在最近的前一个空格处插入一个中断。用户粘贴文本块的难度; 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.每次有按键时,您都希望存储最后一个光标位置,并注意跳转。

There's code to get and set the cursor position here .有代码来获取和设置光标的位置在这里

Try this.尝试这个。

 <textarea name="limit" id="limit" cols="30" rows="10"></textarea> <script> const text = document.querySelector('#limit'); const CHAR_LIMIT_PER_LINE = 5; const LINES_LIMIT = 6; text.addEventListener('keyup', (e) => { const lines = e.target.value.split('\\n'); for (let i = 0; i < lines.length; i++) { if (lines[i].length < CHAR_LIMIT_PER_LINE) continue; lines[i] = lines[i].substring(0, CHAR_LIMIT_PER_LINE); lines[i + 1] = `${lines[i].substring(CHAR_LIMIT_PER_LINE + 1)}${lines[i + 1] || ''}`; } text.value = lines.slice(0, LINES_LIMIT).join('\\n'); }); </script>

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.编辑:这是javascript。 You of course will also want to validate server-side.您当然还想验证服务器端。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM