Skip to content

Instantly share code, notes, and snippets.

@muratcorlu
Created February 18, 2014 23:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save muratcorlu/9083266 to your computer and use it in GitHub Desktop.
Save muratcorlu/9083266 to your computer and use it in GitHub Desktop.
Masked Input Directive trying for AngularJS (It's not working)
/**
* 0 User must enter a digit (0 to 9).
* 9 User can enter a digit (0 to 9).
* # User can enter a digit, space, plus or minus sign. If skipped, enters a blank space.
* L User must enter a letter.
* ? User can enter a letter.
* A User must enter a letter or a digit.
* a User can enter a letter or a digit.
* & User must enter either a character or a space.
* C User can enter characters or spaces.
* . , : ; - / Decimal and thousands placeholders, date and time separators.
* > Coverts all characters that follow to uppercase.
* < Converts all characters that follow to lowercase.
* ! Causes the input mask to fill from left to right instead of from right to left.
* \ Characters immediately following will be displayed literally.
* "" Characters enclosed in double quotation marks will be displayed literally.
*
* '"+90 "(000) 000 0000' => '+90 (___) ___ ____'
* +90 (533) 737 11 44 => 5337371144
*
*
* Examples:
*
* '+90' (000) 000 0000
*
* <input type="text" masked-input="'+90 '(000) 000 0000" ng-model="phonenumber">
*
*/
angular.module('sahibinden.input', [])
.value('maskConfig', {
maskRules: {
'0': /[0-9]/,
'9': /[0-9\ ]/,
'#': /[0-9\-\+\ ]/,
'L': /[a-zA-Z]/,
'?': /[a-zA-Z\ ]/,
'A': /[a-zA-Z0-9]/,
'a': /[a-zA-Z0-9\ ]/,
'&': /[a-zA-Z\ ]/,
'C': /[a-zA-Z\ ]/
}
})
.directive('maskedInput', function (maskConfig) {
'use strict';
return {
restrict: 'A', // Only use as attribute
require: '?ngModel', // ngModel controller is required
link: function (scope, element, attrs, ngModel) {
var maskDefinition = attrs.maskedInput,
caretPositions = [],
// Get mask placeholder
maskPlaceholder = (function () {
var tmpPlaceholder = '',
escape = false, // For one-char escaping '\'
literalBlock = false, // For block level escaping with quotes
charIndex = 0;
angular.forEach(maskDefinition.split(''), function (char) {
// Escape next char if this is an escape char (\)
if (char == '\\') {
escape = true;
// Toggle literalBlock if this a quote char (' or ")
} else if (!escape && (char == '"' || char == '\'')) {
literalBlock = !literalBlock;
// Set rules if not an escaped char and if it's in maskRules list
} else if (!literalBlock && !escape && (char in maskConfig.maskRules)) {
caretPositions.push(charIndex);
tmpPlaceholder += '_';
charIndex++;
// This char is not in rules and is not an escape char
// Then add to placeholder directly
} else {
charIndex++;
escape = false;
tmpPlaceholder += char;
}
});
return tmpPlaceholder;
})(),
unmaskValue = function (maskedValue) {
var unmaskedValue = '';
angular.forEach(caretPositions, function (pos) {
unmaskedValue += maskedValue.substr(pos, 1);
});
return unmaskedValue.replace(/_/g, '');
},
getCaretPosition = function () {
var input = element[0],
selection;
if (input.selectionStart !== undefined) {
return input.selectionStart;
} else if (document.selection) {
// Curse you IE
input.focus();
selection = document.selection.createRange();
selection.moveStart('character', -input.value.length);
return selection.text.length;
}
return 0;
},
setCaretPosition = function (pos) {
var input = element[0],
range;
if (input.offsetWidth === 0 || input.offsetHeight === 0) {
return; // Input's hidden
}
if (input.setSelectionRange) {
input.focus();
input.setSelectionRange(pos, pos);
}
else if (input.createTextRange) {
// Curse you IE
range = input.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
},
parser = function (value) {
console.debug('parser calisti');
var isValid = false,
chars,
newValue;
console.log(value, unmaskValue(value), ngModel.$modelValue);
ngModel.$setValidity('mask', isValid);
value = unmaskValue(value);
if (value) {
chars = value.split('');
newValue = maskPlaceholder.replace('_', function () {
return chars.pop();
});
if (newValue != value) {
ngModel.$setViewValue(newValue);
ngModel.$modelValue = value;
ngModel.$render();
}
}
setCaretPosition(caretPositions[value.length]);
return value ? newValue : maskPlaceholder;
/*
if (value != maskPlaceholder) {
ngModel.$viewValue = maskPlaceholder;
ngModel.$render();
}
return value;*/
},
formatter = function (value) {
console.debug('formatter calisti');
if (value != maskPlaceholder) {
ngModel.$setViewValue(maskPlaceholder);
ngModel.$render();
}
setCaretPosition(caretPositions[0]);
return maskPlaceholder;
};
element.bind('keydown', function (event) {
var which = event.which,
$element = angular.element(this),
unmaskedValue = $element.data('unmaskedValue'),
value = $element.val(),
caretPosition = getCaretPosition(this);
unmaskedValue += String.fromCharCode(which);
$element.data('unmaskedValue', unmaskedValue);
this.value = this.value.substr(0, caretPosition) + String.fromCharCode(which) + this.value.substr(caretPosition + 2);
setCaretPosition(caretPosition + 1);
console.log(which, caretPosition, value);
return false;
});
ngModel.$parsers.push(parser);
ngModel.$formatters.push(formatter);
console.log(maskDefinition, maskPlaceholder, caretPositions);
}
};
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment