简体   繁体   中英

Word wrap in multiline textbox after 35 characters

<asp:TextBox CssClass="txt" ID="TextBox1" runat="server"
             onkeyup="CountChars(this);" Rows="20" Columns="35" 
             TextMode="MultiLine" Wrap="true">
</asp:TextBox>

I need to implement word-wrapping in a multi-line textbox. I cannot allow users to write more then 35 chars a line. I am using the following code, which breaks at precisely the specified character on every line, cutting words in half. Can we fix this so that if there's not enough space left for a word on the current line, we move the whole word to the next line?

function CountChars(ID) {
    var IntermediateText = '';
    var FinalText = '';
    var SubText = '';
    var text = document.getElementById(ID.id).value;
    var lines = text.split("\n");
    for (var i = 0; i < lines.length; i++) {
        IntermediateText = lines[i];
        if (IntermediateText.length <= 50) {
            if (lines.length - 1 == i)
                FinalText += IntermediateText;
            else
                FinalText += IntermediateText + "\n";
        }
        else {
            while (IntermediateText.length > 50) {
                SubText = IntermediateText.substring(0, 50);
                FinalText += SubText + "\n";
                IntermediateText = IntermediateText.replace(SubText, '');
            }
            if (IntermediateText != '') {
                if (lines.length - 1 == i)
                    FinalText += IntermediateText;
                else
                    FinalText += IntermediateText + "\n";
            }
        }
    }
    document.getElementById(ID.id).value = FinalText;
    $('#' + ID.id).scrollTop($('#' + ID.id)[0].scrollHeight);
}

Edit - 1

I have to show total max 35 characters in line without specific word break and need to keep margin of two characters from the right. Again, the restriction should be for 35 characters but need space for total 37 (Just for the Visibility issue.)

I use the following Jquery plugin in an asp.net web app. Put this code under the opening script tag:

jQuery.fn.limitMaxlength = function(options){

var settings = jQuery.extend({
attribute: "maxlength",
onLimit: function(){},
onEdit: function(){}
}, options);

// Event handler to limit the textarea
var onEdit = function(){
var textarea = jQuery(this);
var maxlength = parseInt(textarea.attr(settings.attribute));

if(textarea.val().length > maxlength){
  textarea.val(textarea.val().substr(0, maxlength));

  // Call the onlimit handler within the scope of the textarea
  jQuery.proxy(settings.onLimit, this)();
}

// Call the onEdit handler within the scope of the textarea
jQuery.proxy(settings.onEdit, this)(maxlength - textarea.val().length);
}
this.each(onEdit);
return this.keyup(onEdit)
    .keydown(onEdit)
    .focus(onEdit);
}

And then in document ready add:

$(document).ready(function () {

//give the user feedback while typing
var onEditCallback = function(remaining){
$(this).siblings('.charsRemaining').text("Characters remaining: " + remaining);

if(remaining > 0){
    $(this).css('background-color', 'white');
    }
}

var onLimitCallback = function(){
    $(this).css('background-color', 'red');
}

$('textarea[maxlength]').limitMaxlength({
    onEdit: onEditCallback,
    onLimit: onLimitCallback
});

});//end doc ready

And then on each textarea just ensure that maxlength='35' like so and add a feedback placeholder...

<textarea id="TextBox1" class="txt" runat="server" placeholder="Some Text"  maxlength="35" cols="35" rows="2" ></textarea>

Hope this helps!

This is a testing exercise. This will break the line at 35 characters. Make sure to set cols="35"

I hope this helps.

UPDATE: 6/26/2012

Removed my JSFiddle link. I will not solve the problem unless you start to answer questions being asked by myself and others.

http://jsfiddle.net/g4Kez/4/

This code should wrap the text at 35 characters like you need. This is kind of a weird way to restrict input but it should work. (Previous versions had bugs in them.. I think this one finally works for the most part)

Taking JakeJ's comment a step further,

If having more than 35 characters on a line would break something, it's not such a good idea to do javascript validation. You may encounter issues where someone has javascript disabled, or knows how to break the check if they're being malicious. Is it a possibility to do this server side? Perhaps a little information on why you need this and we could help with a possible alternate solution?

  • If it is important for the business logic that each line has no more than 35 characters, you definitely have to do it on the server. You can only use JavaScript to improve the user interface. But JavaScript will not protect your server-side logic from "illformed" inputs.

  • For the presentation you can use the suggestion you already got from all the others and restrict the size of the input field to 35 columns. This will not change the input value sent to the server, but you will have to do that on the server anyway. Like you correctly noticed, in newer browsers the users can re-size the textarea. This is completely web-like: The user gets the power to adjust the presentation according to their flavor. If - and only if - you really need to restrict that because there is business logic behind, you can disable the re-sizing feature .

  • If it is not important for the business logic but only a matter of presentation then you definitely want to use plain styling instead: Use a 35-columns sized text area and leave it up to the user to resize it.

Remarks:

  • Be aware that if you wrap lines using JavaScript by adding line breaks, you will cope with the use case that the user changes lines that were already wrapped. Do you re-merge and re-wrap them, or will they just become more and more ugly? With the approach I just mentioned you will not have to cope with that. Try the jsfiddle posted by Brett Holt . Write some text until it wraps. Then go back to the first line and delete some characters (use backspace, the delete key did not work for me using FireFox). You will see what I mean. The user will have to be able to remove the original wrapping and have your application re-wrap the line at a different position.

  • By default textareas have a fixed-width font so each line will be restricted to 35 characters regardless of whether it is an "m" or an "l". But you may want to be on the safe side and set the font to a fixed in CSS in addition.

  • For the "2 blank" requirement - that just sounds silly to me, honestly. Take what the browser does for you. It works for all other websites and web applications. Use CSS to style it (consider adding a padding, for example) but please do not start to add JavaScript hacks. If the requirement is from your client, I am sure you can talk to them and explain why it does not work well the way they wanted.

Thanks for all of the examples. I worked on this, because ultimately I need to wordwrap text in an SVG xml (which my current spec. doesn't support word-wrapping).

Here is my edit too. https://jsfiddle.net/vr_driver/7kr1vfq5/50/

 function columncorrector() { var text = document.getElementById("TextBox1").value; var maxcolumnwidth = 40; var lengthSinceNewLine = function(input) { var lastNewLine = input.lastIndexOf("\n"); if (lastNewLine == -1) { return input.length; } else { console.log("lnl: " + lastNewLine); console.log("input.length: " + input.length); return input.length - lastNewLine; } }; console.log(lengthSinceNewLine(text)); lines = text.split("\n").length; console.log("lines: " + lines); if (lines == 1) // without this, the first line always comes out one character longer { maxcolumnwidth_fix = maxcolumnwidth - 2; } else { maxcolumnwidth_fix = maxcolumnwidth - 1; } if (lengthSinceNewLine(text) >= maxcolumnwidth_fix) { if (text[text.length - 1] == " ") { text = text + "\n"; } else { console.log("length:" + text.length); console.log(text.lastIndexOf(" ")); if (text.lastIndexOf(" ") == "-1") { console.log("here 1"); text = text + "-\n"; // a forced hyphen document.getElementById("TextBox1").value = text; } else { var space = text.lastIndexOf(" "); text = text.substring(0, space) + "\n" + text.substring(space + 1, text.length); document.getElementById("TextBox1").value = text; } } } };
 .txt { width: 400px; }
 <textarea id="TextBox1" class="txt" rows="30" onkeydown="columncorrector()" onkeyup="columncorrector()"></textarea>

Here is a simple function that breaks the lines at (or before) 35 characters. The only scenario this would currently fail for is if you have more than 35 characters with no space. If you want a hard-break in this scenario let me know and I'll add that in.

You can see it working over on JS Fiddle - just hit GO to see the result.

var breakLines = function () {
    var i, limit = 35, lines = [], result = '', currentLine = '';
    var textBox = document.getElementById('example');
    var text = textBox.value;
    var words = text.split(' ');

    for (i = 0; i < words.length; i++) {
        var extendedLine = currentLine + ' ' + words[i];
        if (extendedLine.length > limit) {
            lines.push(currentLine);
            currentLine = words[i];
        } else {
            currentLine = extendedLine;
        }
    }

    if (currentLine.length > 0) {
        lines.push(currentLine);
    }


    for (i = 0; i < lines.length; i++) {
        result += lines[i] + '\r\n';
    }

    textBox.value = result;
};
<script type="text/javascript">
    function CountChars(ID) {
        var IntermediateText = '';
        var FinalText = '';
        var SubText = '';
        var Splitted;
        var Concatenated;
        var text = document.getElementById(ID.id).value;
        var lines = text.split("\n");
        for (var i = 0; i < lines.length; i++) {
            IntermediateText = lines[i];
            if (IntermediateText.length <= 50) {
                if (lines.length - 1 == i)
                    FinalText += IntermediateText;
                else
                    FinalText += IntermediateText + "\n";
            }
            else {
                Splitted = IntermediateText.split(' ');
                for (var index = 0; index < Splitted.length; index++) {
                    Concatenated = Splitted[index].length;
                    if (Concatenated + SubText.length <= 50) {
                        if (index + 1 != Splitted.length) {
                            SubText += Splitted[index] + " ";
                        }
                        else {
                            SubText += Splitted[index];
                        }
                    }
                    else {
                        FinalText += SubText + "\n";
                        SubText = "";
                        if (index + 1 != Splitted.length) {
                            SubText = Splitted[index] + " ";
                        }
                        else {
                            SubText = Splitted[index];
                        }
                    }
                }
                if (SubText != '') {
                    FinalText += SubText;
                }
            }
        }
        document.getElementById(ID.id).value = FinalText;
        $('#' + ID.id).scrollTop($('#' + ID.id)[0].scrollHeight);
    }

</script>


<asp:TextBox ID="txt" onkeyup="CountChars(this);" Width="60%" runat="server" Rows="20"
                    Columns="50" TextMode="MultiLine" MaxLength="1000"></asp:TextBox>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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