Sunday, July 13, 2014

Javascript Input Mask jQuery Plugin

Below is a jQuery plugin that can easily be adapted to mask or limit keystrokes while you type in a textbox. This script blocks invalid keystrokes from being processed. It seems to work reliably in all modern browsers except Chrome for Android (Chrome for Android doesn't seem to fully support the keydown/keypress events). The example below only allows a valid currency value.

Credit: the caret function was borrowed from Masked Input Plugin.

Usage

$(document).ready(function()
{
 $('#text').currencyMask();
});

Code

$.fn.currencyMask = function(options)
{
    options = options || {};
    options.valid = function(s) { return s.match(/^\-?\d{0,7}(:?\.\d{0,2})?$/); };
    return this.inputMask(options);
}

$.fn.inputMask = function(options)
{
 if (this.length == 0)
        return;
 
 return this.each(function()
 {
  $(this).keydown(function(e)
  {
   if (e.which == 8 || e.which == 46) //backspace or delete?
    filter(this, false, e);
  });
  
  $(this).keypress(function(e)
  {
   if (e.which != 0 && e.which != 8) //is it printable?
    filter(this, true, e);
  });
  
  $(this).bind('paste cut blur', function(e)
  {
   setTimeout($.proxy(function()
   {
    if (!options.valid($(this).val()))
     $(this).val('');
   }, $(this)), 0);
  });
 });
 
 function filter(element, press, e)
 {
  if (!e.ctrlKey && !e.altKey && !e.metaKey)
  {
   var caret = $(element).caret();
   var begin = caret.begin;
   var end = caret.end;
   var val = $(element).val();
   var src = String.fromCharCode(e.which);
   var result = val;
   
   if (!press && e.which == 8) //backspace
   {
    begin = begin != end ? begin : Math.max(begin - 1, 0);
    result = val.substring(0, begin) + val.substring(end);
   }
   else if (!press && e.which == 46) //delete
   {
    end = begin != end ? end : Math.min(end + 1, val.length);
    result = val.substring(0, begin) + val.substring(end);
   }
   else if (press) //printable
   {
    result = val.substring(0, begin) + src + val.substring(end);
   }
   
   if (!options.valid(result))
   {
    e.preventDefault();
   }
  }
 }
};

$.fn.caret = function()
{
    if (this.length == 0)
        return;
    
 var begin = 0, end = 0;
    var item = this[0];
    
 item.focus();
    if (item.setSelectionRange)
 {
        begin = item.selectionStart;
        end = item.selectionEnd;
    }
 else if (document.selection && document.selection.createRange)
 {
        var range = document.selection.createRange();
        begin = 0 - range.duplicate().moveStart('character', -100000);
        end = begin + range.text.length;
    }
    return { begin: begin, end: end };
}

No comments:

Post a Comment