Coder Social home page Coder Social logo

ngmask's Introduction

ngMask

Best Angular JS mask alternative!

Angular mask without dependencies (NO JQUERY). Pure javascript and only ~6kb! It gives you power to create your mask with optional fields in accordance with your business.

=======

GitHub version Bower version Build Status Code Climate Test Coverage NPM Dependencies

Chrome Firefox IE8+ Opera Safari

TL;DR

Check live examples here.

Install

With Bower

  • Install the dependency:

    bower install angular-mask --save
  • Add ngMask.min.js to your code:

    <script src='bower_components/ngMask/dist/ngMask.min.js'></script>
  • Include module dependency:

    angular.module('yourApp', ['ngMask']);

Without Bower:

  • Download the ngMask.min.js file from dist folder:

    wget https://raw.githubusercontent.com/candreoliveira/ngMask/master/dist/ngMask.min.js
  • Add ngMask.min.js to your code:

    <script src='ngMask.min.js'></script>
  • Include module dependency:

    angular.module('yourApp', ['ngMask']);

======

How To Use

  1. Add ngMask plugin after your AngularJS.

    <script src="angular.min.js"></script>
    <script src='ngMask.min.js'></script>
  2. Add ngMask module dependency to your app.

    angular.module('yourApp', ['ngMask']);
  3. Use the avaiable patterns to create your mask. Set the mask attribute.

    <input type='text' ng-model='maskModel' mask='39/19/9999' />
  4. Adjust your mask options.

    <input type='text' ng-model='maskModel' ng-value='0/3/9' mask='3/9?' mask-repeat='2' mask-restrict='accept' mask-clean='true' mask-validate='false' mask-limit='false' />

======

Available Patterns

You can make your mask using some patterns available. If you use a pattern not specified below to construct your mask, It'll be considered a divisor. A dividor is a character used to group semantic elements, for example: "/" in dates to separate days, months and years, "-" in SSN to separate area, group and serial numbers or "." in IPv4 to create 4 groups of 8 bits.

Common Patterns

    • =====> /./
    • Any single character
  • w =====> /\w/
    • Any word character (letter, number, underscore)
  • W =====> /\W/
    • Any non-word character
  • d =====> /\d/
    • Any digit
  • D =====> /\D/
    • Any non-digit
  • s =====> /\s/
    • Any whitespace character
  • S =====> /\S/
    • Any non-whitespace character
  • b =====> /\b/
    • Any word boundary

Number Patterns

  • 9 =====> /[0-9]/
    • Valid numbers: 0,1,2,3,4,5,6,7,8,9
  • 8 =====> /[0-8]/
    • Valid numbers: 0,1,2,3,4,5,6,7,8
  • 7 =====> /[0-7]/
    • Valid numbers: 0,1,2,3,4,5,6,7
  • 6 =====> /[0-6]/
    • Valid numbers: 0,1,2,3,4,5,6
  • 5 =====> /[0-5]/
    • Valid numbers: 0,1,2,3,4,5
  • 4 =====> /[0-4]/
    • Valid numbers: 0,1,2,3,4
  • 3 =====> /[0-3]/
    • Valid numbers: 0,1,2,3
  • 2 =====> /[0-2]/
    • Valid numbers: 0,1,2
  • 1 =====> /[0-1]/
    • Valid numbers: 0,1
  • 0 =====> /[0]/
    • Valid numbers: 0

Especial Patterns

  • ? =====> /?/
    • Optional character. It makes the previous pattern optional.
  • A =====> /[A-Z]/
    • Any uppercase alphabet letter without accents
  • a =====> /[a-z]/
    • Any lowercase alphabet letter without accents
  • Z =====> /[A-ZÇÀÁÂÃÈÉÊẼÌÍÎĨÒÓÔÕÙÚÛŨ]/
    • Any uppercase alphabet letter with accents
  • z =====> /[a-zçáàãâéèêẽíìĩîóòôõúùũüû]/
    • Any lowercase alphabet letter with accents
  • @ =====> /[a-zA-Z]/
    • Any alphabet letter without accents
  • # =====> /[a-zA-ZçáàãâéèêẽíìĩîóòôõúùũüûÇÀÁÂÃÈÉÊẼÌÍÎĨÒÓÔÕÙÚÛŨ]/
    • Any alphabet letter with accents
  • % =====> /[0-9a-zA-zçáàãâéèêẽíìĩîóòôõúùũüûÇÀÁÂÃÈÉÊẼÌÍÎĨÒÓÔÕÙÚÛŨ]/
    • Any digit and alphabet letter with accents

======

Options

  • NgModel (required): model object
    • Attribute 'ng-model'
    • The model of input.
  • Mask (required): mask definition
    • Attribute 'mask'
    • The mask for input.
  • NgValue: initial mask value (default: undefined)
    • Attribute 'ng-value'
    • The initial value of input.
  • Restrict: 'select', 'reject' or 'accept' (default: select)
    • Attribute 'mask-restrict' or 'restrict'
    • The way how ngMask will interact with user input.
      • Select restriction: The input will show the char inputted even on error cases. If it has errors, the wrong char will be selected.
      • Reject restriction: The input will show the char inputted on successful cases. If it has errors, the wrong char will be rejected.
      • Accept restriction: The input will always show the char inputted. No matter it's right or wrong.
  • Repeat: number - repeat mask n times (default: undefined)
    • Attribute 'mask-repeat' or 'repeat'
    • Repeats the mask attribute the defined times.
  • Clean: 'true' or 'false' (default: false)
    • Attribute 'mask-clean' or 'clean'
    • Cleans model value. Removes divisors from model value.
  • Validate: 'true' or 'false' (default: true)
    • Attribute 'mask-validate' or 'validate'
    • Applies validation. Uses form controller setValidity method.
  • Limit: 'true' or 'false' (default: true)
    • Attribute 'mask-limit' or 'limit'
    • Limits the max length inputted according with mask.

======

Examples

How to ngMask

======

License

Open Source

The MIT License (MIT)

Copyright (c) 2014 @candreoliveira

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

ngmask's People

Contributors

aaronroberson avatar benjamincharity avatar candreoliveira avatar cavarzan avatar cawabunga avatar cmelone avatar greg-harrison avatar guilhermegm avatar hmaesta avatar huyhong avatar ldeavila avatar ryan-kimber avatar tamtakoe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ngmask's Issues

Problems when writing in android

Let me explain. let's say I've written this mask 99/99/9999. If i write the sequence 1, 2, 3, 4, 5 , 6 etc in this order. The result is this 12/45/63. Because when come the time to put the divisor, the cursor back to back.

mask defined in the variable scope

hello!
I am using your module, but I have a problem.
when I define the mask through a scope variable, defined mask is not working. If I put string D? S ?, insert points every 2 or 3 positions or not working properly.

Mask is not active until focused

Mask should be immediately active on the load of the view.

If the user does not provide a constant value for ng-value then the mask does not initialize until focus is gained.

Currently, when the page loads and the phone number is masked, the string is '1231234567' and when the user adds focus to the input field, then the mask is applied '(123) 123-4567'.

Currently using Chrome edge.

"value.replace is not a function" error with numeric view model values

Issue: If the value of the input's ng-model is numeric (phone is stored and coming back as a number from db), a "value.replace is not a function" error is thrown in the removeDivisors function.

Quick Resolution: Add the following line at the top removeDivisors():
value = typeof value === 'String'? value: value.toString();

NPM support

Hi,

Awesome directive.

I need to start using this via NPM rather than bower. The package name in package.json is a bit unclear as just "mask" and it does not seem to have been registered in the NPM registry.

Would you please rename it to "ngMask" and register on the registry...

Cheers,

Andy

Bump version to 1.2

At current time the bower version at tag 1.2 still with "version": "0.1.0" value.

Can you bump the version to 1.3 to be able to download via bower?

Thanks!

Using input with ng-if

Hi Carlos!

I'm trying to use this directive in an input that also uses ng-if. (And I want to use ng-if because I want to reuse the input as a directive itself.)

I've spent a lot of time trying to figure out why my ng-model wasn't binding, but after a lot of trial and error, it looks like ngMask thinks that no ng-model or mask is available, because I'm using ng-if...and the element isn't on the DOM yet. Tested this by using ng-show/ng-hide and ngMask works amazingly, but was wondering if you can help me figure out how to use ngMask on ng-if elements?

Thanks a lot!

Select

When I select all the text in the field and click delete, it is not deleted.

And "arrow left" works wrong.

If the Javascript array object has additional prototypes, removeWrongPositions fails

Hello,

Here is the scenario we are running into using ngMask:

We have a function called "removeItem" assigned to the Array object in Javascript (Array.prototype.removeItem = function () { ... }); when the "removeWrongPositions" function is called, the for loop correctly loops over the wrong positions, resulting in the correct output, but then preforms an additional loop for this "removeItem" function.

This results in the input not being updated, and the invalid characters not to be removed.

The simplest solution to this would be to a for loop which uses a counter, as the for...in loop is designed to iterate over properties of an object.

Wrong caret position

Hi,

Very nice component. I am using it for a date mask. It works fine on Android 4.4+ and iOS, but having issues with it on Android 4.2.2 . Below is the input code:

input type="text" placeholder="Date of Birth (mm/dd/yyyy)" restrict="select" mask="19/39/9999" ng-model="form.dob"

I'm trying to enter a date of 12/02/1995. After I enter 12 and then hit 0, it correctly puts the "/" in front of the zero becoming "12/0", but the caret position is not at the end of the text, but right before the last digit. Even if I try to change the caret position by tapping at the end of the text, it doesn't help. I have to change to another input and then back. I hope there is a fix for this. Please advise. Thanks.

Date mask

I am trying to use ngMask in angular 1.3 with a Date object on the ng-model. It is not changing the output of the date in the input field. Is ngMask compatible with dates?

Support for angular 1.3

Hello. Thanks for the module, it's look pretty cool.

I'm currently evaluating it for using with angular 1.3. According to bower.json it's supported. Somebody already tried using that (#19).

On the test side it looks ok - no errors when angular updated to 1.3.15. From what was mentioned in 1.2-1.3 migration guide code is using:

  • setViewValue
  • modelValue
  • input with type as date, time, datetime-local, month, week requires date module

How much is missing to have stable angular 1.3 support?

Mask not applied to initial values

If a value is already present in a masked field, the mask is not applied until after the user selects the field, then deselects the field.

For example:

initial-value-not-formatted

constant number in mask

Hey @candreoliveira, thanks for the plugin!

I want to have this kind of mask for phone number: +1 (999) 999-99-99. Here number 1 should be constant 1, just like plus sign.

Is it possible to set constant number in the mask? I haven't found an example of it.

Use ngMask on elements other than input

Is there a way to mask data not in an input element? For example...

item.ssn = 123456789;

And in HTML...

<span mask="999-99-9999">{{item.ssn}}</span>

or even...

{{item.ssn|mask:'999-99-9999'}}

I would expect both of these to result in 123-45-6789 being displayed.

0-5 digits?

I can't seem to get the regex max implementation to work. I need to create a mask that is a number, 0-5 digits in length. I've tried various things like the following but to no avail:

<input mask="/\d{0-5}\" />

Mask visibility always on (ie mask placeholder)

Provide the ability to always see the mask. As an example, when viewing an input field for a phone number, instead of filling in the mask as the user types, we would see (__) - in the empty input field. As the values are inserted, they replace the relative _underscore in the masked text string.

Ideally, one could control this visibility (displayPlaceholder) through a simple T/F (default F) property and also have an optional parameter to provide the placeholder (default is '_' underscore)

Time Mask

How can I specify a mask that has a rule based on the previous value?

For example the mask 29:59 will allow the time 29:59. It should only allow [4-9] if the first character is 1.

SVG conflict

the ngMask conflicts when we use svg with the mask attribute.

error with input type number

When I use the mask it returns an error (below), I guess you are expecting a string.
TypeError: a.split is not a function

ngMask makes form dirty

Form becomes dirty after the mask is applied.

I would have expected the form to stay pristine until the user interacted with the form.

IP Address

The ability to do IP Addresses would be great.

Problem is you need 'conditional' for example:

1.1.1.123
123.123.123.123
12.1.123.12

Mask accepts single digit for (999)-999-9999

I've created a plnkr demonstrating the issue.

When we specify a North American telephone mask (that is, (999)-999-9999), ng-valid-mask is added and $valid = true for a single digit entered into the field. When subsequent digits are added, it switches to ng-invalid-mask and $valid = false. It will also populate the single-digit into the model.

The expected behaviour is that a single digit would not satisfy the mask, and so the field should have $valid = false, ng-model's value should be clear and the input field should have the class ng-invalid-mask.

Having an issue with gridView onClickListener

Hey Guys,

Relatively new to android programming and am needing a bit of help! I am trying to make LEDs light up when gridView items are pressed... However for not i am just trying to make them toast their positions. Can someone look at my code and give me a nudge in the right direction?

package edu.rose_hulman.doleshmc.claysinebriator;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageButton;
import android.widget.Toast;

public class ClaysInebriator extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_clays_inebriator);

    GridView gridView = (GridView) findViewById(R.id.gridview);
    gridView.setAdapter(new ImageAdapter(this));

    gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            if(position == 0) {
            }


            if(position == 1){
                Toast.makeText(ClaysInebriator.this, "APASATAAAAAAA" + position, Toast.LENGTH_SHORT).show();
            }
            if(position ==2){
                Toast.makeText(ClaysInebriator.this, "APASATAAAAAAA" + position, Toast.LENGTH_SHORT).show();
            }
        }
    });
}

public void handleLedOkay(View view) {

// Log.d("LEDToggle","This is a log we wont use logs much")
Toast.makeText(this, "You clicked OK", Toast.LENGTH_SHORT).show();

}

public class ImageAdapter extends BaseAdapter {
    private Context mContext;

    public ImageAdapter(Context c) {
        mContext = c;
    }

    public int getCount() {
        return mThumbIds.length;
    }

    public Object getItem(int position) {
        return null;
    }

    public long getItemId(int position) {
        return 0;
    }

    // create a new ImageButton for each item referenced by the Adapter
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageButton imageView;
        if (convertView == null) {
            // if it's not recycled, initialize some attributes
            imageView = new ImageButton(mContext);
            imageView.setLayoutParams(new GridView.LayoutParams(400, 400));
            imageView.setScaleType(ImageButton.ScaleType.CENTER_CROP);
            imageView.setPadding(50, 50, 50, 50);
        } else {
            imageView = (ImageButton) convertView;
        }

        imageView.setImageResource(mThumbIds[position]);
        return imageView;
    }

    // references to our images
    private Integer[] mThumbIds = {
            R.drawable.vodka_sour, R.drawable.whisky_sour,
            R.drawable.dirty_shirley, R.drawable.long_island,
            R.drawable.mojito, R.drawable.vodka_sour, R.drawable.whisky_sour,
            R.drawable.dirty_shirley, R.drawable.long_island,
            R.drawable.mojito, R.drawable.vodka_sour, R.drawable.whisky_sour,
            R.drawable.dirty_shirley, R.drawable.long_island,
            R.drawable.mojito, R.drawable.vodka_sour, R.drawable.whisky_sour,
            R.drawable.dirty_shirley, R.drawable.long_island,
            R.drawable.mojito
    };
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_clays_inebriator, menu);
    return true;

}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

}

Restricting input causes strange behaviour

Hello,

I try to mask a number input by:

However, when I try to type a character other than number ('a' for example), the input gets reset and I have to type all from the beginning.

E.g. when I type '111a', as soon as I press 'a' the input gets reset to ''.

I can't reproduce the same behaviour on demo page or jsfiddle. I just want to ask, what might be causing this issue?

Support for reverse mask - for field like Amount

I found this angular plugin very useful because of its simplicity ,no jquery dependency and variety of options but one of the missing element is support for reverse masking.Reverse masking is require for inputs like amount. For example given mask : 9?99,999 on value : 40000 is giving output as 400,00 where as expected output is 40,000

Add option to write separators before the next char is written

Hi! i love this plugin and would like to propose a feature:
Right now, if im writing a date (for example) and i want to write 10/30/2015, the first / will appear after i write the number 3.
What i would like to propose, is to add an option to write the / before the 3, so when i write 10, it auto writes a /.
Sorry for the bad english, i don't know how to explain it better, but i think the idea is pretty much clear.
I think doing this would help the user to learn about the auto format really fast, reducing the possible errors, since the user will not try to write the separators. Right now, the user will probably try to write a / and that is a ver common wrong behavior.
What do you think?
Thanks!

ngMask throws error if model is number

ngMask throws error if model is number (phone numbers can be storaged in DB as numbers, etc.).

var regex = new RegExp('[\-\ \)\(\+]', 'g');
var value = 79210936122;
value.replace(regex, ''); //TypeError: value.replace is not a function

It can be fixed in ngMask/src/services/maskService.js in function removeDivisors:

return value && String(value).replace(regex, '');

Feature: Option to dynamically toggle ngMask.

mask-validate isn't enough if you want to hide some inputs and ignore their errors in regards to form validity. I propose adding an option, maskEnabled, which defaults to true. When maskEnabled evaluates to falsey, the directive should ignore the mask pattern and still allow the form validity to pass.

I'll get started on the change since I need it now :) - let me know if you are interested and I'll submit a pull request once I get it working.

Demo Page

You show have a live demo page on like Github pages so users can eval your project w/o downloading.

Validity not set to true when field is cleared

When a user clears the input field the form remains invalid.
If you change line 18 of mask.js from:

   if(!values){ return undefined; }

to

if (controller.$isEmpty(values)){ 
   controller.$setValidity('mask', true);
   return values; 
}

the issue is resolved.

Safari issue with following mask.

Currently using this mask to identify/mask SSN number and some how it fails on the fullRegex.test(viewValueWithDivisors) and controller$isEmpty(controller.$nodeValue) in the parser,

9?9?991939-9999

when i tried to enter 88888 and then enter a last 8 so the new number is 888888, the validation gives an error and i cannot change any chars in the input

i only encounter this issue on safari browser, is this any known issue?

arrow key editing broken with mask divider characters

When using a mask such as "999999", one can use the left arrow key or mouse to place the caret within the string and typing characters will insert at the caret position as expected. If a mask such as "99999-99999" is used, if the left arrow key is used to move the caret backwards, typing a character will cause the caret to move to the end of the input before inserting the character. This makes editing difficult.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.