Reputation: 61
Auto slash(/) with leading and trailing space in a date value is working fine.
var date = document.getElementById('date');
function checkValue(str, max) {
if (str.charAt(0) !== '0' || str == '00') {
var num = parseInt(str);
if (isNaN(num) || num <= 0 || num > max) num = 1;
str = num > parseInt(max.toString().charAt(0))
&& num.toString().length == 1 ? '0' + num : num.toString();
};
return str;
};
date.addEventListener('input', function(e) {
this.type = 'text';
var input = this.value;
if (/\D\/$/.test(input)) input = input.substr(0, input.length - 3);
var values = input.split('/').map(function(v) {
return v.replace(/\D/g, '')
});
if (values[0]) values[0] = checkValue(values[0], 12);
if (values[1]) values[1] = checkValue(values[1], 31);
var output = values.map(function(v, i) {
return v.length == 2 && i < 2 ? v + ' / ' : v;
});
this.value = output.join('').substr(0, 14);
});
<input type="text" id="date" />
But when I tried to remove the space before and after slash(/). But when I deleting each character using backspace key, slash is not deleting.
Below is what I tried.
var date = document.getElementById('date');
function checkValue(str, max) {
if (str.charAt(0) !== '0' || str == '00') {
var num = parseInt(str);
if (isNaN(num) || num <= 0 || num > max) num = 1;
str = num > parseInt(max.toString().charAt(0))
&& num.toString().length == 1 ? '0' + num : num.toString();
};
return str;
};
date.addEventListener('input', function(e) {
this.type = 'text';
var input = this.value;
if (/\D\/$/.test(input)) input = input.substr(0, input.length - 1);
var values = input.split('/').map(function(v) {
return v.replace(/\D/g, '')
});
if (values[0]) values[0] = checkValue(values[0], 12);
if (values[1]) values[1] = checkValue(values[1], 31);
var output = values.map(function(v, i) {
return v.length == 2 && i < 2 ? v + '/' : v;
});
this.value = output.join('').substr(0, 10);
});
<input type="text" id="date" />
Please suggest me to rectify this.
Upvotes: 2
Views: 16875
Reputation: 11
This is my regex solution for React:
// add auto "/" for date, i.e. MM/YY
handleExpInput(e) {
// ignore invalid input
if (!/^\d{0,2}\/?\d{0,2}$/.test(e.target.value)) {
return;
}
let input = e.target.value;
if (/^\d{3,}$/.test(input)) {
input = input.match(new RegExp('.{1,2}', 'g')).join('/');
}
this.setState({
expDateShow: input,
});
}
Upvotes: 0
Reputation: 769
I also had this come up as a requirement for an application that I am building and I implemented my solution like this.
$(document).ready(function () {
Date.prototype.toShortDateString = function() {
return (this.getMonth() + 1) + "/" + this.getDate() + "/" + this.getFullYear();
}
//#region CUSTOM FUNCTIONS FOR DATEPICKERS
function isTextSelected(input) {
if (typeof input.selectionStart == "number" && input.selectionStart != input.value.length && input.selectionStart != input.selectionEnd) {
return true;
} else if (typeof document.selection != "undefined") {
input.focus();
return document.selection.createRange().text == input.value;
}
return false;
}
function isNumber(e) {
var allowedKeys = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105];
if ($.inArray(e.keyCode, allowedKeys) != -1 && !e.originalEvent.shiftKey) {
return true;
}
return false;
}
function isBackspace(keyCode) {
var allowedKeys = [8];
if ($.inArray(keyCode, allowedKeys) != -1) {
return true;
}
return false;
}
function isAllowedKey(keyCode) {
var allowedKeys = [9, 13, 16, 37, 38, 39, 40];//191,111];
if ($.inArray(keyCode, allowedKeys) != -1) {
return true;
}
return false;
}
//#endregion
$.fn.extend({
allowMMDDYYYY: function (validate) {
$(this).keydown(function (e) {
var that = this;
if (!isNumber(e) && !isBackspace(e.keyCode) && !isAllowedKey(e.keyCode)) {
e.preventDefault();
} else if ($(that).val().length == 10 && !isBackspace(e.keyCode) && !isAllowedKey(e.keyCode)) {// && !isTextSelected(e.target) && isNumber(e.keyCode)) {
if(!isTextSelected(e.target) && isNumber(e))
e.preventDefault();
}
});
$(this).keyup(function (e) {
var that = this;
var value = $(that).val();
if (e.keyCode != 8 && !isAllowedKey(e.keyCode)) {
switch (value.length) {
case 2:
$(that).val(value + "/");
break;
case 3:
if (value.indexOf("/") == -1) {
$(that).val(value.substr(0, 2) + "/" + value.substr(2, 1));
}
break;
case 4:
if (value.substr(0,3).indexOf("/") == -1) {
$(that).val(value.substr(0, 2) + "/" + value.substr(2, 2));
}
break;
case 5:
if (e.target.selectionStart == value.length) {
if (e.target.selectionStart != 1) {
$(that).val(value + "/");
}
}
break;
case 6:
if (e.target.selectionStart == value.length) {
if (value.substr(5).indexOf("/") == -1) {
$(that).val(value.substr(0, 5) + "/" + value.substr(5, 1));
}
} else if (e.target.selectionStart == 2) {
$(that).val(value.substr(0, 2) + "/" + value.substr(2))
e.target.selectionStart = 3;
e.target.selectionEnd = 3;
}
break;
case 7:
if (e.target.selectionStart == value.length) {
if (value.substr(5).indexOf("/") == -1) {
$(that).val(value.substr(0, 6) + "/" + value.substr(5, 2));
}
} else if (e.target.selectionStart == 2) {
$(that).val(value.substr(0, 2) + "/" + value.substr(2));
e.target.selectionStart = 3;
e.target.selectionEnd = 3;
}
break;
case 9:
if (value.substr(3, 5).indexOf("/") == -1) {
$(that).val(value.substr(0,5) + "/" + value.substr(5))
} else if (value.substr(0, 3).indexOf("/") == -1) {
$(that).val(value.substr(0, 2) + "/" + value.substr(2))
}
break;
//IF THE LENGTH IS 10 (ONKEYUP) THEN CALL VALIDATION ON OTHER DATEPICKER ELEMENTS.
case 10:
if (!isTextSelected(e.target)) {
validate();
}
break;
}
}
});
}
});
//#endregion
$("input[data-role='datepicker']").each(function (i, o) {
var jqueryElement = $(o);
jqueryElement.allowMMDDYYYY(function () {
//THIS IS MY CALLBACK FUNCTION TO ALLOW VALIDATION ON OTHER ELEMENTS
console.log("validating");
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" data-role="datepicker"/>
My requirements we to be able to enter MMddyyyy format without slashes and it would auto populate the slashes as they typed. Solution does not allow any characters but numbers,backspace, arrow keys, ctrl, and shift key. This extension also has a callback function so that you can validate other elements after a date has been entered (since i was using jquery validator).
Upvotes: 1
Reputation: 1581
Here's a alternate answer even though Albzi's answer works perfectly fine. You can use the keydown
event and check if backspace or delete is being pressed and return false
in your event. I also added a maxlength
of 10 to your input
element so it does not exceed 10 characters.
var date = document.getElementById('date');
function checkValue(str, max) {
if (str.charAt(0) !== '0' || str == '00') {
var num = parseInt(str);
if (isNaN(num) || num <= 0 || num > max) num = 1;
str = num > parseInt(max.toString().charAt(0)) && num.toString().length == 1 ? '0' + num : num.toString();
};
return str;
};
date.addEventListener('keydown', function(e) {
this.type = 'text';
var input = this.value;
var key = e.keyCode || e.charCode;
if (key == 8 || key == 46) // here's where it checks if backspace or delete is being pressed
return false;
if (/\D\/$/.test(input)) input = input.substr(0, input.length - 1);
var values = input.split('/').map(function(v) {
return v.replace(/\D/g, '')
});
if (values[0]) values[0] = checkValue(values[0], 12);
if (values[1]) values[1] = checkValue(values[1], 31);
var output = values.map(function(v, i) {
return v.length == 2 && i < 2 ? v + '/' : v;
});
this.value = output.join('').substr(0, 10);
});
<input type="text" id="date" maxlength="10" />
Upvotes: 2
Reputation: 15609
var date = document.getElementById('date');
function checkValue(str, max) {
if (str.charAt(0) !== '0' || str == '00') {
var num = parseInt(str);
if (isNaN(num) || num <= 0 || num > max) num = 1;
str = num > parseInt(max.toString().charAt(0))
&& num.toString().length == 1 ? '0' + num : num.toString();
};
return str;
};
date.addEventListener('input', function(e) {
this.type = 'text';
var input = this.value;
if (/\D\/$/.test(input)) input = input.substr(0, input.length - 3);
var values = input.split('/').map(function(v) {
return v.replace(/\D/g, '')
});
if (values[0]) values[0] = checkValue(values[0], 12);
if (values[1]) values[1] = checkValue(values[1], 31);
var output = values.map(function(v, i) {
return v.length == 2 && i < 2 ? v + ' / ' : v;
});
this.value = output.join('').substr(0, 14);
});
input {
word-spacing:-3px;
}
<input type="text" id="date" />
You can 'cheat' and use some CSS:
word-spacing:-3px;
This moves the /
closer to the text.
The reason it doesn't work when you remove the spaces from the JavaScript is because your code is looking for a string length of 2
, but the string length goes to 3
when you add the /
with no spaces.
Upvotes: 14