Text input length limit with jQuery

Requirements

  • jQuery (tested on 1.6.2)

Introduction

Limiting the character length on a text input is one of the most commonly used patterns in web applications. In this post I’ll go over an easily re-usable implementation that is compatible with Internet Explorer, Firefox and Chrome using jQuery

Considerations

Setting a character length limit on text input is fairly simple to implement. For example the following snippet of code can achieve this:

$('#tweet_input').keydown(function () {
	var tweet_length = this.val().length;
	if(tweet_length > 140) {
		this.val(this.substring(0,140));
	}
});

One flaw with this simple implementation is that the text length limiting logic only fires when a key is pressed. If someone were to copy and paste text into this text input the character count limit would not be applied. Another problem to consider is that when we truncate the text the cursor position is set to the end of the text box. This becomes an issue when a user highlights a portion of text in the middle and hits  the character length limit; the cursor will be set to the end of the text box giving them a glitchy experience.

jQuery plugin

Implementing the text length limit in this manner is not very re-usable and not easily maintainable. In jQuery a popular way to write frequently used code is to write it as a plugin. To do this we start it off by writing the following:

(function( $ ){
	$.fn.charLimit = function( options ) {
		if(options.limit === undefined || typeof options.limit !== 'number') {
			$.error('Option limit must be defined and must be a number.');
		}
		return this.each(function() {
			// CharLimit logic goes here.
		});
	};
})( jQuery );

This will add a function called charLimit to jQuery that takes a required parameter ‘limit’ that must be a number. So we can call:

$('#selector').charLimit({limit: 140});

anywhere on the page and it will apply the character length limiting to the matching selector.

Character Length Limit Logic

Initialization and Helper Functions

We will initialize our function with two variables; self which is the selector for the target text input and charLimit which is the character length limit. We have two helper functions _truncate which limits text length to charLimit and _setCaretPos which sets the cursor position of the text box. Calling _truncate will call _setCaretPos therefore it will limit character count and set the caret to the proper location.

// CharLimit logic goes here.
var self = $(this);
var charLimit = options.limit;

function _truncate(ev) {
	var caretPos;
	if (ev.target.selectionStart !== undefined) {
		caretPos = ev.target.selectionEnd;
	} else if(document.selection) {
		ev.target.focus();
		var range = document.selection.createRange();
		range.moveStart('character', -ev.target.value.length);
		caretPos = range.text.length;
	}

	self.val(self.val().substring(0, charLimit));
	_setCaretPos(ev, caretPos);
}

function _setCaretPos(ev, pos) {
	if ($(ev.target).get(0).setSelectionRange) {
		$(ev.target).get(0).setSelectionRange(pos, pos);
	} else if ($(ev.target).get(0).createTextRange) {
		var range = $(ev.target).get(0).createTextRange();
		range.collapse(true);
		range.moveEnd('character', pos);
		range.moveStart('character', pos);
		range.select();
	}
}

Keyboard Event

The most of obvious of the events to handle; we will call the _truncate function anytime a key is pressed. The difference between the keypress and keydown event is that keypress will ignore special keys such as backspace, shift and ctrl. We will also block the key input event if the character limit is reached unless a portion of text is highlighted. We do this because if a portion of text is highlighted it would delete the selected portion bringing down the text length.

self.keypress(function(ev) {
	var charCount = self.val().length;
	var selected;
	if (ev.target.selectionStart !== undefined) {
		selected = !(ev.target.selectionStart==ev.target.selectionEnd);
	} else if(document.selection) {
		ev.target.focus();
		var range = document.selection.createRange();
		selected = (range.text.length > 0);
	}

	if(charCount > charLimit-1 && !selected) {
		return false;
	}
	setTimeout(function() {
		_truncate(ev);
	}, 1);
});

Paste Event

Another event to handle is the paste event. The following will handle paste events triggered by either keyboard or mouse. It will call same truncate helper function that the keyboard event handler uses.

self.bind('paste', function(ev) {
	setTimeout(function() {
		_truncate(ev);
	}, 1);
});

Final Product

When we put everything together this is our final product.

(function($) {
	$.fn.charLimit = function(options) {
		if(options === undefined || options.limit === undefined || typeof options.limit !== 'number') {
			$.error('Option limit must be defined and must be a number.');
		}

		return this.each(function() {
			var self = $(this);
			var charLimit = options.limit;

			function _truncate(ev) {
				var caretPos;
				if (ev.target.selectionStart !== undefined) {
					caretPos = ev.target.selectionEnd;
				} else if(document.selection) {
					ev.target.focus();
					var range = document.selection.createRange();
					range.moveStart('character', -ev.target.value.length);
					caretPos = range.text.length;
				}

				self.val(self.val().substring(0, charLimit));
				_setCaretPos(ev, caretPos);
			}

			function _setCaretPos(ev, pos) {
				if ($(ev.target).get(0).setSelectionRange) {
					$(ev.target).get(0).setSelectionRange(pos, pos);
				} else if ($(ev.target).get(0).createTextRange) {
					var range = $(ev.target).get(0).createTextRange();
					range.collapse(true);
					range.moveEnd('character', pos);
					range.moveStart('character', pos);
					range.select();
				}
			}

			self.keypress(function(ev) {
				var charCount = self.val().length;
				var selected;
				if (ev.target.selectionStart !== undefined) {
					selected = !(ev.target.selectionStart==ev.target.selectionEnd);
				} else if(document.selection) {
					ev.target.focus();
					var range = document.selection.createRange();
					selected = (range.text.length > 0);
				}

				if(charCount > charLimit-1 && !selected) {
					return false;
				}
				setTimeout(function() {
					_truncate(ev);
				}, 1);
			});

			self.bind('paste', function(ev) {
				setTimeout(function() {
					_truncate(ev);
				}, 1);
			});

		});
	};
})( jQuery );

In order to use it all you need to is type the following. Where #your_textbox is the id of your text input.

// Include this once.
<script type="text/javascript" src="/js/jquery.charlimit.js"></script>

<input type="text" id='your_textbox'></input>
<script type="text/javascript">$('#your_textbox').charLimit({limit: 60})</script>

Resources

jquery.charlimit.js

This entry was posted in 0-Uncategorized and tagged , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*