Last active
February 14, 2017 22:55
-
-
Save dfkaye/aa728f701939a25cfbcd028bc4336f1b to your computer and use it in GitHub Desktop.
CampusSolutions: telephone number validation for Intl and US values
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var angular = require('angular'); | |
angular.module('calcentral.directives').directive('ccTelPhoneInputDirective', function() { | |
/** | |
* 8,9,18,19 AUG 2016 | |
* Regexp-based attempt at parsing tel number input strings | |
* Note: should use <input type="tel" ...> to display big number buttons in small mobile devices | |
* Goals: | |
* + remove leading `+` char from International matches | |
* + re-format US matches as either `1 xxx yyy zzzz` if leading 1 is | |
* present, or as `xxx yyy zzzz` | |
* What it does: | |
* - replaces one or more consecutive non-word chars with a single space char | |
* - trims leading and trailing space chars | |
* Returns object with: | |
* + `value` containing formatted phone number if matching | |
* International or US patterns, or the user-entered value if no match. | |
* + `valid` boolean property set to true if a pattern was matched, false if | |
* no pattern is matched. | |
*/ | |
var reIntlPhone = /^(\+?((?:\d ?){6,14}\d))?\s?$/; | |
var reUsPhone = /^([\d][\W])?(\d{3})\W?[\W]?(\d{3})[\W]?(\d{4})?\s?$/; | |
var space = ' '; | |
var blank = ''; | |
var validPhone = function(phone) { | |
var value = (phone || blank).replace(/[\W]{1,}/gm, space); | |
var valid = reUsPhone.test(value) || reIntlPhone.test(value); | |
return { | |
valid: valid, | |
value: value | |
}; | |
}; | |
return { | |
require: 'ngModel', | |
restrict: 'A', | |
link: function(scope, elm, attr, ctrl) { | |
var validateAndUpdate = function(options) { | |
var showMessage = options && options.showMessage; | |
var value = elm.val(); | |
var phone = validPhone(value); | |
var valid = phone.valid; | |
if (valid || (!valid && showMessage)) { | |
ctrl.$setValidity('invalidPhoneNumber', valid); | |
var viewValue = valid ? phone.value.trim() : phone.value; | |
ctrl.$setViewValue(viewValue); | |
ctrl.$render(); | |
} | |
}; | |
elm.on('keyup', function() { | |
// The keyup handler updates the view only when a valid field value | |
// is detected, in order to hide error messages. | |
validateAndUpdate({ | |
showMessage: false | |
}); | |
}); | |
elm.on('blur', function() { | |
// The blur handler updates the view only when an invalid field value | |
// is detected, in order to show error messages. We use blur rather than | |
// change in order to prevent link or button default actions. | |
validateAndUpdate({ | |
showMessage: true | |
}); | |
}); | |
} | |
}; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 8,9 AUG 2016 | |
* Regexp-based attempt at parsing tel number input strings | |
* Note: should use <input type="tel" ... /> to display big number buttons in small mobile devices | |
* - replaces tabs and multiple space chars with single space char | |
* - trims leading and trailing space chars | |
* - removes leading `+` char from International matches | |
* - re-formats US matches as `xxx/yyy-zzz` | |
* - returns formatted value if matching International or US patterns | |
* - returns object with `error` property if no pattern is matched. | |
*/ | |
var reIntlPhone = /^(\+?((?:\d ?){6,14}\d))?$/ | |
var reUsPhone = /^\W?(\d{3})\W?[\W]?(\d{3})[\W]?(\d{4})?$/ | |
var space = ' ' | |
var blank = '' | |
var validPhone = function(value) { | |
var phone = (blank + value).replace(/\s{2,}|\t+/gm, space).trim() | |
if (reIntlPhone.test(phone)) { | |
return phone.replace(reIntlPhone, "$2") | |
} | |
if (reUsPhone.test(phone)) { | |
return phone.replace(reUsPhone, "$1/$2-$3") | |
} | |
return { | |
error: 'Please re-format the phone number [' + value + ']', | |
toString: function() { | |
return value | |
} | |
} | |
} | |
/** | |
* use cases by samsonite | |
*/ | |
var apply = function(value, $scope) { | |
console.info('applying ', value, 'to ' + $scope) | |
return $scope.phone = value | |
} | |
var error = function(phone) { | |
console.error(phone.error) | |
return phone | |
} | |
var test = function(value) { | |
var phone = validPhone(value) | |
return phone.error ? error(phone) : apply(phone, { | |
toString: function() { | |
return 'scope' | |
} | |
}) | |
} | |
/** | |
* test cases by tourister | |
*/ | |
console.log( | |
test('4444 00 00 ') | |
// intl: 4444 00 00 | |
// 4444 00 00 | |
) | |
console.log( | |
test('000.000(0000') | |
// us: 000.000(0000 | |
// 000/000-0000 | |
) | |
console.log( | |
test("44 20 79 25 09 18666") | |
// intl: 44 20 79 25 09 18666 | |
// 44 20 79 25 09 18666 | |
) | |
// be liberal in what you accept,... | |
console.log( | |
test("(123) 456 1234") | |
// us: (123) 456 1234 | |
// 123/456-1234 | |
) | |
console.log( | |
test('+1234567890') | |
// intl: +1234567890 | |
// 1234567890 | |
) | |
console.log( | |
test('1234567890') | |
// intl: 1234567890 | |
// 1234567890 | |
) | |
console.log( | |
test('123.4567890') | |
// us: 123.4567890 | |
// 123/456-7890 | |
) | |
console.log( | |
test('456&654$4567') | |
// us: 456&654$4567 | |
// 456/654-4567 | |
) | |
console.log( | |
// contains tab character between 13 and 242 | |
test('13 242 5095 5520') | |
// intl: 13 242 5095 5520 | |
// 13 242 5095 5520 | |
) | |
// should fail | |
console.error( | |
test('h23-456-7891') | |
// Please re-format the phone number [h23-456-7891] | |
// h23-456-7891 | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var reIntlPhone = /^(\+?((?:\d ?){6,14}\d))$/; | |
var reUsPhone = /^([\d][\W])?(\d{3})\W?[\W]?(\d{3})[\W]?(\d{4})$/; | |
var space = ' '; | |
var blank = ''; | |
var validPhone = function(phone) { | |
var value = (phone || blank).replace(/[\W]{1,}/gm, space).trim(); | |
var valid = value && (reUsPhone.test(value) || reIntlPhone.test(value)); | |
return { | |
valid: valid, | |
value: value.trim() | |
}; | |
}; | |
function test(value) { | |
console.log(validPhone(value)) | |
} | |
test('') | |
test('d') | |
test('11f23 123 1234') | |
test(' +12 12 33 1234 ') | |
test('1 123-123-1234 ') | |
test('(123) 123-1234 ') | |
test('123/123-1234 ') | |
test('1.123.123.1234 ') | |
test('+011 011 1110 ') | |
test('+99.--99--993') | |
test('343 343 34343 ') | |
test('+33 7 52 86 38 27') | |
test('+65 81182519') | |
test('+8227937536') | |
/* | |
Object { valid="", value=""} | |
Object { valid=false, value="d"} | |
Object { valid=false, value="11f23 123 1234"} | |
Object { valid=true, value="12 12 33 1234"} | |
Object { valid=true, value="1 123 123 1234"} | |
Object { valid=true, value="123 123 1234"} | |
Object { valid=true, value="123 123 1234"} | |
Object { valid=true, value="1 123 123 1234"} | |
Object { valid=true, value="011 011 1110"} | |
Object { valid=true, value="99 99 993"} | |
Object { valid=true, value="343 343 34343"} | |
Object { valid=true, value="33 7 52 86 38 27"} | |
Object { valid=true, value="65 81182519"} | |
Object { valid=true, value="8227937536"} | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- fragment--> | |
<form data-ng-submit="save(currentObject.data)" name="cc_page_widget_profile_work_experience"> | |
<!-- ... --> | |
<div class="cc-page-widget-profile-margin-top"> | |
<label for="cc-page-widget-profile-work-experience-phone-number"> | |
<strong>Phone Number</strong> | |
</label> | |
</div> | |
<div> | |
<input type="text" id="cc-page-widget-profile-work-experience-phone-number" | |
name="cc_profile_work_experience_phone" | |
data-cc-tel-phone-input-directive data-ng-model="currentObject.data.phone" maxlength="24"> | |
<p class="cc-page-widget-profile-section-input-error-message cc-text-red" data-ng-show="cc_page_widget_profile_work_experience.$error.invalidPhoneNumber"> | |
<i class="cc-icon-red fa fa-exclamation-circle"></i> | |
The phone number, <span data-ng-bind="cc_page_widget_profile_work_experience.cc_profile_work_experience_phone.$viewValue"></span>, is incomplete or formatted incorrectly. | |
</p> | |
</div> | |
<!-- ... --> | |
<div class="cc-page-widget-profile-margin-top"> | |
<button class="cc-button cc-button-blue" type="submit" data-ng-disabled="cc_page_widget_profile_work_experience.$invalid || isSaving || currentObject.stateFieldLoading"> | |
<span data-ng-if="!isSaving">Save</span> | |
<span data-ng-if="isSaving">Updating…</span> | |
</button> | |
<button class="cc-button" data-ng-click="closeEditor()" data-ng-disabled="isSaving">Cancel</button> | |
</div> | |
</form> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment