A Pen by Estelle Weyl on CodePen.
Created
June 30, 2018 05:52
-
-
Save goonursultan/900f440ee4613007c30bb6879099ce3a to your computer and use it in GitHub Desktop.
input masking
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
<!-- see https://github.com/estelle/input-masking/ for a detailed explanation--><ul> | |
<li> | |
<label for="expiration">Credit Card Expiration Month</label> | |
<input id="expiration" type="tel" placeholder="MM/YY" class="masked" pattern="(1[0-2]|0[1-9])\/\d\d" data-valid-example="11/18" title="2-digit month and 2-digit year"> | |
</li> | |
<li> | |
<label for="zip">Zip Code</label> | |
<input id="zip" type="tel" name="zipcode" placeholder="XXXXX" pattern="\d{5}" class="masked" title="5-digit zip code"> | |
</li> | |
<li> | |
<label for="zipca">Canadian Zip Code</label> | |
<input id="zipca" type="text" name="zipcodeca" placeholder="XXX XXX" pattern="\w\d\w \d\w\d" class="masked" data-charset="_X_ X_X" title="6-character alphanumeric zip code in the format of A1A 1A1"> | |
</li> | |
<li> | |
<label for="tel">Telephone</label> | |
<input id="tel" type="tel" name="phone" placeholder="(XXX) XXX-XXXX" pattern="\(\d{3}\) \d{3}\-\d{4}" class="masked" title="10-digit number"> | |
</li> | |
<li> | |
<label for="cc">Credit Card Number</label> | |
<input id="cc" type="tel" name="ccnumber" placeholder="XXXX XXXX XXXX XXXX" pattern="\d{4} \d{4} \d{4} \d{4}" class="masked" title="16-digit number"> | |
</li> | |
</ul> |
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 masking = { | |
// User defined Values | |
//maskedInputs : document.getElementsByClassName('masked'), // add with IE 8's death | |
maskedInputs : document.querySelectorAll('.masked'), // kill with IE 8's death | |
maskedNumber : 'XdDmMyY9', | |
maskedLetter : '_', | |
init: function () { | |
masking.setUpMasks(masking.maskedInputs); | |
masking.maskedInputs = document.querySelectorAll('.masked'); // Repopulating. Needed b/c static node list was created above. | |
masking.activateMasking(masking.maskedInputs); | |
}, | |
setUpMasks: function (inputs) { | |
var i, l = inputs.length; | |
for(i = 0; i < l; i++) { | |
masking.createShell(inputs[i]); | |
} | |
}, | |
// replaces each masked input with a shall containing the input and it's mask. | |
createShell : function (input) { | |
var text = '', | |
placeholder = input.getAttribute('placeholder'); | |
input.setAttribute('maxlength', placeholder.length); | |
input.setAttribute('data-placeholder', placeholder); | |
input.removeAttribute('placeholder'); | |
text = '<span class="shell">' + | |
'<span aria-hidden="true" id="' + input.id + | |
'Mask"><i></i>' + placeholder + '</span>' + | |
input.outerHTML + | |
'</span>'; | |
input.outerHTML = text; | |
}, | |
setValueOfMask : function (e) { | |
var value = e.target.value, | |
placeholder = e.target.getAttribute('data-placeholder'); | |
return "<i>" + value + "</i>" + placeholder.substr(value.length); | |
}, | |
// add event listeners | |
activateMasking : function (inputs) { | |
var i, l; | |
for (i = 0, l = inputs.length; i < l; i++) { | |
if (masking.maskedInputs[i].addEventListener) { // remove "if" after death of IE 8 | |
masking.maskedInputs[i].addEventListener('keyup', function(e) { | |
masking.handleValueChange(e); | |
}, false); | |
} else if (masking.maskedInputs[i].attachEvent) { // For IE 8 | |
masking.maskedInputs[i].attachEvent("onkeyup", function(e) { | |
e.target = e.srcElement; | |
masking.handleValueChange(e); | |
}); | |
} | |
} | |
}, | |
handleValueChange : function (e) { | |
var id = e.target.getAttribute('id'); | |
switch (e.keyCode) { // allows navigating thru input | |
case 20: // caplocks | |
case 17: // control | |
case 18: // option | |
case 16: // shift | |
case 37: // arrow keys | |
case 38: | |
case 39: | |
case 40: | |
case 9: // tab (let blur handle tab) | |
return; | |
} | |
document.getElementById(id).value = masking.handleCurrentValue(e); | |
document.getElementById(id + 'Mask').innerHTML = masking.setValueOfMask(e); | |
}, | |
handleCurrentValue : function (e) { | |
var isCharsetPresent = e.target.getAttribute('data-charset'), | |
placeholder = isCharsetPresent || e.target.getAttribute('data-placeholder'), | |
value = e.target.value, l = placeholder.length, newValue = '', | |
i, j, isInt, isLetter, strippedValue; | |
// strip special characters | |
strippedValue = isCharsetPresent ? value.replace(/\W/g, "") : value.replace(/\D/g, ""); | |
for (i = 0, j = 0; i < l; i++) { | |
var x = | |
isInt = !isNaN(parseInt(strippedValue[j])); | |
isLetter = strippedValue[j] ? strippedValue[j].match(/[A-Z]/i) : false; | |
matchesNumber = masking.maskedNumber.indexOf(placeholder[i]) >= 0; | |
matchesLetter = masking.maskedLetter.indexOf(placeholder[i]) >= 0; | |
if ((matchesNumber && isInt) || (isCharsetPresent && matchesLetter && isLetter)) { | |
newValue += strippedValue[j++]; | |
} else if ((!isCharsetPresent && !isInt && matchesNumber) || (isCharsetPresent && ((matchesLetter && !isLetter) || (matchesNumber && !isInt)))) { | |
// masking.errorOnKeyEntry(); // write your own error handling function | |
return newValue; | |
} else { | |
newValue += placeholder[i]; | |
} | |
// break if no characters left and the pattern is non-special character | |
if (strippedValue[j] == undefined) { | |
break; | |
} | |
} | |
if (e.target.getAttribute('data-valid-example')) { | |
return masking.validateProgress(e, newValue); | |
} | |
return newValue; | |
}, | |
validateProgress : function (e, value) { | |
var validExample = e.target.getAttribute('data-valid-example'), | |
pattern = new RegExp(e.target.getAttribute('pattern')), | |
placeholder = e.target.getAttribute('data-placeholder'), | |
l = value.length, testValue = ''; | |
//convert to months | |
if (l == 1 && placeholder.toUpperCase().substr(0,2) == 'MM') { | |
if(value > 1 && value < 10) { | |
value = '0' + value; | |
} | |
return value; | |
} | |
// test the value, removing the last character, until what you have is a submatch | |
for ( i = l; i >= 0; i--) { | |
testValue = value + validExample.substr(value.length); | |
if (pattern.test(testValue)) { | |
return value; | |
} else { | |
value = value.substr(0, value.length-1); | |
} | |
} | |
return value; | |
}, | |
errorOnKeyEntry : function () { | |
// Write your own error handling | |
} | |
} | |
masking.init(); |
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
/* Libary CSS */ | |
.shell { | |
position: relative; | |
line-height: 1; | |
span { | |
position: absolute; | |
left: 3px; | |
top: 1px; | |
color: red; | |
pointer-events: none; | |
z-index: -1; | |
i { /* any of these 3 will work */ | |
color: transparent; | |
opacity: 0; | |
visibility: hidden; | |
} | |
} | |
} | |
input.masked, | |
.shell span { | |
font-size: 16px; | |
font-family: monospace; | |
padding-right: 10px; | |
background-color: transparent; | |
text-transform: uppercase; | |
} | |
/* Look and feel (not lib specific) */ | |
li { | |
line-height: 2; | |
font-family: helvetica; | |
list-style-type: none; | |
border-bottom: 1px solid #ccc; | |
} | |
label { | |
display: inline-block; | |
width: 14em; | |
} | |
input { | |
border: none; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment