views:

300

answers:

3

Hi guys,

I am using contenteditable div elements in my web application and I am trying to come up with a solution to limit the amount of characters allowed in the area, and once the limit is hit, attempting to enter characters simply does nothing. This is what I have so far:

var content_id = 'editable_div';

//binding keyup/down events on the contenteditable div
$('#'+content_id).keyup(function(){ check_charcount(content_id, max); });
$('#'+content_id).keydown(function(){ check_charcount(content_id, max); });

function check_charcount(content_id, max)
{   
    if($('#'+content_id).text().length > max)
    {
        $('#'+content_id).text($('#'+content_id).text().substring(0, max));
    }
}

This DOES limit the number of characters to the number specified by 'max', however once the area's text is set by the jquery .text() function the cursor resets itself to the beginning of the area. So if the user keeps on typing, the newly entered characters will be inserted at the beginning of the text and the last character of the text will be removed. So really, I just need some way to keep the cursor at the end of the contenteditable area's text.

+3  A: 

How about passing in the event object to your function and calling e.preventDefault() if the max is reached?

    var content_id = 'editable_div';  

    max = 10;

    //binding keyup/down events on the contenteditable div
    $('#'+content_id).keyup(function(e){ check_charcount(content_id, max, e); });
    $('#'+content_id).keydown(function(e){ check_charcount(content_id, max, e); });

    function check_charcount(content_id, max, e)
    {   
        if(e.which != 8 && $('#'+content_id).text().length > max)
        {
           // $('#'+content_id).text($('#'+content_id).text().substring(0, max));
            e.preventDefault();
        }
    }

Although, you may need to do a little more to allow the user to do things like 'delete'.


EDIT:

Added support for 'delete' key.


EDIT 2:

Also, you could probably get rid of the keyup handler. keydown should be enough.

patrick dw
Works like a charm! :-) I also added conditionals for arrow keys and backspace/delete, other than that it works perfectly.
Bill Dami
A paste via the context menu or edit menu could still take the user over the limit.
Tim Down
@Tim Down - Very true. Unavoidable (to my knowledge) if using a contentEditable div since there's no `change` event. My solution was specific to the question. Your's very aptly covers the general downside of the approach presented.
patrick dw
+2  A: 

Firstly, this kind of thing is irritating for the user: I would suggest instead doing something similar to StackOverflow's comment field, which allows you type as much or as little as you like, shows you a message telling you how many characters you've typed and whether it's too many or too few, and refuses to let you submit a comment whose length is not valid.

Secondly, if you really have to limit the length of text, replacing the whole content of the <div> on every keystroke if the content is too long is unnecessarily expensive, and will make the editor unresponsive on slower machines. I suggest handling the keypress event and simply preventing the character being inserted using preventDefault() on the event (or in IE, setting the event's returnValue to true, assuming you're using attachEvent). This won't prevent the user from pasting text in, so you'll need to handle the paste event (which doesn't exist in Opera or Firefox < 3, so you'll need some kind of polling-based solution for those). Since you won't be able to access the content being pasted in advance, you'll have no way of knowing if the paste will take you over the character limit, so you'll need to set a timer to check the length again shortly after the paste. Is the first option starting to look more attractive now?

Tim Down
Very good points Tim, I totally forgot to take into a account paste actions or any method of getting text into the editor that won't generate a keypress event for that matter.And yeah, I was never thrilled with the solution of replacing the entire content either, it was just a quick initial stab at the problem.So looking at it now I may just have to go with the solution of allowing an unlimited number of characters initially but warning the user when they are over and not allowing the content to be saved.
Bill Dami
A: 
var onKeyPress = function () {
    var keyCode = window.event.keyCode,
        isNumeric = (keyCode > 47 && keyCode < 58),
        isNotEnterKey = !!(window.event.keyCode !== 13);

        (isNotEnterKey) || (this.blur());

        return (isNumeric && this.innerText.length < 3);
};
shawndumas