0

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);
        }
    });         
});
royhowie
  • 11,075
  • 14
  • 50
  • 67
  • Since `wordCount` is a local variable encapsulated inside of the `.keypress` function, there is no need to give it a specific name with PHP: `var wordCount echo $rowcat2['cfid'];?>`. Just use `var wordCount`. – royhowie Jul 19 '14 at 20:19

2 Answers2

0

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);
        }
    }
});
Rob Schmuecker
  • 8,934
  • 2
  • 18
  • 34
-1

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

Community
  • 1
  • 1
royhowie
  • 11,075
  • 14
  • 50
  • 67