Skip to content

Instantly share code, notes, and snippets.

@JoeMeeks
Last active October 25, 2020 13:44
Show Gist options
  • Select an option

  • Save JoeMeeks/e7932fa291ba1c7e1e66597e5b52c633 to your computer and use it in GitHub Desktop.

Select an option

Save JoeMeeks/e7932fa291ba1c7e1e66597e5b52c633 to your computer and use it in GitHub Desktop.

Revisions

  1. JoeMeeks revised this gist Oct 5, 2017. 1 changed file with 56 additions and 38 deletions.
    94 changes: 56 additions & 38 deletions InputMask.ts
    Original file line number Diff line number Diff line change
    @@ -1,60 +1,78 @@
    import { Directive, Attribute } from '@angular/core';
    import { NgModel } from '@angular/forms';
    import { Directive, Attribute } from '@angular/core';

    @Directive({
    selector: '[mask]',
    host: {
    '(keyup)': 'onInputChange($event)'
    },
    providers: [NgModel]
    }
    })
    export class InputMask {
    export class InputMask {

    pattern: string;

    constructor(
    public model: NgModel,
    @Attribute('mask') pattern: string
    ) {
    this.pattern = pattern;
    }

    onInputChange(event) {
    let value = event.target.value,
    pattern = this.pattern;
    if (event.keyIdentifier === 'U+0008' || event.keyCode === 8 || event.key === 'Backspace') {
    if (value.length) { //prevent fatal exception when backspacing empty value in progressive web app
    //remove all trailing formatting then delete character
    while (pattern[value.length] && pattern[value.length] !== '*') {
    value = value.substring(0, value.length - 1);
    }
    //remove all leading formatting to restore placeholder
    if (pattern.substring(0, value.length).indexOf('*') < 0) {
    value = value.substring(0, value.length - 1);
    onInputChange(e) {
    try {

    let value = e.target.value,
    caret = e.target.selectionStart,
    pattern = this.pattern,
    reserve = pattern.replace(/\*/, 'g'),
    applied = '',
    ordinal = 0;

    if (e.keyCode === 8 || e.key === 'Backspace' || e.keyCode === 46 || e.key === 'Delete') {
    if (value.length) {
    //remove all trailing formatting
    while (value.length && pattern[value.length] && pattern[value.length] !== '*') {
    value = value.substring(0, value.length - 1);
    }
    //remove all leading formatting to restore placeholder
    if (pattern.substring(0, value.length).indexOf('*') < 0) {
    value = value.substring(0, value.length - 1);
    }
    }
    }
    } else {
    let maskIndex = value.length,
    formatted = '';
    if (value.length === 1 && value !== pattern[0]) {
    //apply leading formatting
    maskIndex = 0;
    while (maskIndex < pattern.length && pattern[maskIndex] !== '*') {
    formatted += pattern[maskIndex];
    maskIndex++;

    //apply mask characters
    for (var i = 0; i < value.length; i++) {
    //enforce pattern limit
    if (i < pattern.length) {
    //match mask
    if (value[i] === pattern[ordinal]) {
    applied += value[i];
    ordinal++;
    } else if (reserve.indexOf(value[i]) > -1) {
    //skip other reserved characters
    } else {
    //apply leading formatting
    while (ordinal < pattern.length && pattern[ordinal] !== '*') {
    applied += pattern[ordinal];
    ordinal++;
    }
    applied += value[i];
    ordinal++;
    //apply trailing formatting
    while (ordinal < pattern.length && pattern[ordinal] !== '*') {
    applied += pattern[ordinal];
    ordinal++;
    }
    }
    }
    }
    formatted += value;
    if (maskIndex < pattern.length) {
    //apply trailing formatting
    while (pattern[maskIndex] !== '*') {
    formatted += pattern[maskIndex];
    maskIndex++;
    }
    e.target.value = applied;
    if (caret < value.length) {
    e.target.setSelectionRange(caret, caret);
    }
    value = formatted;
    } catch (ex) {
    console.error(ex.message);
    }
    this.model.update.emit(value);
    }

    }
    }

    }
  2. JoeMeeks created this gist May 31, 2017.
    3 changes: 3 additions & 0 deletions InputMask.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,3 @@
    <ion-input type="tel" pattern="\d*" placeholder="(xxx) xxx-xxxx" mask="(***) ***-****" [(ngModel)]="phone" name="phone"></ion-input>

    <ion-input type="tel" pattern="\d*" placeholder="xxx-xx-xxxx" mask="***-**-****" [(ngModel)]="ssn" name="ssn"></ion-input>
    60 changes: 60 additions & 0 deletions InputMask.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,60 @@
    import { Directive, Attribute } from '@angular/core';
    import { NgModel } from '@angular/forms';

    @Directive({
    selector: '[mask]',
    host: {
    '(keyup)': 'onInputChange($event)'
    },
    providers: [NgModel]
    })
    export class InputMask {

    pattern: string;

    constructor(
    public model: NgModel,
    @Attribute('mask') pattern: string
    ) {
    this.pattern = pattern;
    }

    onInputChange(event) {
    let value = event.target.value,
    pattern = this.pattern;
    if (event.keyIdentifier === 'U+0008' || event.keyCode === 8 || event.key === 'Backspace') {
    if (value.length) { //prevent fatal exception when backspacing empty value in progressive web app
    //remove all trailing formatting then delete character
    while (pattern[value.length] && pattern[value.length] !== '*') {
    value = value.substring(0, value.length - 1);
    }
    //remove all leading formatting to restore placeholder
    if (pattern.substring(0, value.length).indexOf('*') < 0) {
    value = value.substring(0, value.length - 1);
    }
    }
    } else {
    let maskIndex = value.length,
    formatted = '';
    if (value.length === 1 && value !== pattern[0]) {
    //apply leading formatting
    maskIndex = 0;
    while (maskIndex < pattern.length && pattern[maskIndex] !== '*') {
    formatted += pattern[maskIndex];
    maskIndex++;
    }
    }
    formatted += value;
    if (maskIndex < pattern.length) {
    //apply trailing formatting
    while (pattern[maskIndex] !== '*') {
    formatted += pattern[maskIndex];
    maskIndex++;
    }
    }
    value = formatted;
    }
    this.model.update.emit(value);
    }

    }