(function ($) {
  $.fn.Maxlength = function (o) {
	// handle option changes
	o = $.extend({
	  maxlength: 100,
	  message: ' characters remaining',
	  messageClass: 'maxlength-message',
	  idToken: 'max_',
	  wrapChars: ['( ', ' )']
	}, o);
	// execute for each item
	return this.each(function (i) {
	  var $el = $(this);
	  var $message = null;
	  var id = $el.attr('id');
	  var type = $el.attr('type');
	  var value = $el.val();
	  var messageId = id + '-' + i;
	  var ml = 0;
	  var il = 0;

	  if (o.maxlength > 0) {
	    // use the maxlength by default
		ml = o.maxlength;
	  } else if (id.indexOf(o.idToken) != -1) {
	    // grab the initial max to show chars remaining (find it by looking for a number
	    // after an underscore in the field's id attribute
	    ml = parseInt(id.substr(id.indexOf(o.idToken) + o.idToken.length, id.length), 10);
	  } else if (type == 'textarea') {
		// if it is a textarea multiply the rows by cols or
		ml = (parseInt($el.attr('cols'), 10) * parseInt($el.attr('rows'), 10));
	  } else if (type == 'text') {
		// if it is a text input get the max length attribute		  
		ml = parseInt($el.attr('maxLength'), 10);
	  }
	  
	  il = (value.length == 0 || value.length < ml) ? (ml - value.length) : 0;
	  
	  // create a msg holder and set the initial value 
	  $el.after('<span id="' + messageId + '" class="' + o.messageClass + '">' + o.wrapChars[0] + il + o.message + o.wrapChars[1] + '</span>');
	  $message = $('#' + messageId).css({ padding: '0px 0px 0px 5px' });

	  // add the key up listener 
	  $el.bind(
	    'keyup', 
		function(e) {
		  var $e = $(this);

		  // get the current length 
		  var cl = $e.val().length;
		  
		  if (cl > ml) {
		    $e.val($e.val().substring(0, ml));
		    return false;
		  } else {
		    // otherwise show the remaining
		     $message.text(o.wrapChars[0] + (ml - cl) + o.message + o.wrapChars[1]);
		  }
        }
	  );
	});
  }
}) (jQuery);