So with this code I'm trying (not done by me but it's a bit different) to do a date of birth select with 3 selects, 1 for day, 1 for month and 1 for year, but whenever the user chooses for ex 30 for day and then chooses February it displays an error using setCustomValidity and reportValidity but it does not work when I choose 29 day then February then choose a non leap year like 2022, its does not show the error.
var Days = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; // index => month [0-11]
$(document).ready(function() {
var option = '<option id="dayOption" selected disabled value="day">Day</option>';
var selectedDay = "day";
for (var i = 1; i <= Days[0]; i ) { //add option days
option = '<option value="' i '">' i '</option>';
}
$('#day').append(option);
$('#day').val(selectedDay);
var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
var option = '<option selected disabled value="month">Month</option>';
var selectedMon = "month";
for (var i = 1; i <= 12; i ) {
option = '<option value="' i '">' months[i - 1] '</option>';
}
$('#month').append(option);
$('#month').val(selectedMon);
var d = new Date();
var option = '<option selected disabled value="year">Year</option>';
selectedYear = "year";
for (var i = d.getFullYear(); i >= 1910; i--) { // years start i
option = '<option value="' i '">' i '</option>';
}
$('#year').append(option);
$('#year').val(selectedYear);
});
function isLeapYear(year) {
if (year == "year") {
return true;
} else {
year = parseInt(year);
if (year % 4 != 0) {
return false;
} else if (year % 400 == 0) {
return true;
} else if (year % 100 == 0) {
return false;
} else {
return true;
}
}
}
function change_month(select) {
var day = $('#day');
var val = $(day).val();
$(day).empty();
var option = '<option id="dayOption" selected disabled value="day">Day</option>';
var month = parseInt($(select).val()) - 1;
for (var i = 1; i <= Days[month]; i ) { //add option days
if (val == i) {
option = '<option selected value="' i '">' i '</option>';
} else {
option = '<option value="' i '">' i '</option>';
}
}
$(day).append(option);
if (val > Days[month]) {
dayOption = $('#dayOption');
dayOption.removeAttr("disabled", false);
dayOption.removeAttr("selected", false);
dayOption.attr("selected", true);
dayOption.attr("disabled", true);
day.get(0).setCustomValidity("Wrong day");
day.get(0).reportValidity();
} else {
day.get(0).setCustomValidity("");
}
}
function change_year(select) {
if (isLeapYear($(select).val())) {
Days[1] = 29;
} else {
Days[1] = 28;
}
month = $("#month").val();
if (month == 2) {
var day2 = $('#day');
var val = $(day).val();
$(day2).empty();
var option = '<option id="dayOption" selected disabled value="day">Day</option>';
for (var i = 1; i <= Days[1]; i ) { //add option days
if (val == i) {
option = '<option selected value="' i '">' i '</option>';
} else {
option = '<option value="' i '">' i '</option>';
}
}
$(day2).append(option);
if (month > Days[1]) {
day2.get(0).setCustomValidity("Wrong day");
day2.get(0).reportValidity();
dayOption = $('#dayOption');
dayOption.removeAttr("disabled", false);
dayOption.removeAttr("selected", false);
dayOption.attr("selected", true);
dayOption.attr("disabled", true);
} else {
day2.get(0).setCustomValidity("");
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<form >
<SELECT id="day" name="dd"></SELECT>
<SELECT id="month" name="mm" onchange="change_month(this)"></SELECT>
<SELECT id="year" name="yyyy" onchange="change_year(this)"></SELECT>
</form>
CodePudding user response:
var Days = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; // index => month [0-11]
$(document).ready(function() {
var option = '<option id="dayOption" selected disabled value="day">Day</option>';
var selectedDay = "day";
for (var i = 1; i <= Days[0]; i ) { //add option days
option = '<option value="' i '">' i '</option>';
}
$('#day').append(option);
$('#day').val(selectedDay);
var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
var option = '<option selected disabled value="month">Month</option>';
var selectedMon = "month";
for (var i = 1; i <= 12; i ) {
option = '<option value="' i '">' months[i - 1] '</option>';
}
$('#month').append(option);
$('#month').val(selectedMon);
var d = new Date();
var option = '<option selected disabled value="year">Year</option>';
selectedYear = "year";
for (var i = d.getFullYear(); i >= 1910; i--) { // years start i
option = '<option value="' i '">' i '</option>';
}
$('#year').append(option);
$('#year').val(selectedYear);
});
function isLeapYear(year) {
if (year == "year") {
return true;
} else {
year = parseInt(year);
if (year % 4 != 0) {
return false;
} else if (year % 400 == 0) {
return true;
} else if (year % 100 == 0) {
return false;
} else {
return true;
}
}
}
function change_month(select) {
var day = $('#day');
var val = $(day).val();
$(day).empty();
var option = '<option id="dayOption" selected disabled value="day">Day</option>';
var month = parseInt($(select).val()) - 1;
for (var i = 1; i <= Days[month]; i ) { //add option days
if (val == i) {
option = '<option selected value="' i '">' i '</option>';
} else {
option = '<option value="' i '">' i '</option>';
}
}
$(day).append(option);
if (val > Days[month]) {
dayOption = $('#dayOption');
dayOption.removeAttr("disabled", false);
dayOption.removeAttr("selected", false);
dayOption.attr("selected", true);
dayOption.attr("disabled", true);
day.get(0).setCustomValidity("Wrong day");
day.get(0).reportValidity();
} else {
day.get(0).setCustomValidity("");
}
}
function change_year(select) {
if (isLeapYear($(select).val())) {
Days[1] = 29;
} else {
Days[1] = 28;
}
month = $("#month").val();
if (month == 2) {
var day2 = $('#day');
var val = $(day).val();
$(day2).empty();
var option = '<option id="dayOption" selected disabled value="day">Day</option>';
for (var i = 1; i <= Days[1]; i ) { //add option days
if (val == i) {
option = '<option selected value="' i '">' i '</option>';
} else {
option = '<option value="' i '">' i '</option>';
}
}
$(day2).append(option);
if (val > Days[1]) {
day2.get(0).setCustomValidity("Wrong day");
day2.get(0).reportValidity();
dayOption = $('#dayOption');
dayOption.removeAttr("disabled", false);
dayOption.removeAttr("selected", false);
dayOption.attr("selected", true);
dayOption.attr("disabled", true);
} else {
day2.get(0).setCustomValidity("");
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<form >
<SELECT id="day" name="dd"></SELECT>
<SELECT id="month" name="mm" onchange="change_month(this)"></SELECT>
<SELECT id="year" name="yyyy" onchange="change_year(this)"></SELECT>
</form>
I have updated one line.
In function change_year
if (month > Days[1]) {
to
if (val > Days[1]) {
CodePudding user response:
We do NOT need leap year tests - just create a date with what is entered and test the year month and day are the same. OR change the number of days depending on the month chosen
This code does not need to give errors, the user cannot select a wrong date
Also it can generate month names in any valid locale
const isValid = (year,month,day) => {
const date = new Date(year,month,day,15,0,0,0)
return date.getMonth() === month && date.getDate() === day; // valid date
};
const getLastDay = (year, month) => new Date(year,month 1,0,15,0,0,0).getDate();
$(function() {
const $year = $('#year');
const $month = $('#month');
const $day = $('#day');
const date = new Date();
date.setDate(15); // arbitrary, but not 1
$month.append(
Array.from({
length: 12
}).map((_, i) => {
date.setMonth(i);
return `<option value="${i}">${date.toLocaleString("en-US",{ month: "long" })}</option>`;
})
);
const endYear = date.getFullYear();
const years = [];
for (let i = endYear, n = endYear - 110; i >= n; i--) years.push(`<option value="${i}">${i}</option>`);
$year.append(years.join(""));
$day.append(
Array.from({
length: 31
}).map((_, i) => `<option value="${i 1}">${i 1}</option>`)
);
const $days = $day.find("option");
$('#day, #month, #year').on("change",(e) => {
const month = $month.val();
const year = $year.val();
const day = $day.val();
if (day === null || month === null || year === null) return; // nothing selected
if (isValid(year,month,day)) return; // ok date
const lastDay = getLastDay(year,month)
if (day>lastDay) $day.val("day"); // reset
for (let i = lastDay; i<=32; i ) $days.eq(i).prop("disabled",i>lastDay); // toggle disabled
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<form >
<select id="day" name="dd">
<option selected disabled value="day">Day</option>
</select>
<select id="month" name="mm">
<option selected disabled value="month">Month</option>
</select>
<select id="year" name="yyyy"><option selected disabled value="year">Year</option></select>
</form>