/** * Hours Copy Extension for form.min.js * Adds copy functionality to hours forms with modal interface * * Dependencies: form.min.js, modal.min.js, utility functions (targetCheck, getIcon) */ class HoursCopyExtension { constructor() { this.createModal(); this.setupModal(); this.currentSourceDay = null; this.days = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']; this.init(); } handleChange(e) { if (window.targetCheck('.hours-copy-btn')) { e.preventDefault({bubbles: true}); } } init() { this.addCopyButtons(); this.bindEvents(); } createModal() { this.modalElement = document.querySelector('dialog#copy-hours'); // Create modal element if it doesn't exist if (!this.modalElement) { const modal = window.getTemplate('copyHours'); document.body.appendChild(modal); this.modalElement = document.querySelector('dialog#copy-hours'); } console.log(this.modalElement); } setupModal() { this.modal = new window.jvbModal( this.modalElement, { open: '.hours-copy-btn', openMessage: "Copy hours modal opened", closeMessage: "Copy hours modal closed", } ); this.modal.subscribe((event, data) => { switch(event) { case 'modal-open': let e = data.event; let modal = data.modal; const dayGroup = e.target.closest('.group-fields:not(.hours)'); console.log(dayGroup); const dayName = this.getDayNameFromGroup(dayGroup); console.log(dayName); if (!dayName) return; this.currentSourceDay = dayName; console.log(dayName); // Get source day hours const sourceData = this.getSourceDayData(dayGroup); console.log(sourceData); // Update source day info const sourceDayEl = modal.querySelector('.source-day'); const sourceHoursEl = modal.querySelector('.source-hours'); console.log('Elements: ', {sourceDayEl, sourceHoursEl}); if (sourceDayEl) { sourceDayEl.textContent = window.uppercaseFirst ? window.uppercaseFirst(dayName) : dayName.charAt(0).toUpperCase() + dayName.slice(1); } if (sourceHoursEl) { if (sourceData.isOpen && sourceData.opens && sourceData.closes) { sourceHoursEl.textContent = `${sourceData.opens} - ${sourceData.closes}`; sourceHoursEl.className = 'source-hours'; } else { sourceHoursEl.textContent = 'Closed'; sourceHoursEl.className = 'source-hours closed'; } } this.modal.modal.querySelector(`label[for=copy-to-${dayName}]`).hidden = true; this.modal.modal.querySelectorAll(`label:not([for=copy-to-${dayName}])[hidden]`).hidden = false; break; case 'modal-close': this.applyCopyHours() this.currentSourceDay = null; break; } }); } addCopyButtons() { // Add copy buttons to each day group const dayGroups = document.querySelectorAll('.group-fields.hours .group-fields:not(.hours)'); dayGroups.forEach(group => { if (!group.querySelector('.hours-copy-btn')) { const copyBtn = this.createCopyButton(); group.insertBefore(copyBtn, group.querySelector('.field.time')); } }); } createCopyButton() { const button = window.getTemplate('blankButton'); button.type = 'button'; button.className = 'hours-copy-btn'; button.title = 'Copy this time to other days'; button.prepend(window.getIcon('copy')); button.setAttribute('data-action', 'copy-hours'); return button; } bindEvents() { this.changeHandler = this.handleChange.bind(this); this.modal.modal.addEventListener('change', this.changeHandler); } getDayNameFromGroup(group) { const classList = Array.from(group.classList); return this.days.find(day => classList.includes(day)); } getSourceDayData(dayGroup) { console.log(dayGroup); const openCheckbox = dayGroup.querySelector('input[type="checkbox"][name$=":open"]'); const opensInput = dayGroup.querySelector('input[name$=":time_opens"]'); const closesInput = dayGroup.querySelector('input[name$=":time_closes"]'); return { isOpen: openCheckbox ? openCheckbox.checked : false, opens: opensInput ? opensInput.value : '', closes: closesInput ? closesInput.value : '' }; } applyCopyHours() { if (!this.currentSourceDay) return; const sourceGroup = document.querySelector(`.group-fields.${this.currentSourceDay}`); if (!sourceGroup) return; const sourceData = this.getSourceDayData(sourceGroup); // Get selected target days const selectedDays = Array.from( this.modal.modal.querySelectorAll('input:checked') ).map(checkbox => checkbox.value); if (selectedDays.length === 0) { alert('Please select at least one day to copy to.'); return; } // Apply hours to selected days selectedDays.forEach(day => { this.applyHoursToDay(day, sourceData); }); // Show success feedback this.showSuccessFeedback(selectedDays.length); } applyHoursToDay(dayName, sourceData) { const targetGroup = document.querySelector(`.group-fields.${dayName}`); if (!targetGroup) return; const openCheckbox = targetGroup.querySelector('input[type="checkbox"][name$=":open"]'); const opensInput = targetGroup.querySelector('input[name$=":time_opens"]'); const closesInput = targetGroup.querySelector('input[name$=":time_closes"]'); console.log('applying hours to days: ', { openCheckbox, opensInput, closesInput }); if (!openCheckbox) return; // Set checkbox state openCheckbox.checked = sourceData.isOpen; openCheckbox.dispatchEvent(new Event('change', {bubbles: true})); // Set time values if open if (sourceData.isOpen && opensInput && closesInput) { opensInput.value = sourceData.opens; closesInput.value = sourceData.closes; } else if (opensInput && closesInput) { opensInput.value = ''; closesInput.value = ''; } } showSuccessFeedback(count) { // Create or update feedback element let feedback = document.getElementById('copy-success-feedback'); if (!feedback) { feedback = document.createElement('div'); feedback.id = 'copy-success-feedback'; feedback.className = 'copy-success-feedback'; document.body.appendChild(feedback); } const message = count === 1 ? 'Hours copied to 1 day successfully!' : `Hours copied to ${count} days successfully!`; feedback.querySelector('span').textContent = message; // Show feedback feedback.classList.add('show'); // Hide after delay window.debouncer.schedule('copy-success', () => { feedback.classList.remove('show'); }, 3000); // Use accessibility announcements if available if (window.jvbA11y && window.jvbA11y.announce) { window.jvbA11y.announce(message); } } } document.addEventListener('DOMContentLoaded', () => { window.jvbCopy = new HoursCopyExtension(); });