function updateAnnouncementDurationFields() { var modeSelect = document.getElementById('announcement-duration-mode'); var durationFields = document.querySelector('[data-announcement-duration-value-fields]'); if (!modeSelect || !durationFields) { return; } var durationValueInput = document.getElementById('announcement-duration-value'); var durationUnitSelect = document.getElementById('announcement-duration-unit'); var isDurationMode = String(modeSelect.value || '').trim() === 'duration'; durationFields.hidden = !isDurationMode; if (durationValueInput) { durationValueInput.disabled = !isDurationMode; } if (durationUnitSelect) { durationUnitSelect.disabled = !isDurationMode; } } function updateAnnouncementColorPickerSelection() { var colorInput = document.getElementById('announcement-color'); var picker = document.querySelector('[data-announcement-color-picker-shell]'); if (!colorInput || !picker) { return; } var selectedValue = String(colorInput.value || '').trim().toLowerCase() || 'primary'; picker.querySelectorAll('[data-announcement-color-option]').forEach(function (button) { var isSelected = String(button.getAttribute('data-color-key') || '').trim().toLowerCase() === selectedValue; button.classList.toggle('is-selected', isSelected); button.setAttribute('aria-pressed', isSelected ? 'true' : 'false'); }); } function setAnnouncementScreenSelection(isSelected) { document.querySelectorAll('input[name="screen_ids[]"]').forEach(function (input) { input.checked = isSelected; }); } function getAnnouncementActionButtonState() { var actionForm = document.getElementById('announcement-action-form'); var visibleButton = document.querySelector('button[form="announcement-action-form"]'); var actionPath = actionForm ? String(actionForm.getAttribute('action') || '').trim() : ''; var isPlay = /\/play$/.test(actionPath); var isActive = !isPlay; var selectedScreenCount = document.querySelectorAll('input[name="screen_ids[]"]:checked').length; return { visibleButton: visibleButton, actionForm: actionForm, isActive: isActive, hasTargets: selectedScreenCount > 0, actionDisabled: !isActive && selectedScreenCount === 0, actionLabel: isActive ? 'Stop' : 'Play', actionIcon: isActive ? 'bi-stop-fill' : 'bi-play-fill', actionClassName: !isActive && selectedScreenCount === 0 ? 'btn-outline-info' : (isActive ? 'btn-outline-warning' : 'btn-info'), actionDisabledTitle: !isActive && selectedScreenCount === 0 ? 'Select at least one screen group to play this announcement.' : '', actionConfirmMessage: isActive ? 'Stop this announcement on the selected screens now?' : 'Send this announcement to the selected screens now?' }; } function updateAnnouncementActionButtonState() { var state = getAnnouncementActionButtonState(); if (!state.visibleButton) { return; } state.visibleButton.className = state.visibleButton.className.replace(/btn-outline-(info|warning|success)|btn-info/g, state.actionClassName); state.visibleButton.disabled = state.actionDisabled; state.visibleButton.setAttribute('aria-disabled', state.actionDisabled ? 'true' : 'false'); state.visibleButton.setAttribute('title', state.actionDisabled ? state.actionDisabledTitle : state.actionConfirmMessage); state.visibleButton.setAttribute('aria-label', state.actionLabel); var icon = state.visibleButton.querySelector('i.bi'); if (icon) { icon.className = 'bi ' + state.actionIcon + ' me-1'; } var label = state.visibleButton.childNodes.length > 1 ? state.visibleButton.childNodes[state.visibleButton.childNodes.length - 1] : null; if (label && label.nodeType === Node.TEXT_NODE) { label.textContent = state.actionLabel; } else { state.visibleButton.textContent = state.actionLabel; } if (state.actionForm) { state.actionForm.setAttribute('data-confirm-message', state.actionConfirmMessage); } } function positionAnnouncementTypePicker() { var picker = document.querySelector('[data-announcement-type-picker]'); var toggle = document.querySelector('[data-announcement-type-picker-toggle]'); var shell = document.querySelector('[data-announcement-type-picker-shell]'); if (!picker || picker.hidden || !toggle || !shell) { return; } var padding = 8; var toggleRect = toggle.getBoundingClientRect(); var menuRect = picker.getBoundingClientRect(); var viewportHeight = window.innerHeight || document.documentElement.clientHeight || toggleRect.bottom; var placementAbove = false; var spaceBelow = viewportHeight - toggleRect.bottom - padding; var spaceAbove = toggleRect.top - padding; if (menuRect.height > spaceBelow && spaceAbove > spaceBelow) { placementAbove = true; } picker.classList.toggle('is-open-above', placementAbove); } function closeAnnouncementTypePicker() { var picker = document.querySelector('[data-announcement-type-picker]'); var toggle = document.querySelector('[data-announcement-type-picker-toggle]'); if (!picker) { return; } picker.hidden = true; picker.classList.remove('is-open-above'); if (toggle) { toggle.setAttribute('aria-expanded', 'false'); } } function openAnnouncementTypePicker() { var picker = document.querySelector('[data-announcement-type-picker]'); var toggle = document.querySelector('[data-announcement-type-picker-toggle]'); if (!picker) { return; } picker.hidden = false; if (toggle) { toggle.setAttribute('aria-expanded', 'true'); } if (typeof window !== 'undefined' && window.requestAnimationFrame) { window.requestAnimationFrame(positionAnnouncementTypePicker); } else { positionAnnouncementTypePicker(); } } function updateAnnouncementTypePickerSelection() { var typeInput = document.getElementById('announcement-type'); var previewButton = document.querySelector('[data-announcement-type-picker-toggle]'); var picker = document.querySelector('[data-announcement-type-picker]'); if (!typeInput || !previewButton || !picker) { return; } var selectedValue = String(typeInput.value || '').trim().toLowerCase(); var selectedOption = picker.querySelector('[data-announcement-type-option][data-type-key="' + selectedValue + '"]'); var label = selectedOption ? String(selectedOption.getAttribute('data-type-label') || selectedOption.textContent || selectedValue).trim() : selectedValue; var iconKey = selectedOption ? String(selectedOption.getAttribute('data-type-icon') || '').trim().toLowerCase() : ''; var icon = previewButton.querySelector('[data-announcement-type-picker-icon]'); var text = previewButton.querySelector('[data-announcement-type-picker-label]'); previewButton.setAttribute('aria-label', label); previewButton.setAttribute('title', label); if (icon) { icon.className = 'bi bi-' + iconKey; } if (text) { text.textContent = label; } picker.querySelectorAll('[data-announcement-type-option]').forEach(function (button) { var isSelected = String(button.getAttribute('data-type-key') || '').trim().toLowerCase() === selectedValue; button.classList.toggle('is-selected', isSelected); button.setAttribute('aria-pressed', isSelected ? 'true' : 'false'); }); } function setAnnouncementTypeValue(typeKey) { var typeInput = document.getElementById('announcement-type'); if (!typeInput) { return; } var normalized = String(typeKey || '').trim().toLowerCase(); if (!normalized) { return; } typeInput.value = normalized; updateAnnouncementTypePickerSelection(); } function initAnnouncementForm() { var typeInput = document.getElementById('announcement-type'); var typePickerToggle = document.querySelector('[data-announcement-type-picker-toggle]'); var typePicker = document.querySelector('[data-announcement-type-picker]'); var typePickerClose = document.querySelector('[data-announcement-type-picker-close]'); var modeSelect = document.getElementById('announcement-duration-mode'); var colorInput = document.getElementById('announcement-color'); var colorPicker = document.querySelector('[data-announcement-color-picker-shell]'); var screenSelectAll = document.querySelector('[data-announcement-screen-select-all]'); var screenSelectNone = document.querySelector('[data-announcement-screen-select-none]'); if (typeInput) { updateAnnouncementTypePickerSelection(); } if (typePickerToggle) { typePickerToggle.addEventListener('click', function (event) { event.preventDefault(); var isExpanded = typePicker && !typePicker.hidden; if (isExpanded) { closeAnnouncementTypePicker(); } else { openAnnouncementTypePicker(); } }); } if (typePickerClose) { typePickerClose.addEventListener('click', function (event) { event.preventDefault(); closeAnnouncementTypePicker(); }); } if (typePicker) { typePicker.addEventListener('click', function (event) { var button = event.target && event.target.closest ? event.target.closest('[data-announcement-type-option]') : null; if (!button) { return; } event.preventDefault(); setAnnouncementTypeValue(button.getAttribute('data-type-key')); closeAnnouncementTypePicker(); }); } if (modeSelect) { modeSelect.addEventListener('change', updateAnnouncementDurationFields); updateAnnouncementDurationFields(); } if (colorInput) { updateAnnouncementColorPickerSelection(); } if (colorPicker) { colorPicker.addEventListener('click', function (event) { var button = event.target && event.target.closest ? event.target.closest('[data-announcement-color-option]') : null; if (!button) { return; } event.preventDefault(); colorInput.value = String(button.getAttribute('data-color-key') || '').trim().toLowerCase(); updateAnnouncementColorPickerSelection(); }); } if (screenSelectAll) { screenSelectAll.addEventListener('click', function (event) { event.preventDefault(); setAnnouncementScreenSelection(true); }); } if (screenSelectNone) { screenSelectNone.addEventListener('click', function (event) { event.preventDefault(); setAnnouncementScreenSelection(false); }); } document.addEventListener('web-async-save:success', function (event) { var detail = event && event.detail ? event.detail : null; var form = detail && detail.form ? detail.form : null; if (!form || form.id !== 'announcement-form') { return; } updateAnnouncementActionButtonState(); }); window.addEventListener('resize', positionAnnouncementTypePicker); document.addEventListener('click', function (event) { var typePickerNode = document.querySelector('[data-announcement-type-picker]'); var typeToggleNode = document.querySelector('[data-announcement-type-picker-toggle]'); if (typePickerNode && !typePickerNode.hidden) { if (!(typePickerNode.contains(event.target) || (typeToggleNode && typeToggleNode.contains(event.target)))) { closeAnnouncementTypePicker(); } } }); updateAnnouncementActionButtonState(); } if (typeof document !== 'undefined') { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initAnnouncementForm, { once: true }); } else { initAnnouncementForm(); } }