Files
pulse-signage/src/player/public/js/player-announcement-templates.js
T
2026-08-05 19:38:16 +01:00

137 lines
5.8 KiB
JavaScript

(function () {
var ANNOUNCEMENT_TYPES = ['lower-third', 'fullscreen', 'top-banner'];
var ANNOUNCEMENT_ICONS = Array.isArray(window.pulseAnnouncementIconKeys) ? window.pulseAnnouncementIconKeys : [];
var DEFAULT_ANNOUNCEMENT_ICON = String(window.pulseAnnouncementDefaultIconKey || ANNOUNCEMENT_ICONS[0] || '').trim().toLowerCase();
function escapeHtml(value) {
return String(value ?? '')
.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}
function normalizeAnnouncementType(value) {
var normalized = String(value || '').trim().toLowerCase();
if (normalized === 'center-card') {
return 'fullscreen';
}
return ANNOUNCEMENT_TYPES.indexOf(normalized) !== -1 ? normalized : 'lower-third';
}
function normalizeAnnouncementColor(value) {
var normalized = String(value || '').trim().toLowerCase();
if (['primary', 'secondary', 'success', 'info', 'warning', 'danger', 'dark', 'light'].indexOf(normalized) !== -1) {
return normalized;
}
return 'primary';
}
function normalizeAnnouncementIcon(value) {
var normalized = String(value || '').trim().toLowerCase();
return ANNOUNCEMENT_ICONS.indexOf(normalized) !== -1 ? normalized : DEFAULT_ANNOUNCEMENT_ICON;
}
function getAnnouncementColorTokens(colorKey) {
var tokens = {
primary: { accent: '#0d6efd', foreground: '#ffffff', glow: 'rgba(13, 110, 253, 0.32)' },
secondary: { accent: '#6c757d', foreground: '#ffffff', glow: 'rgba(108, 117, 125, 0.30)' },
success: { accent: '#198754', foreground: '#ffffff', glow: 'rgba(25, 135, 84, 0.34)' },
info: { accent: '#0dcaf0', foreground: '#052c36', glow: 'rgba(13, 202, 240, 0.28)' },
warning: { accent: '#ffc107', foreground: '#201400', glow: 'rgba(255, 193, 7, 0.30)' },
danger: { accent: '#dc3545', foreground: '#ffffff', glow: 'rgba(220, 53, 69, 0.34)' },
dark: { accent: '#212529', foreground: '#ffffff', glow: 'rgba(33, 37, 41, 0.34)' },
light: { accent: '#f8f9fa', foreground: '#1f2937', glow: 'rgba(248, 249, 250, 0.34)' }
};
return tokens[colorKey] || tokens.primary;
}
function replaceTemplate(template, replacements) {
return String(template || '').replace(/{{([A-Z0-9_]+)}}/g, function (_match, key) {
return Object.prototype.hasOwnProperty.call(replacements, key) ? String(replacements[key]) : '';
});
}
function getComputedGapWidth(track) {
if (!track || !window.getComputedStyle) {
return 0;
}
var computedStyle = window.getComputedStyle(track);
var gapValue = String(computedStyle.columnGap || computedStyle.gap || '0').trim();
var gap = Number.parseFloat(gapValue);
return Number.isFinite(gap) ? gap : 0;
}
function getElementWidth(element) {
if (!element || !element.getBoundingClientRect) {
return 0;
}
return Math.max(0, element.getBoundingClientRect().width || 0);
}
function initPlayerAnnouncementMarquee(track, options) {
if (!track || track.dataset.marqueeMeasured === 'true') {
return;
}
var settings = options || {};
var rate = Number(settings.rate || track.getAttribute('data-announcement-marquee-rate') || 44) || 44;
var textSelector = String(settings.textSelector || '.player-announcement__message-text').trim() || '.player-announcement__message-text';
var textNodes = Array.prototype.slice.call(track.querySelectorAll(textSelector));
if (!textNodes.length) {
return;
}
var container = settings.container || track.parentElement || track;
var containerWidth = Math.max(1, getElementWidth(container) || 0);
var gapWidth = getComputedGapWidth(track);
var firstItemWidth = Math.max(1, getElementWidth(textNodes[0]) || 0);
var cycleWidth = Math.max(1, firstItemWidth + gapWidth);
var minimumTrackWidth = Math.max(containerWidth + cycleWidth, cycleWidth * 2);
var cloneIndex = 0;
while (getElementWidth(track) < minimumTrackWidth && cloneIndex < 8) {
var clone = textNodes[cloneIndex % textNodes.length].cloneNode(true);
clone.setAttribute('aria-hidden', 'true');
track.appendChild(clone);
cloneIndex += 1;
}
var durationSeconds = Math.max(8, cycleWidth / rate);
var durationValue = durationSeconds.toFixed(2) + 's';
track.dataset.marqueeMeasured = 'true';
track.style.setProperty('--announcement-scroll-distance', cycleWidth.toFixed(2) + 'px');
track.style.setProperty('--announcement-scroll-duration', durationValue);
track.style.animationDuration = durationValue;
}
function renderPlayerAnnouncementMarkup(announcement) {
var normalizedType = normalizeAnnouncementType(announcement && announcement.announcement_type);
var colorKey = normalizeAnnouncementColor(announcement && announcement.color_key);
var colorTokens = getAnnouncementColorTokens(colorKey);
var iconKey = normalizeAnnouncementIcon(announcement && announcement.icon_key);
var text = escapeHtml(String(announcement && announcement.message || '').trim()).replace(/[\r\n]+/g, ' ');
var titleText = escapeHtml(String(announcement && announcement.short_label || 'Announcement').trim() || 'Announcement');
var templates = window.playerAnnouncementTemplates || {};
var templateName = normalizedType === 'fullscreen' ? 'fullscreen' : normalizedType === 'top-banner' ? 'topBanner' : 'lowerThird';
var template = templates[templateName] || '';
return replaceTemplate(template, {
ACCENT: colorTokens.accent,
FOREGROUND: colorTokens.foreground,
GLOW: colorTokens.glow,
ICON: iconKey,
COLOR_KEY: colorKey,
TITLE: titleText,
MESSAGE: text
});
}
window.renderPlayerAnnouncementMarkup = renderPlayerAnnouncementMarkup;
window.initPlayerAnnouncementMarquee = initPlayerAnnouncementMarquee;
})();