VSP
VSP

Reputation: 2393

Centralized way/system for defining input mask

We currently use the following logic to mask the inputs:

  1. Set a specific class to several inputs <input type="text" class="typenumdec" />

  2. In document.ready() bind a propertychange event with the rules:

    $('table tbody > tr > td.tiponumdec').children('input[type=text], input[type=number]')
            .add('input[type=text].tiponumdec, input[type=number].tiponumdec').bind('input propertychange', function () {
            $(this).val($(this).val().replace(/[^0-9,]/g, ''));
        });
    

But we wanted to centralize the logic and make it more streamlined for our developers so they dont have to add/modify the bindings.

Something like this:

  1. Developer defines somewhere the format and its name (javascript globals? key/value array?):

    var formatmoney1 ='5.2'; //5 integers and 2 decimals

    var formatmoney2 ='5.3'; //5 integers and 3 decimals

    var formatdays ='3'; //3 integers

  2. Developer sets the format to a data-atribute or css class (recommended option?)

    <input type="text" class="formatmoney1" data-formatx="formatmoney1" />

  3. On document.ready() a generic function parses the format definitions and the inputs in order to mask them depending on its assigned format

PS: we saw this plugin that seems interesting in order to cover part of the mask logic (your opinions?): http://igorescobar.github.io/jQuery-Mask-Plugin/

Upvotes: 0

Views: 1972

Answers (3)

Kevin
Kevin

Reputation: 2802

I would HIGHLY recommend taking a look at this plugin- Robin Herbots inputMask

This plugin is robust, has alot of callbacks/options and is actively developed. One of the major advantages of this plugin are the extensions which is where you define masks and aliases.

You can define a mask however you want..if you wanted to extend the out of box decimal mask definition you could do it like this...

$.extend($.inputmask.defaults.aliases, 
{
  'formatmoney1': 
  {
            mask: "99999.99",
            placeholder: "_____.__",
            alias: "decimal"
  },
  'formatmoney2': 
  {
            mask: "99999.999",
            placeholder: "_____.___",
            alias: "decimal"
  }
}

Once you have defined your mask, and extended the out of box decimal definition then you could pick up all elements and apply the inputmask.

$(document).ready(function()
{
  $('.formatmoney1').inputmask('formatmoney1');
  $('.formatmoney2').inputmask('formatmoney2');
});

This mask allows you to have a very high amount of control through the numerous callbacks and is highly configurable by setting default options.

Another option you have with using this plugin is to take advantage of the data-inputmask attribute. For example,

<input type="text" data-inputmask="'alias':'formatmoney1'" />

Be sure you look through the Usage page as well as the extension files, there are a few of them but it looks like you will want to use the jquery.inputmask.numeric.extensions.js

Upvotes: 0

Patrick Hofman
Patrick Hofman

Reputation: 156968

We are currently using HTML 5 to make 99% of all validations. You can use them in a very understandable and developer-friendly way.

For example this code will prevent entering everything else then an email address:

<input type="email" />

Or use this with custom regex:

<input type="text" name="dutch_zip_code" pattern="[A-Za-z]{4}[0-9]{2}" />

You can also set the pattern in javascript / jquery like this:

<html>
<head>
  <script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
  <script type="text/javascript" src="jquery.mask.js"></script>
</head>
<body>
<input type="text" name="dutch_zip_code" data-validation-type="dutch_zip_code" />

<script>
$(document).ready(function()
{
    $('input[type=text]').each( function()
                           {
                               var type = $(this).data('validation-type');

                               if (type == 'dutch_zip_code')
                               {
                                   $(this).attr('pattern', '[A-Za-z]{4}[0-9]{2}');
                                   //
                                   // Use jquery mask plugin:
                                   // https://plugins.jquery.com/mask/
                                   //
                                   $(this).mask('0000SS');
                               }
                           }
                         );
});
</script>
</body>
</html>

You can use modernizr for backwards compatibility.

Upvotes: 1

Adam Marshall
Adam Marshall

Reputation: 3009

As mentioned in comments, if you use bootstrap (http://getbootstrap.com/), there is the excellent Jazny Bootstrap (http://jasny.github.io/bootstrap/) plugin which makes input masks extremely easy and tidy.

Here is a fiddle which demonstrates your 3 formats: http://jsfiddle.net/JNfxa/9/

Here is the HTML:

<label>formatmoney1</label>
<input type="text" class="form-control" data-mask="99999.99" data-placeholder=" ">
<label>formatmoney2</label>
<input type="text" class="form-control" data-mask="99999.999" data-placeholder="0">
<label>formatdays</label>
<input type="text" class="form-control" data-mask="999" data-placeholder="#">

And that is it, no extra CSS or JS required.

I have used three different examples for the data-placeholder attribute, this is the character that appears for the empty digits that the user must complete, default is '_'. Where I have used '9', this will restrict the user to enter a number, there are other options detailed here: http://jasny.github.io/bootstrap/javascript/#inputmask

Now, to centralise the data-mask to a single, maintainable variable, you could bind it to an observable ViewModel property using KnockoutJS. (http://knockoutjs.com/index.html)

You can do a lot more than this, but here is an updated fiddle: http://jsfiddle.net/JNfxa/11/

Now there is some JS, to declare our observable properties containing each of the masks:

vm = {};

vm.formatmoney1Mask = ko.observable("99999.99");
vm.formatmoney2Mask = ko.observable("99999.999");
vm.formatdaysMask = ko.observable("999");

ko.applyBindings(vm);

Knockout has an attr binding, which lets you bind the value of an observable property to a custom HTML attribute of your choice. More details here: http://knockoutjs.com/documentation/attr-binding.html

The HTML changes slightly to bind the data-mask attribute instead of setting it directly:

<label>formatmoney1</label>
<input type="text" class="form-control" data-bind="attr: { 'data-mask': vm.formatmoney1Mask }" data-placeholder=" ">
<label>formatmoney2</label>
<input type="text" class="form-control" data-bind="attr: { 'data-mask': vm.formatmoney2Mask }" data-placeholder="0">
<label>formatdays</label>
<input type="text" class="form-control" data-bind="attr: { 'data-mask': vm.formatdaysMask }"  data-placeholder=" ">

What's great about this, is you can update the mask observable on the fly, and the HTML will automatically update without refreshing the page, so you could have e.g. a radio button control to choose different input mask types.

Upvotes: 0

Related Questions