简体   繁体   中英

jQuery: prevent pasting of text of length greater than given limit

I have a textarea where I am limiting the amount of words that can be typed in. It works fine and stops the user from entering in additional text but it has a problem. If the user copy/pastes into the textarea, they can break the rule. I'm not sure how to go about fixing that.

I know it probably has to do with the onpaste event but how would I implement it into this code:

jQuery(document).ready(function($) {
    var max = 100;
    $('#text<? echo $rowcat2['cfid'];?>').keypress(function(e) {
        if (e.which < 0x20) {
            return;
        }

        var value<? echo $rowcat2['cfid'];?> = $('#text<? echo $rowcat2['cfid'];?>').val();
        var regex = /\s+/gi;
        var wordCount<? echo $rowcat2['cfid'];?> = value<? echo $rowcat2['cfid'];?>.trim().replace(regex, ' ').split(' ').length;

        if (wordCount<? echo $rowcat2['cfid'];?> == max) {
            // Reached max, prevent additional.
            e.preventDefault();
        } else if (wordCount<? echo $rowcat2['cfid'];?> > max) {
            // This doesn't work.
            this.value = this.value.substring(0, max);
        }
    });         
});

OK - I would just add the paste event with the recommended timeout and refactor your code a little.

Not tested but something along the lines of this:

jQuery(document).ready(function ($) {
    var max = 100;
    $('#text<? echo $rowcat2['
    cfid '];?>').on('keypress', function (e) {
        if (e.which < 0x20) {
            return;
        }
        processWordCount(this, e);
    }).on('paste', function () {
        setTimeout(function () {
            processWordCount(this, e);
        }, 100);
    });

    function processWordCount(that, e) {
        var value <? echo $rowcat2['cfid']; ?> = $('#text<? echo $rowcat2['
        cfid '];?>').val();
        var regex = /\s+/gi;
        var wordCount <? echo $rowcat2['cfid']; ?> = value <? echo $rowcat2['cfid']; ?> .trim().replace(regex, ' ').split(' ').length;

        if (wordCount <? echo $rowcat2['cfid']; ?> == max) {
            // Reached max, prevent additional.
            e.preventDefault();
        } else if (wordCount <? echo $rowcat2['cfid']; ?> > max) {
            // This doesn't work.
            that.value = that.value.substring(0, max);
        }
    }
});

The problem with catching paste input is that the actual input seems to be delayed until after the event handler assigned to said paste is fired. Dealing with this has already been addressed in this question.

The workaround is to use a setTimeout() —the timer can even be set to 0ms . This causes the function to be deferred, by putting it at the bottom of the stack. The minimum timeout in HTML5 is actually 4ms , but it's okay to put a timeout of 0ms :

setTimeout(function () {
    /* do whatever */
}, 0)

This answer is very similar to the other one I gave for you . You may want to consider binding them together by

var checkInput = function () {
    /* the logic goes here */
}
$("#selector").keypress(checkInput);
$("#selector").on("paste", checkInput);

The key difference is the use of setTimeout :

JavaScript

var maxWords = 10;
$("#myText").on("paste", function (event) {
    setTimeout(function () {
        var text = $("#myText").val().split(" ");
        while (text.length > maxWords) {
            text.pop();
        }
        $("#myText").val(text.join(" "));
    }, 0)
})

HTML

<p>Enter no more than 10 words:</p>
<textarea id="myText"></textarea>

CSS

textarea {
    width: 300px;
    height: 100px;     
}

fiddle

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