/* @config : next999.json @filename : ${psFileBasename} @title : 2.カレンダー表示 @name : 2.カレンダー表示 @siteIds : 310514 @siteTitles : イオン多摩平シフト希望 @disabled: false */ //カレンダーを生成して挿入する関数 function renderCalendar(year, month, checkedDates = [], selectedHoursArray = []) { $('#custom-calendar-container').remove(); let containerHtml = `
`; // メインコンテナ let calendarAndControlsFlexContainer = `
`; // カレンダーと操作ボタンのFlexコンテナ // カレンダー本体 let calendarTableHtml = `
`; let firstDay = new Date(year, month - 1, 1); let lastDay = new Date(year, month, 0); for (let i = 0; i < firstDay.getDay(); i++) calendarTableHtml += ""; for (let d = 1; d <= lastDay.getDate(); d++) { let dateObj = new Date(year, month - 1, d); let dayOfWeek = dateObj.getDay(); let dateStr = `${year}-${String(month).padStart(2, '0')}-${String(d).padStart(2, '0')}`; let checked = checkedDates.includes(dateStr) ? 'checked' : ''; calendarTableHtml += ``; if ((firstDay.getDay() + d) % 7 === 0 && d !== lastDay.getDate()) calendarTableHtml += ""; } let lastDayOfWeek = new Date(year, month - 1, lastDay.getDate()).getDay(); for (let i = lastDayOfWeek + 1; i <= 6; i++) calendarTableHtml += ""; calendarTableHtml += "
"; // カレンダーテーブルの閉じタグ calendarAndControlsFlexContainer += calendarTableHtml; // 操作コントロール(ボタンとタイムバー)のコンテナ let controlsContainerHtml = `
`; // 一括操作ボタン controlsContainerHtml += `
`; // 曜日ボタン controlsContainerHtml += `
`; // 時間選択バー controlsContainerHtml += `
`; for (let hour = 10; hour <= 21; hour++) { controlsContainerHtml += `
${hour}
`; } controlsContainerHtml += `

選択された時間: なし

`; controlsContainerHtml += `
`; // controls-container の閉じタグ calendarAndControlsFlexContainer += controlsContainerHtml; calendarAndControlsFlexContainer += `
`; // custom-calendar (Flexコンテナ) の閉じタグ containerHtml += calendarAndControlsFlexContainer; containerHtml += "
"; // custom-calendar-container の閉じタグ $('#SectionFields1Container').after(containerHtml); // ボタンイベント (変更なし) $('#calendar-check-all').off('click').on('click', function () { $('#custom-calendar .calendar-checkbox').prop('checked', true); }); $('#calendar-uncheck-all').off('click').on('click', function () { $('#custom-calendar .calendar-checkbox').prop('checked', false); }); let dayToggleState = { 0: false, 1: false, 2: false, 3: false, 4: false, 5: false, 6: false }; $('.calendar-day-toggle').off('click').on('click', function () { const day = $(this).data('day'); dayToggleState[day] = !dayToggleState[day]; $('#custom-calendar .calendar-checkbox[data-day="' + day + '"]').prop('checked', dayToggleState[day]); if (dayToggleState[day]) { $(this).css('background', '#0078d7').css('color', '#fff'); } else { $(this).css('background', '').css('color', ''); } }); // 時間選択バーのロジック (変更なし) const timeSlots = $('.time-slot'); const selectedHoursDisplay = $('#selected-hours-display'); let isDragging = false; let selectionStartHour = -1; let selectionEndHour = -1; if (selectedHoursArray && selectedHoursArray.length > 0) { if (selectedHoursArray.length >= 1) { selectionStartHour = Math.min(...selectedHoursArray); selectionEndHour = Math.max(...selectedHoursArray); updateSelectionVisuals(); if (selectedHoursArray.length >= 2) { selectedHoursDisplay.text(selectedHoursArray.sort((a, b) => a - b).join(',')); } else { selectedHoursDisplay.text('最低2時間選択してください'); } } } timeSlots.on('mousedown touchstart', function (e) { // touchstart を追加 e.preventDefault(); isDragging = true; const currentHour = parseInt($(this).data('hour')); selectionStartHour = currentHour; selectionEndHour = currentHour; updateSelectionVisuals(); }); timeSlots.on('mousemove touchmove', function (e) { // touchmove を追加 if (isDragging) { let pageX; if (e.type === 'touchmove') { pageX = e.originalEvent.touches[0].pageX; } else { pageX = e.pageX; } // マウス/タッチ位置から最も近いスロットを見つける let closestSlot = null; let minDistance = Infinity; timeSlots.each(function () { const slot = $(this); const slotCenterX = slot.offset().left + slot.width() / 2; const distance = Math.abs(pageX - slotCenterX); if (distance < minDistance) { minDistance = distance; closestSlot = slot; } }); if (closestSlot) { const currentHour = parseInt(closestSlot.data('hour')); selectionEndHour = currentHour; updateSelectionVisuals(); } } }); $(document).on('mouseup touchend', function () { // touchend を追加 if (isDragging) { isDragging = false; const start = Math.min(selectionStartHour, selectionEndHour); const end = Math.max(selectionStartHour, selectionEndHour); const selectedCount = (start !== -1 && end !== -1) ? (end - start + 1) : 0; if (selectedCount < 2 && selectedCount > 0) { $p.ex.setMyMessage('alert-error new-status-red', '開始時間と終了時間を選択してください'); timeSlots.css('background-color', ''); selectedHoursDisplay.text('なし'); $p.set($('#Results_ClassD'), JSON.stringify([])); selectionStartHour = -1; selectionEndHour = -1; } else if (selectedCount >= 2) { $p.clearMessage(); saveSelectedHoursToField(); } else { $p.clearMessage(); timeSlots.css('background-color', ''); selectedHoursDisplay.text('なし'); $p.set($('#Results_ClassD'), JSON.stringify([])); selectionStartHour = -1; selectionEndHour = -1; } } }); function updateSelectionVisuals() { timeSlots.css('background-color', ''); const start = Math.min(selectionStartHour, selectionEndHour); const end = Math.max(selectionStartHour, selectionEndHour); if (start !== -1 && end !== -1) { for (let i = start; i <= end; i++) { $(`.time-slot[data-hour="${i}"]`).css('background-color', '#a0c4ff'); } } } function saveSelectedHoursToField() { const selected = []; if (selectionStartHour !== -1 && selectionEndHour !== -1) { const start = Math.min(selectionStartHour, selectionEndHour); const end = Math.max(selectionStartHour, selectionEndHour); if ((end - start + 1) >= 2) { for (let i = start; i <= end; i++) { selected.push(i.toString()); } selectedHoursDisplay.text(selected.join(',') || 'なし'); $p.set($('#Results_ClassD'), JSON.stringify(selected)); console.log('Selected hours saved to Results_ClassD:', JSON.stringify(selected)); } else { selectedHoursDisplay.text('開始時間と終了時間を選択してください'); $p.set($('#Results_ClassD'), JSON.stringify([])); console.log('Selection less than 2 hours, not saved.'); } } else { selectedHoursDisplay.text('なし'); $p.set($('#Results_ClassD'), JSON.stringify([])); } } } //チェックされた日付を取得する関数 (変更なし) function getCheckedDates() { return $('.calendar-checkbox:checked').map(function () { return this.value; }).get(); } //選択された時間を取得する関数 (Results_ClassDから読み込む) function getSelectedHours() { const classD = $('#Results_ClassD').val(); let hoursArray = []; if (classD[0] === 'いつでも') { hoursArray = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]; } else { for (let i = 0; i < classD.length; i++) { hoursArray.push(parseFloat(classD[i])); } } return hoursArray; } /* console.log(hoursString); if (hoursString) { try { const parsedHours = JSON.parse(hoursString); if (Array.isArray(parsedHours) && parsedHours.every(h => typeof h === 'number')) { return parsedHours; } } catch (e) { console.error("Error parsing selected hours from Results_ClassD:", e); if (typeof hoursString === 'string' && hoursString.includes(',')) { return hoursString.split(',').map(h => parseInt(h.trim(), 10)).filter(h => !isNaN(h)); } } } return []; } */ //年月選択UIとイベント (変更なし) function setupCalendarUI(initialYear, initialMonth, checkedDates = [], initialSelectedHoursArray = []) { renderCalendar(initialYear, initialMonth, checkedDates, initialSelectedHoursArray); $p.on('change', 'ClassA', function () { let y = parseFloat($('#Results_ClassA').val().split('年')[0]); let m = parseFloat($('#Results_ClassA').val().split('年')[1].split('月')[0]); renderCalendar(y, m, getCheckedDates(), getSelectedHours()); }); } function setupCalendar() { let initialYear = parseFloat($('#Results_ClassA').val().split('年')[0]); let initialMonth = parseFloat($('#Results_ClassA').val().split('年')[1].split('月')[0]); let initialCheckedDates = $('#Results_ClassW').val() ? JSON.parse($('#Results_ClassW').val()) : []; let initialSelectedHoursArray = getSelectedHours(); setupCalendarUI(initialYear, initialMonth, initialCheckedDates, initialSelectedHoursArray); }