以下是 信用卡表单验证插件Creditly js代码 的示例演示效果:
部分效果截图:
HTML代码(creditly.html):
<section class="creditly-wrapper">
<div class="credit-card-wrapper">
<div class="first-row form-group">
<div class="col-sm-8 controls">
<label class="control-label">Card Number</label>
<input class="number credit-card-number form-control"
type="text" name="number"
pattern="\d*"
inputmode="numeric" autocomplete="cc-number" autocompletetype="cc-number" x-autocompletetype="cc-number"
placeholder="•••• •••• •••• ••••">
</div>
<div class="col-sm-4 controls">
<label class="control-label">CVV</label>
<input class="security-code form-control"·
inputmode="numeric"
pattern="\d*"
type="text" name="security-code"
placeholder="•••">
</div>
</div>
<div class="second-row form-group">
<div class="col-sm-8 controls">
<label class="control-label">Name on Card</label>
<input class="billing-address-name form-control"
type="text" name="name"
placeholder="John Smith">
</div>
<div class="col-sm-4 controls">
<label class="control-label">Expiration</label>
<input class="expiration-month-and-year form-control"
type="text" name="expiration-month-and-year"
placeholder="MM / YY">
</div>
</div>
<div class="card-type">
</div>
</div>
</section>
HTML代码(index.html):
<html>
<meta charset="utf-8">
<title>信用卡表单验证插件Creditly</title>
<link rel="stylesheet" href="src/creditly.css">
<link rel="stylesheet" href="src/teaser.css">
<script src="src/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="src/creditly.js"></script>
<script type="text/javascript">
$(function() {
var creditly = Creditly.initialize(
'.creditly-wrapper .expiration-month-and-year',
'.creditly-wrapper .credit-card-number',
'.creditly-wrapper .security-code',
'.creditly-wrapper .card-type');
$(".creditly-card-form .submit").click(function(e) {
e.preventDefault();
var output = creditly.validate();
if (output) {
// Your validated credit card output
console.log(output);
}
});
});
</script>
</html>
<body>
<div class="banner">
<div class="row">
<div class="header">
</div>
<form class="creditly-card-form">
<section class="creditly-wrapper">
<div class="credit-card-wrapper">
<div class="first-row form-group">
<div class="col-sm-8 controls">
<label class="control-label">Card Number</label>
<input class="number credit-card-number form-control"
type="text" name="number"
pattern="\d*"
inputmode="numeric" autocomplete="cc-number" autocompletetype="cc-number" x-autocompletetype="cc-number"
placeholder="•••• •••• •••• ••••">
</div>
<div class="col-sm-4 controls">
<label class="control-label">CVV</label>
<input class="security-code form-control"路
inputmode="numeric"
pattern="\d*"
type="text" name="security-code"
placeholder="•••">
</div>
</div>
<div class="second-row form-group">
<div class="col-sm-8 controls">
<label class="control-label">Name on Card</label>
<input class="billing-address-name form-control"
type="text" name="name"
placeholder="John Smith">
</div>
<div class="col-sm-4 controls">
<label class="control-label">Expiration</label>
<input class="expiration-month-and-year form-control"
type="text" name="expiration-month-and-year"
placeholder="MM / YY">
</div>
</div>
<div class="card-type"></div>
</div>
</section>
<button class="submit"><span>Submit</span></button>
</form>
</div>
</div>
</body>
JS代码(creditly.js):
var Creditly = (function(){
var getInputValue = function(e,selector){
var inputValue = $.trim($(selector).val());
inputValue = inputValue + String.fromCharCode(e.which);
return getNumber(inputValue);
}
;
var getNumber = function(string){
return string.replace(/[^\d]/g,"");
}
;
var reachedMaximumLength = function(e,maximumLength,selector){
return getInputValue(e,selector).length > maximumLength;
}
;
// Backspace,delete,tab,escape,enter,.,Ctrl+a,Ctrl+c,Ctrl+v,home,end,left,right var isEscapedKeyStroke = function(e){
// Key event is for a browser shortcut if (e.metaKey || e.ctrlKey) return true;
// If keycode is a space if (e.which === 32) return false;
// If keycode is a special char (WebKit) if (e.which === 0) return true;
// If char is a special char (Firefox) if (e.which < 33) return true;
return false;
}
;
var isNumberEvent = function(e){
return (/^\d+$/.test(String.fromCharCode(e.which)));
}
;
var onlyAllowNumeric = function(e,maximumLength,selector){
e.preventDefault();
// Ensure that it is a number and stop the keypress if (!isNumberEvent(e)){
return false;
}
return true;
}
;
var isAmericanExpress = function(number){
return number.match("^(34|37)");
}
;
var shouldProcessInput = function(e,maximumLength,selector){
var target = $(e.currentTarget);
if (reachedMaximumLength(e,maximumLength,selector)){
e.preventDefault();
return false;
}
if ((target.prop("selectionStart") !== target.val().length)){
return false;
}
return (!isEscapedKeyStroke(e)) && onlyAllowNumeric(e,maximumLength,selector);
}
;
var CvvInput = (function(){
var selector;
var numberSelector;
var createCvvInput = function(mainSelector,creditCardNumberSelector){
selector = mainSelector;
numberSelector = creditCardNumberSelector;
var getMaximumLength = function(isAmericanExpressCard){
if (isAmericanExpressCard){
return 4;
}
else{
return 3;
}
}
;
$(selector).keypress(function(e){
$(selector).removeClass("has-error");
var number = getInputValue(e,numberSelector);
var cvv = getInputValue(e,selector) var isAmericanExpressCard = isAmericanExpress(number);
var maximumLength = getMaximumLength(isAmericanExpressCard);
if (shouldProcessInput(e,maximumLength,selector)){
$(selector).val(cvv);
}
}
);
}
;
return{
createCvvInput:createCvvInput}
;
}
)();
var NumberInput = (function(){
var selector;
var americanExpressSpaces = [4,10,15];
var defaultSpaces = [4,8,12,16];
var getMaximumLength = function(isAmericanExpressCard){
if (isAmericanExpressCard){
return 15;
}
else{
return 16;
}
}
;
var createNumberInput = function(mainSelector){
selector = mainSelector;
$(selector).keypress(function(e){
$(selector).removeClass("has-error");
var number = getInputValue(e,selector);
var isAmericanExpressCard = isAmericanExpress(number);
var maximumLength = getMaximumLength(isAmericanExpressCard);
if (shouldProcessInput(e,maximumLength,selector)){
var newInput;
if (isAmericanExpressCard){
newInput = addSpaces(number,americanExpressSpaces);
}
else{
newInput = addSpaces(number,defaultSpaces);
}
$(selector).val(newInput);
$(selector).trigger("changed_input");
}
}
);
}
;
var addSpaces = function(number,spaces){
var parts = [] var j = 0;
for (var i=0;
i<spaces.length;
i++){
if (number.length > spaces[i]){
parts.push(number.slice(j,spaces[i]));
j = spaces[i];
}
else{
if (i < spaces.length){
parts.push(number.slice(j,spaces[i]));
}
else{
parts.push(number.slice(j));
}
break;
}
}
if (parts.length > 0){
return parts.join(" ");
}
else{
return number;
}
}
;
return{
createNumberInput:createNumberInput}
;
}
)();
var Validation = (function(){
var Validators = (function(){
var expirationRegex = /(\d\d)\s*\/\s*(\d\d)/;
var creditCardExpiration = function(selector,data){
var expirationVal = $.trim($(selector).val());
var match = expirationRegex.exec(expirationVal);
var isValid = false;
var outputValue = ["",""];
if (match && match.length === 3){
var month = parseInt(match[1],10);
var year = "20" + match[2];
if (month >= 0 && month <= 12){
isValid = true;
var outputValue = [month,year];
}
}
return{
"is_valid":isValid,"messages":[data["message"]],"output_value":outputValue}
;
}
;
var isValidSecurityCode = function(isAmericanExpress,securityCode){
if ((isAmericanExpress && securityCode.length == 4) || (!isAmericanExpress && securityCode.length == 3)){
return true;
}
return false;
}
;
var creditCard = function(selector,data){
var rawNumber = $(data["creditCardNumberSelector"]).val();
var number = $.trim(rawNumber).replace(/\D/g,"");
var rawSecurityCode = $(data["cvvSelector"]).val();
var securityCode = $.trim(rawSecurityCode).replace(/\D/g,"");
var messages = [];
var isValid = true;
var selectors = [];
if (!isValidCreditCardNumber(number)){
messages.push(data["message"]["number"]);
selectors.push(data["creditCardNumberSelector"]);
isValid = false;
}
if (!isValidSecurityCode(isAmericanExpress(number),securityCode)){
messages.push(data["message"]["security_code"]);
selectors.push(data["cvvSelector"]);
isValid = false;
}
result ={
"is_valid":isValid,"output_value":[number,securityCode],"selectors":selectors,"messages":messages}
;
return result;
}
;
var isAmericanExpress = function(number){
return (number.length == 15);
}
;
// Luhn Algorithm. var isValidCreditCardNumber = function(value){
if (value.length === 0) return false;
// accept only digits,dashes or spaces if (/[^0-9-\s]+/.test(value)) return false;
var nCheck = 0,nDigit = 0,bEven = false;
for (var n = value.length - 1;
n >= 0;
n--){
var cDigit = value.charAt(n);
var nDigit = parseInt(cDigit,10);
if (bEven){
if ((nDigit *= 2) > 9) nDigit -= 9;
}
nCheck += nDigit;
bEven = !bEven;
}
return (nCheck % 10) == 0;
}
;
return{
creditCard:creditCard,creditCardExpiration:creditCardExpiration,}
;
}
)();
var ValidationErrorHolder = (function(){
var errorMessages = [];
var selectors = [];
var addError = function(selector,validatorResults){
if (validatorResults.hasOwnProperty("selectors")){
selectors = selectors.concat(validatorResults["selectors"]);
}
else{
selectors.push(selector)}
errorMessages.concat(validatorResults["messages"]);
}
;
var triggerErrorMessage = function(){
var errorsPayload ={
"selectors":selectors,"messages":errorMessages}
;
for (var i=0;
i<selectors.length;
i++){
$(selectors[i]).addClass("has-error");
}
$("body").trigger("creditly_client_validation_error",errorsPayload);
}
;
return{
addError:addError,triggerErrorMessage:triggerErrorMessage}
;
}
);
var ValidationOutputHolder = (function(){
var output ={
}
;
var addOutput = function(outputName,value){
var outputParts = outputName.split(".");
var currentPart = output;
for (var i=0;
i<outputParts.length;
i++){
if (!currentPart.hasOwnProperty(outputParts[i])){
currentPart[outputParts[i]] ={
}
;
}
// Either place the value into the output,or continue going down the // search space. if (i === outputParts.length-1){
currentPart[outputParts[i]] = value}
else{
currentPart = currentPart[outputParts[i]];
}
}
}
;
var getOutput = function(){
return output;
}
;
return{
addOutput:addOutput,getOutput:getOutput}
}
);
var processSelector = function(selector,selectorValidatorMap,errorHolder,outputHolder){
if (selectorValidatorMap.hasOwnProperty(selector)){
var currentMapping = selectorValidatorMap[selector];
var validatorType = currentMapping["type"];
var fieldName = currentMapping["name"];
var validatorResults = Validators[validatorType](selector,currentMapping["data"]);
if (validatorResults["is_valid"]){
if (currentMapping["output_name"] instanceof Array){
for (var i=0;
i<currentMapping["output_name"].length;
i++){
outputHolder.addOutput(currentMapping["output_name"][i],validatorResults["output_value"][i]);
}
}
else{
outputHolder.addOutput(currentMapping["output_name"],validatorResults["output_value"]);
}
}
else{
errorHolder.addError(selector,validatorResults);
return true;
}
}
}
;
var validate = function(selectorValidatorMap){
var errorHolder = ValidationErrorHolder();
var outputHolder = ValidationOutputHolder();
var anyErrors = false;
for (var selector in selectorValidatorMap){
if (processSelector(selector,selectorValidatorMap,errorHolder,outputHolder)){
anyErrors = true;
}
}
if (anyErrors){
errorHolder.triggerErrorMessage();
return false;
}
else{
return outputHolder.getOutput();
}
}
;
return{
validate:validate}
;
}
)();
var ExpirationInput = (function(){
var maximumLength = 4;
var selector;
var createExpirationInput = function(mainSelector){
selector = mainSelector $(selector).keypress(function(e){
$(selector).removeClass("has-error");
if (shouldProcessInput(e,maximumLength,selector)){
var inputValue = getInputValue(e,selector);
if (inputValue.length >= 2){
var newInput = inputValue.slice(0,2) + " / " + inputValue.slice(2);
$(selector).val(newInput);
}
else{
$(selector).val(inputValue);
}
}
}
);
}
;
var parseExpirationInput = function(expirationSelector){
var inputValue = getNumber($(expirationSelector).val());
var month = inputValue.slice(0,2);
var year = "20" + inputValue.slice(2);
return{
'year':year,'month':month}
;
}
;
return{
createExpirationInput:createExpirationInput,parseExpirationInput:parseExpirationInput}
;
}
)();
var CardTypeListener = (function(){
var determineCardType = function(value){
if (/^(34|37)/.test(value)){
return "American Express";
}
else if (/^4/.test(value)){
return "Visa";
}
else if (/^5[0-5]/.test(value)){
return "MasterCard";
}
else if (/^(6011|622|64[4-9]|65)/.test(value)){
return "Discover";
}
else{
return "";
}
}
;
var changeCardType = function(numberSelector,cardTypeSelector){
$(numberSelector).on("changed_input keypress keydown keyup",function(e){
var data = $(numberSelector).val();
var cardType = determineCardType(getNumber(data));
$(cardTypeSelector).text(cardType);
}
);
}
;
return{
changeCardType:changeCardType}
;
}
)();
var initialize = function(expirationSelector,creditCardNumberSelector,cvvSelector,cardTypeSelector,options){
createSelectorValidatorMap(expirationSelector,creditCardNumberSelector,cvvSelector,options);
ExpirationInput.createExpirationInput(expirationSelector);
NumberInput.createNumberInput(creditCardNumberSelector);
CvvInput.createCvvInput(cvvSelector,creditCardNumberSelector);
CardTypeListener.changeCardType(creditCardNumberSelector,cardTypeSelector);
return this;
}
;
var selectorValidatorMap;
var createSelectorValidatorMap = function(expirationSelector,creditCardNumberSelector,cvvSelector,options){
var optionValues = options ||{
}
;
optionValues["security_code_message"] = optionValues["security_code_message"] || "Your security code is invalid";
optionValues["number_message"] = optionValues["number_message"] || "Your credit card number is invalid";
optionValues["expiration_message"] = optionValues["expiration_message"] || "Your credit card expiration is invalid";
selectorValidatorMap ={
}
;
selectorValidatorMap[creditCardNumberSelector] ={
"type":"creditCard","data":{
"cvvSelector":cvvSelector,"creditCardNumberSelector":creditCardNumberSelector,"message":{
"security_code":optionValues["security_code_message"],"number":optionValues["number_message"]}
}
,"output_name":["number","security_code"]}
;
selectorValidatorMap[expirationSelector] ={
"type":"creditCardExpiration","data":{
"message":optionValues["expiration_message"]}
,"output_name":["expiration_month","expiration_year"]}
;
}
;
var validate = function(){
return Validation.validate(selectorValidatorMap);
}
;
return{
initialize:initialize,validate:validate,}
;
}
)();
CSS代码(creditly.css):
.creditly-wrapper{background-color:rgba(66,139,202,0.8);border-color:#357ebd;border-radius:4px;-webkit-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out;width:350px;min-height:216px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:white;background-image:-webkit-linear-gradient(#7dc5ee,#008cdd 85%,#30a2e4);background-image:-moz-linear-gradient(#7dc5ee,#008cdd 85%,#30a2e4);background-image:-ms-linear-gradient(#7dc5ee,#008cdd 85%,#30a2e4);background-image:-o-linear-gradient(#7dc5ee,#008cdd 85%,#30a2e4);background-image:-webkit-linear-gradient(#7dc5ee,#008cdd 85%,#30a2e4);background-image:-moz-linear-gradient(#7dc5ee,#008cdd 85%,#30a2e4);background-image:-ms-linear-gradient(#7dc5ee,#008cdd 85%,#30a2e4);background-image:-o-linear-gradient(#7dc5ee,#008cdd 85%,#30a2e4);background-image:linear-gradient(#7dc5ee,#008cdd 85%,#30a2e4);}
.creditly-wrapper .credit-card-wrapper{padding:40px 30px;}
.creditly-wrapper .credit-card-wrapper .controls{padding-left:7px;padding-right:7px;}
.creditly-wrapper input.has-error{outline:none;border-color:#ff7076;border-top-color:#ff5c61;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.2),0 1px 0 rgba(255,255,255,0),0 0 4px 0 rgba(255,0,0,0.5);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.2),0 1px 0 rgba(255,255,255,0),0 0 4px 0 rgba(255,0,0,0.5);-ms-box-shadow:inset 0 1px 2px rgba(0,0,0,0.2),0 1px 0 rgba(255,255,255,0),0 0 4px 0 rgba(255,0,0,0.5);-o-box-shadow:inset 0 1px 2px rgba(0,0,0,0.2),0 1px 0 rgba(255,255,255,0),0 0 4px 0 rgba(255,0,0,0.5);box-shadow:inset 0 1px 2px rgba(0,0,0,0.2),0 1px 0 rgba(255,255,255,0),0 0 4px 0 rgba(255,0,0,0.5);}
/* * Bootstrap stuff */
.creditly-wrapper .form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;}
.creditly-wrapper .form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);}
.creditly-wrapper label{display:inline-block;margin-bottom:5px;font-weight:bold;}
.creditly-wrapper input:focus::-webkit-input-placeholder{color:#ccc;}
.creditly-wrapper input:focus:-moz-placeholder{color:#ccc;}
.creditly-wrapper input:focus::-moz-placeholder{color:#ccc;}
.creditly-wrapper input:focus:-ms-input-placeholder{color:#ccc;}
.creditly-wrapper .col-sm-8{width:66.6666666666666%;}
.creditly-wrapper .col-sm-4{width:33.3333333333333%;}
.creditly-wrapper .col-sm-8,.creditly-wrapper .col-sm-4{float:left;position:relative;display:block;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}
.creditly-wrapper .form-group{width:100%;display:table;}
.creditly-wrapper .first-row{margin-bottom:20px;}
.creditly-wrapper .card-type{margin-top:10px;float:right;}
/** * Button CSS */
.creditly-card-form .submit{overflow:hidden;display:inline-block;visibility:visible!important;background-image:-webkit-linear-gradient(#28a0e5,#015e94);background-image:-moz-linear-gradient(#28a0e5,#015e94);background-image:-ms-linear-gradient(#28a0e5,#015e94);background-image:-o-linear-gradient(#28a0e5,#015e94);background-image:-webkit-linear-gradient(#28a0e5,#015e94);background-image:-moz-linear-gradient(#28a0e5,#015e94);background-image:-ms-linear-gradient(#28a0e5,#015e94);background-image:-o-linear-gradient(#28a0e5,#015e94);background-image:linear-gradient(#28a0e5,#015e94);-webkit-font-smoothing:antialiased;border:0;padding:1px;text-decoration:none;-webkit-border-radius:5px;-moz-border-radius:5px;-ms-border-radius:5px;-o-border-radius:5px;border-radius:5px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.2);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.2);-ms-box-shadow:0 1px 0 rgba(0,0,0,0.2);-o-box-shadow:0 1px 0 rgba(0,0,0,0.2);box-shadow:0 1px 0 rgba(0,0,0,0.2);-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;cursor:pointer;}
.creditly-card-form .submit span{display:block;position:relative;padding:0 12px;height:30px;line-height:30px;background:#1275ff;background-image:-webkit-linear-gradient(#7dc5ee,#008cdd 85%,#30a2e4);background-image:-moz-linear-gradient(#7dc5ee,#008cdd 85%,#30a2e4);background-image:-ms-linear-gradient(#7dc5ee,#008cdd 85%,#30a2e4);background-image:-o-linear-gradient(#7dc5ee,#008cdd 85%,#30a2e4);background-image:-webkit-linear-gradient(#7dc5ee,#008cdd 85%,#30a2e4);background-image:-moz-linear-gradient(#7dc5ee,#008cdd 85%,#30a2e4);background-image:-ms-linear-gradient(#7dc5ee,#008cdd 85%,#30a2e4);background-image:-o-linear-gradient(#7dc5ee,#008cdd 85%,#30a2e4);background-image:linear-gradient(#7dc5ee,#008cdd 85%,#30a2e4);font-size:14px;color:#fff;font-weight:bold;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;text-shadow:0 -1px 0 rgba(0,0,0,0.25);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25);-ms-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25);-o-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25);box-shadow:inset 0 1px 0 rgba(255,255,255,0.25);-webkit-border-radius:4px;-moz-border-radius:4px;-ms-border-radius:4px;-o-border-radius:4px;border-radius:4px;}
CSS代码(teaser.css):
body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;}
h1,h2{color:#357ebd;}
.banner .row{width:350px;margin-left:auto;margin-right:auto;}
.banner .creditly-card-form{margin-top:60px;}
.banner .row .submit{margin-top:20px;float:right;}
.banner .footer{bottom:0;position:absolute;margin:20px;}