0

How do I get the input to automatically parse the numbers to follow the format [MM / YY] like it is done in this codepen example?

Right now in order for the validation to work, you need to manually enter 5 digits, including a '/' separator entered manually by the user:

$("#ExpDate").on("input", function() {
  var expdate = $(this).val();
  if (expdate.length == 5) {
    checkExpDate($(this));
  } else {
    notCorrectInput($(this));
    removeError($(this));
  }
  if (expdate.indexOf("\\") > -1) {
    $(this).val(expdate.replace("\\", "/"));
    expdate = expdate.replace("\\", "/");
  }
  if (expdate.length == 2 && expdate.indexOf("/") > -1) {
    $(this).val("0" + expdate);
  }
});

function checkExpDate($ele) {
  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 exdate = $ele.val();
  var dateregex = /^(0[1-9]|1[0-2])\/?([0-9]{2})$/;
  if (exdate.length != 0) {
    if (!dateregex.exec(exdate)) {
      activateError($ele);
      $ele.next().text("Date is not valid.");
    } else {
      var today = new Date(),
        someday = new Date();
      someday.setFullYear("20" + exdate.substr(3, 4), exdate.substr(0, 2), 1);
      if (someday < today) {
        activateError($ele);
        $ele.next().text("Card is expired.");
      } else {
        correctInput($ele);
        removeError($ele);
      }
    }
  } else {
    correctInput($ele);
    removeError($ele);
  }
}
$("#ExpDate").on("input", function() {
  var expdate = $(this).val();
  if (expdate.length == 5) {
    checkExpDate($(this));
  } else {
    notCorrectInput($(this));
    removeError($(this));
  }
  if (expdate.indexOf("\\") > -1) {
    $(this).val(expdate.replace("\\", "/"));
    expdate = expdate.replace("\\", "/");
  }
  if (expdate.length == 2 && expdate.indexOf("/") > -1) {
    $(this).val("0" + expdate);
  }
});
$("#ExpDate").keydown(function(e) {
  var exdate = $(this).val();
  if (exdate.length == 5 && keyIsNum(e)) {
    e.preventDefault();
    return false;
  }
});
$("#ExpDate").keydown(function(e) {
  if (
    (e.keyCode > 64 && e.keyCode < 91) ||
    (e.keyCode > 185 && e.keyCode < 191)
  ) {
    e.preventDefault();
    return false;
  }
});

function correctInput($ele) {
  $ele.addClass("input-correct");
}

function notCorrectInput($ele) {
  $ele.removeClass("input-correct");
}

function removeError($ele) {
  $ele.next().removeClass("active");
  $ele.removeClass("input-error");
}

function activateError($ele) {
  $ele.addClass("input-error");
  $ele.removeClass("input-correct");
  $ele.next().addClass("active");
}

function keyIsNum(event) {
  console.log(event);
  if (
    (event.keyCode >= 48 && event.keyCode <= 57) ||
    (event.keyCode >= 96 && event.keyCode <= 105)
  ) {
    return true;
  } else {
    return false;
  }
}

function checkIfEmpty($ele) {
  if ($ele.val().length == 0) {
    $ele.addClass("input-error");
    return false;
  } else {
    return true;
  }
}
.input-error:focus {
  outline: none;
}

.input-error {
  border-color: #DB4F4F !important;
  background-color: #FEF8F8 !important;
}

.input-correct {
  border-color: #75CC72 !important;
  background-color: #F9FEF8 !important;
}

.help-info {
  display: none;
}

.help-info.active {
  display: block;
}

span {
  display: block;
  font-size: 13px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="box">
    <input type="text" id="ExpDate" placeholder="MM / YY" />
    <span class="help-info"></span></div>
</div>

6
  • Here is code pen codepen.io/aravi-pen/pen/RBxbXP check and let me know Commented Jul 30, 2018 at 4:51
  • The formatting is working in your pen, but the validation is not functioning like it does in the snippet. Commented Jul 30, 2018 at 4:54
  • Check now codepen.io/aravi-pen/pen/RBxbXP Commented Jul 30, 2018 at 5:19
  • I need the snippet in the question to be changed. The codepen is just the example of how I want the input to function. The goal is to get the input in the snippet above to work the same way as the input in the codepen. Commented Jul 30, 2018 at 5:24
  • The codepen code(which you shared) is best for the validation. the js you have can modify based on my codepen Commented Jul 30, 2018 at 5:30

1 Answer 1

1

Here is code updated to handle the format you mentioned and the validation. here is the codepen link https://codepen.io/aravi-pen/pen/RBxbXP

$(document).ready(function() {
  $(function() {
    var creditly = Creditly.initialize(
      "#ExpDate",
    );
    $(".payment__confirm").click(function(e) {
      e.preventDefault();
      var output = creditly.validate();
	  $ele = $("#ExpDate");
	  var today = new Date();
      if (output) {
        // Your validated credit card output
        console.log(output);
		if(output.expiration_year > today.getFullYear()){
			$ele.next().show().text("Card is expired.");
		}
		else{
			$ele.next().hide();
		}
      }
    });
  });
});
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) {
    return ( $.inArray(e.which,[46,8,9,0,27,13,190]) !== -1 ||
      (e.which == 65 && e.ctrlKey === true) || 
      (e.which == 67 && e.ctrlKey === true) || 
      (e.which == 86 && e.ctrlKey === true) || 
      (e.which >= 35 && e.which <= 39));
  };

  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 (reachedMaximumLength(e, maximumLength, selector) || e.shiftKey || (!isNumberEvent(e))) {
      return false;
    }
    return true;
  };


  var shouldProcessInput = function(e, maximumLength, selector) {
    return (!isEscapedKeyStroke(e)) && onlyAllowNumeric(e, maximumLength, selector);
  };

  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
        };
      };


      return {
        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");
        }
		$("#ExpDate").next().show().text("Date is not valid.");
        $("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 initialize = function(expirationSelector) {
    createSelectorValidatorMap(expirationSelector);
    ExpirationInput.createExpirationInput(expirationSelector);
    return this;
  };

  var selectorValidatorMap;

  var createSelectorValidatorMap = function(expirationSelector) {
    var optionValues = {};
    optionValues["expiration_message"] = optionValues["expiration_message"] || "Your credit card expiration is invalid";

    selectorValidatorMap = {};
    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,
  };
})();
.input-error:focus {
  outline: none;
}

.input-error {
  border-color: #DB4F4F !important;
  background-color: #FEF8F8 !important;
}

.input-correct {
  border-color: #75CC72 !important;
  background-color: #F9FEF8 !important;
}

.help-info {
  display: none;
}

.help-info.active {
  display: block;
}

span {
  display: block;
  font-size: 13px;
}

input.has-error {
  outline: none;
  border-color: #ff7076;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="box">
    <input type="text" id="ExpDate" placeholder="MM / YY" />
    <span class="help-info"></span></div>
</div>
  <button class="payment__confirm"><span>Submit</span></button>

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks Aravind. If I un-comment selectorValidatorMap[creditCardNumberSelector], you can see the code works for the other inputs, but your code no longer works. How do I get them both to work when the variable is un-commented? Here is the updated pen: codepen.io/moofawsaw/pen/vapREY
@KyleUnderhill now it's midnight for me.i will check tmrw..in btw I done everything for date validation only. If my answer helped upvote and accept.thanks!
I have marked your answer complete. Hoping you can help me figure out the issue in my last comment! Thanks again
@KyleUnderhill hey can you explain your issue in detail on a chat room
I have migrated to chat. More details there!
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.