同じページに選択によって3パターンに分岐する構成のフォームがあります。その中のそれぞれに2つカレンダーによる入力項目があります。
いづれのページも「申込日」「工事日」なのですが下記のように制限をかけたいです。
申込日:今日以前の選択ができない
工事日:申込日から30営業日以降でないと選択できない
分岐があった際の処理がわかりません。1つ対応できそうなスクリプトを組んだのですがうまく動きませんでした。有識者の方、ご教授いただけますと幸いです。
==============================
// カレンダーのセレクタ設定
const calendarSelectors = [
{ wrapper: ‘[data-vv-name=“お客様_申込日”]’, name: ‘お客様_申込日’ },
{ wrapper: ‘[data-vv-name=“お客様_工事希望日”]’, name: ‘お客様_工事希望日’ }
];
// 日本時間で今日の日付を取得
function getJapanTime() {
const now = new Date();
return new Date(now.getFullYear(), now.getMonth(), now.getDate());
}
const today = getJapanTime();
// 静的な除外日リスト(毎年の固定除外日+2025年~2029年の祝日)
const staticExclusionDates = [
// 毎年の固定除外日(※1月1日は除外)
‘12-27’, ‘12-28’, ‘12-29’, ‘12-30’, ‘12-31’, ‘01-02’, ‘01-03’,
// 2025年の祝日
'2025-01-01', '2025-01-13', '2025-02-11', '2025-02-23', '2025-03-20', '2025-04-29',
'2025-05-03', '2025-05-04', '2025-05-05', '2025-07-21', '2025-08-11',
'2025-09-15', '2025-09-23', '2025-10-13', '2025-11-03', '2025-11-23',
// 2026年の祝日
'2026-01-01', '2026-01-12', '2026-02-11', '2026-02-23', '2026-03-20',
'2026-04-29', '2026-05-03', '2026-05-04', '2026-05-05', '2026-07-20',
'2026-08-11', '2026-09-21', '2026-09-22', '2026-10-12', '2026-11-03',
'2026-11-23',
// 2027年の祝日
'2027-01-01', '2027-01-11', '2027-02-11', '2027-02-23', '2027-03-21',
'2027-04-29', '2027-05-03', '2027-05-04', '2027-05-05', '2027-07-19',
'2027-08-11', '2027-09-20', '2027-09-23', '2027-10-11', '2027-11-03',
'2027-11-23',
// 2028年の祝日
'2028-01-01', '2028-01-10', '2028-02-11', '2028-02-23', '2028-03-20',
'2028-04-29', '2028-05-03', '2028-05-04', '2028-05-05', '2028-07-17',
'2028-08-11', '2028-09-18', '2028-09-22', '2028-10-09', '2028-11-03',
'2028-11-23',
// 2029年の祝日
'2029-01-01', '2029-01-08', '2029-02-11', '2029-02-23', '2029-03-20',
'2029-04-29', '2029-05-03', '2029-05-04', '2029-05-05', '2029-07-16',
'2029-08-11', '2029-09-17', '2029-09-23', '2029-10-08', '2029-11-03',
'2029-11-23'
];
// 営業日計算関数
function calculateBusinessDate(startDate, days) {
let date = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
let businessDaysCount = 0;
while (businessDaysCount < days) {
date.setDate(date.getDate() + 1);
// 年と月に依存するフォーマットでチェック
const formattedDate = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`;
const isWeekend = date.getDay() === 0 || date.getDay() === 6;
const isExclusionDate = staticExclusionDates.includes(formattedDate);
if (!isWeekend && !isExclusionDate) {
businessDaysCount++;
}
}
console.log(`Calculated business date: ${date.toISOString()}`);
return date;
}
// カレンダー制御関数
function disablePastAndInvalidDates(panelElement, minDate) {
console.log(Disabling dates before: ${minDate.toISOString()}
);
const calendarCells = panelElement.querySelectorAll('.el-date-table td');
calendarCells.forEach(cell => {
const cellText = cell.innerText.trim();
const cellClass = cell.className;
let cellDate;
if (cellClass.includes('prev-month')) {
cellDate = new Date(minDate.getFullYear(), minDate.getMonth() - 1, parseInt(cellText));
} else if (cellClass.includes('next-month')) {
cellDate = new Date(minDate.getFullYear(), minDate.getMonth() + 1, parseInt(cellText));
} else if (cellClass.includes('available')) {
cellDate = new Date(minDate.getFullYear(), minDate.getMonth(), parseInt(cellText));
} else {
return; // 無効なセルはスキップ
}
if (cellDate < minDate) {
cell.classList.add('disabled');
cell.style.pointerEvents = 'none';
cell.style.backgroundColor = '#f5f5f5';
cell.style.color = '#ccc';
} else {
cell.classList.remove('disabled');
cell.style.pointerEvents = 'auto';
cell.style.backgroundColor = '';
cell.style.color = '';
}
});
console.log('Past and invalid dates disabled.');
}
// 初期化関数
function initializeCalendars() {
const applicationWrapper = document.querySelector(‘[data-vv-name=“申込日”]’);
const constructionWrapper = document.querySelector(‘[data-vv-name=“工事日”]’);
if (applicationWrapper) {
const applicationInput = applicationWrapper.querySelector('.el-input__inner');
// 申込日カレンダーの制御
applicationInput.addEventListener('focus', () => {
setTimeout(() => {
const panelElements = document.querySelectorAll('.el-picker-panel');
const panelElement = Array.from(panelElements).find(panel => panel.style.display !== 'none');
if (panelElement) {
disablePastAndInvalidDates(panelElement, today);
}
}, 30);
});
// 申込日変更時の工事希望日更新
applicationInput.addEventListener('change', () => {
const applicationDate = new Date(applicationInput.value);
if (isNaN(applicationDate)) {
console.warn("Invalid application date.");
return;
}
const minDate = calculateBusinessDate(applicationDate, 30);
if (constructionWrapper) {
const constructionInput = constructionWrapper.querySelector('.el-input__inner');
constructionInput.addEventListener('focus', () => {
setTimeout(() => {
const panelElements = document.querySelectorAll('.el-picker-panel');
const panelElement = Array.from(panelElements).find(panel => panel.style.display !== 'none');
if (panelElement) {
disablePastAndInvalidDates(panelElement, minDate);
}
}, 30);
});
}
});
}
}
// 実行
initializeCalendars();