생년월일은 과거 달력에서 선택하는 방식을 많이 채택하였지만 나이가 있으신분들은 한참을 뒤로 가야하는 불편함이 발생되어 요즘은 입력방식을 사용하는편이다. 이번편에서는 간단하게나마 생년월일 입력 후 슬래시(/) 또는 하이픈(-)을 붙여주는 스크립트이다.
본래 이번편에 소개하는 예제는 JS 라이브러리로 제공할 목적이였으나 시간상 여유가 없어 간단하게 입력 후 처리 방식에대해 알아보도록 하자.
<style>
input[type="text"]{ width:100%; max-width:450px; padding:6px 2px; border:solid 1px cornflowerblue; outline: none;; }
</style>
<h3>생년월일 ex1) 48/11/19 </h3>
<input type="text" class="birthday" value="" data-seq="/" data-format="YYMMDD" data-backspace="false">
<br><br>
<h3>생년월일 ex2) 1948/11/19 </h3>
<input type="text" class="birthday" value="" data-seq="/" data-format="YYYYMMDD">
<script>
// 유효성 체크
function valid(e){
let input = e.target.value.replace(/\D/g, '');
let dataset = e.target.dataset;
let formatLen = dataset.format.length;
if( input.length <= 0 ){ return input; }
if( dataset.format == 'YYYYMMDD'){
let lastYear = new Date().getFullYear();
let inputLength = input.length;
for (let i = 1; i <= inputLength; i++) {
if( i == 1){
if (input[0] > lastYear.toString()[0]) {
input = input.substring(0, 0);
break;
}
}
else if(i == 2){
if (input[0] >= lastYear.toString()[0] && input[1] > lastYear.toString()[1]) {
input = input.substring(0, 1);
break;
}
}
else if(i == 3){
if (input[0] >= lastYear.toString()[0] && input[1] >= lastYear.toString()[1] && input[2] > lastYear.toString()[2]) {
input = input.substring(0, 2);
break;
}
}
else if(i == 4){
if (lastYear > input * 1) {
input = input.substring(0, 4);
break;
}
}
else if(i == 5){
if (input[4] > 1) {
input = input.substring(0, 4);
break;
}
}
else if(i == 6){
var month = input[4] + '' + input[5];
if (month > 12 || month <= 0) {
input = input.substring(0, 5);
break;
}
}
else{
if (i < 7){ continue; }
var year = input[2] + '' + input[3];
var month = input[4] + '' + input[5];
var lastDay = new Date(year, month, 0).getDate();
if (inputLength === 7) {
lastDay = lastDay.toString();
if (lastDay[0] < input[6]) {
input = input.substring(0, 6);
break;
}
} else {
var day = input[6] + '' + input[7];
if (lastDay < Number(day)) {
input = input.substring(0, 7);
break;
}
else if(input[6] == '0' && input[7] == '0'){ input = input.substring(0, 7); }
}
}
}
}
else{
for(let i = 3; i <= input.length; i++){
if( i == 3){
if( input[2]*1 > 1){
input = input.substring(0, 2);
}
}
else if(i == 4){
let month = input[2]+''+input[3];
if( month*1 > 12 || month*1 <= 0){
input = input.substring(0, 3);
}
}
else if(i >= 5){
let year = input[0]+''+input[1];
let month = input[2]+''+input[3];
let lastDay = new Date(year, month, 0).getDate();
if( i == 5){
lastDay = String(lastDay);
if( lastDay[0] < input[4]){
input = input.substring(0, 4);
}
}
else{
var day = input[4]+''+input[5];
if( lastDay < Number(day)){
input = input.substring(0, 5);
}
else if(input[4] == '0' && input[5] == '0'){ input = input.substring(0, 5); }
}
}
}
}
input = input.substring(0,formatLen);
return input;
}
window.onload = function(){
let eventEles = document.querySelectorAll('.birthday');
eventEles.forEach(function(v,i){
if( typeof v.dataset.seq == 'undefined' || v.dataset.seq.length > 1){ v.dataset.seq = '/'; }
if( typeof v.dataset.backspace == 'undefined' || v.dataset.backspace == '' || v.dataset.backspace != 'false'){ v.dataset.backspace = 'true'; }
if( typeof v.dataset.format == 'undefined' || ['YYYYMMDD','YYMMDD'].indexOf(v.dataset.format) === -1 ){ v.dataset.format = 'YYMMDD'; }
if( v.dataset.format == 'YYYYMMDD'){ v.setAttribute('maxlength',10); }
else{ v.setAttribute('maxlength',8); }
v.addEventListener('input',function(e){
let dataset = e.target.dataset;
let formatLen = dataset.format.length;
let input = valid(e);
if( input.length < formatLen){
if(typeof dataset.value != 'undefined' ){
input = dataset.value;
if( dataset.backspace == 'true'){ input = input.substring(0,input.length-1); }
}
e.target.removeAttribute('data-value');
e.target.value = input;
return false;
}
e.target.setAttribute('data-value',input);
if( dataset.format == 'YYYYMMDD'){
input = input.replace(/(\d{4})(\d{2})(\d{2})/, '$1'+v.dataset.seq+'$2'+v.dataset.seq+'$3');
}else{
input = input.replace(/(\d{2})(\d{2})(\d{2})/, '$1'+v.dataset.seq+'$2'+v.dataset.seq+'$3');
}
e.target.value = input;
});
v.addEventListener('blur',function(e){
let dataset = e.target.dataset;
let formatLen = dataset.format.length;
let formatSeqLen = dataset.format.length+2;
let input = e.target.value;
input = valid(e);
if( input.length != formatLen){ return false; }
e.target.setAttribute('data-value',input);
if( dataset.format == 'YYYYMMDD'){
input = input.replace(/(\d{4})(\d{2})(\d{2})/, '$1'+v.dataset.seq+'$2'+v.dataset.seq+'$3');
}else{
input = input.replace(/(\d{2})(\d{2})(\d{2})/, '$1'+v.dataset.seq+'$2'+v.dataset.seq+'$3');
}
e.target.value = input;
});
});
};
</script>
JAVASCRIPT 소스 부분을 보면 알겠지만 배보다 배꼽이 더 크다고 유효성 체크가 상당히 많이 들어간다. 유효성 체크는 실제 날짜를 계산하여 잘못된 날짜는 입력자체가 안되도록 처리하였다.
생년월일의 모든 입력이 완료되면 자동으로 구분자를 붙여주게 되어있다. 지원되는 날짜 포맷형식은 YYMMDD 와 YYYYMMDD이며 포맷형식에 따라 자릿수가 다르기에 유효성 체크도 각각 해주다.
추가적으로 구분자의 경우 입력문자는 제한이 없으나 길이에 제한이 있으며 1글자 이상일 경우 자동으로 슬래시(/) 설정이 되도록 하였다. 이를 제어할 수 있는 data 속성의 옵션은 아래를 참고하도록 하자.
속성 | data-seq
<input type="text" class="birthday" value="" data-seq="/">
속성 | data-backspace
<input type="text" class="birthday" value="" data-backspace="false" >
추가로 이벤트를 보면 blur가 추가되었는데 이는 backspace 옵션이 false 일경우 삭제하고 나면 숫자형태로 그대로 남기 때문에 영역을 벗어나면 다시 구분자를 붙여주기 위해 추가하였다.