Release v2.5.6

This commit is contained in:
2026-08-05 19:38:16 +01:00
parent a8ef35b287
commit 9f831f04bc
161 changed files with 8487 additions and 1295 deletions
+158 -46
View File
@@ -68,6 +68,32 @@ export function createSlideFormEditorController(options) {
return card ? card.querySelector('input[name="region_font_size_' + regionId + '"]') : null;
}
function getTinymce() {
return window.tinymce || null;
}
function getThemeName() {
var theme = String(document.documentElement && document.documentElement.dataset && document.documentElement.dataset.bsTheme || 'light').trim().toLowerCase();
if (theme === 'auto') {
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
return theme === 'dark' ? 'dark' : 'light';
}
function getTinyMceThemeAssets() {
var themeName = getThemeName();
var skinName = themeName === 'dark' ? 'oxide-dark' : 'oxide';
var skinBase = '/assets/vendor/tinymce/skins/ui/' + skinName;
return {
themeName: themeName,
skinName: skinName,
skinUrl: skinBase,
contentCss: skinBase + '/content.css',
bodyClass: themeName === 'dark' ? 'tinymce-theme-dark' : 'tinymce-theme-light'
};
}
function getEditorRegionType(card) {
if (!card) {
return '';
@@ -99,31 +125,6 @@ export function createSlideFormEditorController(options) {
fontSizeHidden.value = normalizeFontSizeValue(fontSizeHidden.value) || String(defaultFontSize);
}
function getTinymce() {
return window.tinymce || null;
}
function getThemeName() {
var theme = String(document.documentElement && document.documentElement.dataset && document.documentElement.dataset.bsTheme || 'light').trim().toLowerCase();
if (theme === 'auto') {
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
return theme === 'dark' ? 'dark' : 'light';
}
function getTinyMceThemeAssets() {
var themeName = getThemeName();
var skinName = themeName === 'dark' ? 'oxide-dark' : 'oxide';
var skinBase = '/assets/vendor/tinymce/skins/ui/' + skinName;
return {
themeName: themeName,
skinName: skinName,
skinUrl: skinBase,
contentCss: skinBase + '/content.css',
bodyClass: themeName === 'dark' ? 'tinymce-theme-dark' : 'tinymce-theme-light'
};
}
function getEditorBackgroundColorValue() {
var value = String(getEditorBackgroundColor() || '').trim();
return value || '#111111';
@@ -161,28 +162,19 @@ export function createSlideFormEditorController(options) {
function attachEditorEvents(regionId, editor) {
var hidden = getEditorHiddenInput(regionId);
var source = editor && editor.targetElm ? editor.targetElm : null;
var hydrated = false;
function syncState() {
function syncState(shouldLock) {
var currentEditor = editorInstances.get(regionId);
if (currentEditor !== editor) {
return;
}
if (typeof editor.save === 'function') {
editor.save();
syncEditorState(regionId, editor, shouldLock, hydrated);
if (!hydrated) {
requestPreviewRender();
return;
}
var content = editor.getContent({ format: 'html' });
content = isEmptyRichTextValue(content) ? '' : content;
if (hidden) {
hidden.value = content;
}
if (source) {
source.value = content;
}
if (templateSelectorLock && typeof templateSelectorLock.markEdited === 'function') {
templateSelectorLock.markEdited();
}
requestPreviewRender();
}
editor.on('init', function () {
@@ -195,11 +187,14 @@ export function createSlideFormEditorController(options) {
source.value = content;
}
syncEditorFontSizeHidden(regionId);
syncState();
hydrated = true;
requestPreviewRender();
});
['change', 'keyup', 'undo', 'redo', 'SetContent', 'Paste', 'input', 'NodeChange'].forEach(function (eventName) {
editor.on(eventName, syncState);
['change', 'keyup', 'undo', 'redo', 'Paste', 'input'].forEach(function (eventName) {
editor.on(eventName, function () {
syncState(true);
});
});
}
@@ -226,15 +221,74 @@ export function createSlideFormEditorController(options) {
source.id = 'slide-editor-region-' + regionId;
}
function registerInlineFormat(editor, formatName, styles) {
editor.formatter.register(formatName, {
inline: 'span',
styles: styles
});
}
function syncEditorState(regionId, editor, shouldLock, hydrated) {
if (editor && typeof editor.save === 'function') {
editor.save();
}
var content = editor.getContent({ format: 'html' });
content = isEmptyRichTextValue(content) ? '' : content;
var hidden = getEditorHiddenInput(regionId);
var sourceElm = editor && editor.targetElm ? editor.targetElm : null;
if (hidden) {
hidden.value = content;
}
if (sourceElm) {
sourceElm.value = content;
}
if (typeof editor.nodeChanged === 'function') {
editor.nodeChanged();
}
if (typeof editor.setDirty === 'function') {
editor.setDirty(true);
}
if (shouldLock && templateSelectorLock && typeof templateSelectorLock.arm === 'function') {
templateSelectorLock.arm();
}
if (shouldLock && templateSelectorLock && typeof templateSelectorLock.markEdited === 'function') {
templateSelectorLock.markEdited();
}
if (hydrated) {
requestPreviewRender();
}
}
function applyInlineFormat(regionId, editor, formatName) {
if (editor && editor.undoManager && typeof editor.undoManager.transact === 'function') {
editor.undoManager.transact(function () {
editor.formatter.apply(formatName);
});
} else {
editor.formatter.apply(formatName);
}
syncEditorState(regionId, editor, false, true);
}
function applyEditorCommand(regionId, editor, commandName) {
if (editor && editor.undoManager && typeof editor.undoManager.transact === 'function') {
editor.undoManager.transact(function () {
editor.execCommand(commandName);
});
} else {
editor.execCommand(commandName);
}
syncEditorState(regionId, editor, false, true);
}
return tinymce.init({
target: source,
menubar: false,
branding: false,
promotion: false,
statusbar: true,
resize: true,
plugins: 'lists code advlist fullscreen table',
toolbar: 'undo redo | fontfamily fontsizeinput | forecolor backcolor bold italic underline strikethrough subscript superscript removeformat | align lineheight indent outdent bullist numlist table | fullscreen',
toolbar: 'undo redo | fontfamily fontsizeinput | forecolor backcolor bold italic underlineformats removeformat | align lineheight indent outdent bullist numlist table chip | fullscreen',
toolbar_mode: 'sliding',
license_key: 'gpl',
skin: themeAssets.skinName,
@@ -251,6 +305,64 @@ export function createSlideFormEditorController(options) {
placeholder: String(source.getAttribute('placeholder') || '').trim(),
setup: function (editor) {
editorInstances.set(regionId, editor);
editor.ui.registry.addButton('chip', {
icon: 'addtag',
tooltip: 'Chip style',
onAction: function () {
applyInlineFormat(regionId, editor, 'chip');
}
});
editor.ui.registry.addSplitButton('underlineformats', {
icon: 'underline',
tooltip: 'Text formats',
onAction: function () {
applyEditorCommand(regionId, editor, 'Underline');
},
onItemAction: function (_api, value) {
if (value === 'strikethrough') {
applyEditorCommand(regionId, editor, 'Strikethrough');
return;
}
if (value === 'subscript') {
applyEditorCommand(regionId, editor, 'Subscript');
return;
}
if (value === 'superscript') {
applyEditorCommand(regionId, editor, 'Superscript');
}
},
fetch: function (callback) {
callback([
{
type: 'choiceitem',
value: 'strikethrough',
icon: 'strikethrough',
text: 'Strikethrough',
},
{
type: 'choiceitem',
value: 'subscript',
icon: 'subscript',
text: 'Subscript',
},
{
type: 'choiceitem',
value: 'superscript',
icon: 'superscript',
text: 'Superscript',
}
]);
}
});
editor.on('init', function () {
registerInlineFormat(editor, 'chip', {
display: 'inline-block',
padding: '0.2em 0.6em',
borderRadius: '999px',
fontWeight: '700',
letterSpacing: '0.02em'
});
});
attachEditorEvents(regionId, editor);
}
}).then(function (editors) {
+97 -6
View File
@@ -10,6 +10,7 @@ export function createSlideFormRegionHelpers(options) {
var apiSources = Array.isArray(settings.apiSources) ? settings.apiSources : [];
var timetableGroups = Array.isArray(settings.timetableGroups) ? settings.timetableGroups : [];
var getRegionTypeModule = typeof settings.getRegionTypeModule === 'function' ? settings.getRegionTypeModule : function () { return null; };
var requestPreviewRender = typeof settings.requestPreviewRender === 'function' ? settings.requestPreviewRender : function () {};
var placeholderUtils = window.placeholderUtils || {};
var placeholderChips = window.placeholderChips || {};
var escapeHtml = typeof settings.escapeHtml === 'function'
@@ -76,6 +77,11 @@ export function createSlideFormRegionHelpers(options) {
}) || null;
}
function getRssFeedItemCount(feedId) {
var feed = getRssFeedById(feedId);
return feed && Array.isArray(feed.items) ? feed.items.length : 0;
}
function getRssFieldList(feedId) {
var module = getRegionTypeModule('rss');
if (module && typeof module.getFieldList === 'function') {
@@ -128,16 +134,18 @@ export function createSlideFormRegionHelpers(options) {
? placeholderChips.renderChip(field)
: '<span class="chip">{{' + escapeHtml(field) + '}}</span>';
}).join('');
var transformHint = '<div class="text-body-secondary small mt-1">Placeholder values support transforms, for example <code>{{title.upper()}}</code>, <code>{{title.title()}}</code>, <code>{{title.lower()}}</code>, <code>{{publishedAt.format("MMM D, YYYY")}}</code>.</div>';
if (!overflowFields.length) {
return visibleMarkup;
return visibleMarkup + transformHint;
}
return '' +
visibleMarkup +
'<details class="w-100 mt-2" data-placeholder-chips-more>' +
transformHint +
'<details class="w-100 mt-1" data-placeholder-chips-more>' +
'<summary class="small text-body-secondary">Show ' + escapeHtml(overflowFields.length) + ' more fields</summary>' +
'<div class="d-flex flex-wrap gap-2 mt-2">' + overflowFields.map(function (field) {
'<div class="d-flex flex-wrap gap-2 mt-1">' + overflowFields.map(function (field) {
return typeof placeholderChips.renderChip === 'function'
? placeholderChips.renderChip(field)
: '<span class="chip">{{' + escapeHtml(field) + '}}</span>';
@@ -212,6 +220,43 @@ export function createSlideFormRegionHelpers(options) {
container.innerHTML = buildLimitedPlaceholderChipMarkup(getRssFieldList(feedId), 'No RSS fields available.');
}
function updateRssItemNumberLimit(regionId, feedId) {
var card = templateFields ? templateFields.querySelector('[data-region-id="' + regionId + '"]') : null;
if (!card) {
return;
}
var input = card.querySelector('input[name="region_rss_item_number_' + regionId + '"]');
if (!input) {
return;
}
var itemCount = Math.max(1, Number(getRssFeedItemCount(feedId) || 1));
input.setAttribute('max', String(itemCount));
if (Number(input.value || 0) > itemCount) {
input.value = String(itemCount);
}
}
function clampRssItemNumber(regionId, feedId, itemNumber) {
var card = templateFields ? templateFields.querySelector('[data-region-id="' + regionId + '"]') : null;
if (!card) {
return '';
}
var input = card.querySelector('input[name="region_rss_item_number_' + regionId + '"]');
if (!input) {
return '';
}
var itemCount = Math.max(1, Number(getRssFeedItemCount(feedId) || 1));
var parsedValue = Math.max(1, Number(itemNumber || 1));
var clampedValue = Math.min(itemCount, Number.isFinite(parsedValue) && parsedValue > 0 ? parsedValue : 1);
input.setAttribute('max', String(itemCount));
input.value = String(clampedValue);
return String(clampedValue);
}
function getCurrentRssConfig(region) {
var module = getRegionTypeModule('rss');
if (module && typeof module.getCurrentConfig === 'function') {
@@ -568,6 +613,50 @@ export function createSlideFormRegionHelpers(options) {
return makeRegionCardCollapsible(module.renderEditorCard(buildRegionEditorCardContext(region)), region);
}
function bindRegionCards() {
if (!templateFields) {
return;
}
Array.prototype.forEach.call(templateFields.querySelectorAll('[data-region-id]'), function (card) {
var module = null;
if (!card || !card.querySelector || !card.querySelector('input[type="url"][name^="region_qr_code_"]')) {
return;
}
module = getRegionTypeModule('qr-code');
if (module && typeof module.bindEditorCard === 'function') {
module.bindEditorCard({
card: card,
region: { id: card.getAttribute('data-region-id') },
existingContent: existingContent,
requestPreviewRender: requestPreviewRender
});
}
});
}
function syncRegionCards() {
if (!templateFields) {
return Promise.resolve();
}
var syncs = [];
Array.prototype.forEach.call(templateFields.querySelectorAll('[data-region-id]'), function (card) {
if (!card || !card.querySelector || !card.querySelector('input[type="url"][name^="region_qr_code_"]')) {
return;
}
if (typeof card.__pulseQrSync === 'function') {
syncs.push(Promise.resolve(card.__pulseQrSync()));
}
});
return Promise.all(syncs);
}
function makeRegionCardCollapsible(html, region) {
if (typeof html !== 'string' || !html) {
return html;
@@ -666,7 +755,6 @@ export function createSlideFormRegionHelpers(options) {
var videoFileInput = card.querySelector('input[type="file"][name="region_video_' + region.id + '"]');
var webpageInput = card.querySelector('input[type="url"][name="region_webpage_' + region.id + '"]');
var rtmpInput = card.querySelector('input[type="url"][name="region_rtmp_' + region.id + '"]');
var disableAudioInput = card.querySelector('input[type="checkbox"][name="region_disable_audio_' + region.id + '"]');
var rssFeedInput = card.querySelector('select[name="region_rss_feed_id_' + region.id + '"]');
var rssItemInput = card.querySelector('input[name="region_rss_item_number_' + region.id + '"]');
var apiSourceInput = card.querySelector('select[name="region_api_source_id_' + region.id + '"]');
@@ -681,7 +769,7 @@ export function createSlideFormRegionHelpers(options) {
content.value = webpageInput ? webpageInput.value : (content.value || '');
} else if (region.region_type === 'rtmp') {
content.value = rtmpInput ? rtmpInput.value : (content.value || '');
content.disable_audio = disableAudioInput ? disableAudioInput.checked : (content.disable_audio === undefined ? true : Boolean(content.disable_audio));
content.disable_audio = false;
} else if (region.region_type === 'html') {
content.value = htmlInput ? htmlInput.value : (content.value || '');
} else if (region.region_type === 'time-date') {
@@ -691,7 +779,7 @@ export function createSlideFormRegionHelpers(options) {
} else if (region.region_type === 'rss') {
content.value = hiddenInput ? hiddenInput.value : (content.value || '');
content.feed_id = rssFeedInput ? rssFeedInput.value : content.feed_id;
content.item_number = rssItemInput ? rssItemInput.value : content.item_number;
content.item_number = rssItemInput ? clampRssItemNumber(region.id, content.feed_id, rssItemInput.value) : content.item_number;
} else if (region.region_type === 'api') {
content.value = hiddenInput ? hiddenInput.value : (content.value || '');
content.source_id = apiSourceInput ? apiSourceInput.value : content.source_id;
@@ -754,11 +842,14 @@ export function createSlideFormRegionHelpers(options) {
updateApiPlaceholderChips: updateApiPlaceholderChips,
updateApiSampleDataPanel: updateApiSampleDataPanel,
updateApiItemNumberLimit: updateApiItemNumberLimit,
updateRssItemNumberLimit: updateRssItemNumberLimit,
getCurrentApiConfig: getCurrentApiConfig,
reduceAspectRatio: reduceAspectRatio,
renderPreviewTextRegion: renderPreviewTextRegion,
startPreviewVideoPlayback: startPreviewVideoPlayback,
getRegionEditorCardHtml: getRegionEditorCardHtml,
bindRegionCards: bindRegionCards,
syncRegionCards: syncRegionCards,
buildRegionEditorCardContext: buildRegionEditorCardContext,
getPreviewRegionContent: getPreviewRegionContent,
buildPreviewRenderContext: buildPreviewRenderContext,
+96 -19
View File
@@ -114,7 +114,7 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
requestPreviewRender: requestPreviewRender
});
var regionUtils = window.pulseRegionUtils || {};
var slideRegionHelpers = createSlideFormRegionHelpers({
var slideRegionHelperOptions = {
templateFields: templateFields,
existingContent: existingContent,
rssFeeds: rssFeeds,
@@ -124,8 +124,10 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
uploadMaxLabel: uploadMaxLabel,
uploadVideoMaxLabel: uploadVideoMaxLabel,
escapeHtml: escapeHtml,
getRegionTypeModule: getRegionTypeModule
});
getRegionTypeModule: getRegionTypeModule,
requestPreviewRender: requestPreviewRender
};
var slideRegionHelpers = createSlideFormRegionHelpers(slideRegionHelperOptions);
var slidePreviewHelpers = createSlideFormPreviewHelpers({
getRegionTypeModule: getRegionTypeModule,
escapeHtml: escapeHtml
@@ -139,6 +141,8 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
var renderPreviewTextRegion = slidePreviewHelpers.renderPreviewTextRegion;
var buildRegionEditorCardContext = slideRegionHelpers.buildRegionEditorCardContext;
var getRegionEditorCardHtml = slideRegionHelpers.getRegionEditorCardHtml;
var bindRegionCards = slideRegionHelpers.bindRegionCards;
var syncRegionCards = slideRegionHelpers.syncRegionCards;
var getPreviewRegionContent = slideRegionHelpers.getPreviewRegionContent;
var buildPreviewRenderContext = slideRegionHelpers.buildPreviewRenderContext;
var startPreviewVideoPlayback = slidePreviewHelpers.startPreviewVideoPlayback;
@@ -147,6 +151,28 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
return templates.find(function (item) { return Number(item.id) === Number(templateSelect.value); }) || null;
}
function hasMeaningfulValue(value) {
if (value === null || value === undefined) {
return false;
}
if (Array.isArray(value)) {
return value.some(hasMeaningfulValue);
}
if (typeof value === 'object') {
return Object.keys(value).some(function (key) {
return hasMeaningfulValue(value[key]);
});
}
return String(value).trim() !== '';
}
function hasExistingSlideContent() {
return hasMeaningfulValue(existingContent);
}
function clearImagePreviewUrls() {
templateFields.querySelectorAll('input[type="file"][name^="region_image_"], input[type="file"][name^="region_video_"]').forEach(function (input) {
if (input.dataset.previewUrl) {
@@ -170,6 +196,10 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
return String(card.dataset.regionMediaType || '').trim();
}
if (card.querySelector && card.querySelector('input[type="file"][name^="region_qr_image_"], input[type="url"][name^="region_qr_code_"]')) {
return 'qr-code';
}
var regionTypeInput = card.querySelector ? card.querySelector('input[type="hidden"][name="region_type[]"]') : null;
return String(regionTypeInput && regionTypeInput.value || '').trim();
}
@@ -192,6 +222,7 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
return syncVideoRegionDuration(card, source);
},
markEdited: function () {
templateSelectorLock.arm();
templateSelectorLock.markEdited();
requestPreviewRender();
},
@@ -201,7 +232,7 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
}) : null;
function buildRegionMediaHookContext(input, file) {
var regionId = input && input.name ? input.name.replace(/^region_(?:image|video)_/, '') : '';
var regionId = input && input.name ? input.name.replace(/^region_(?:image|video|qr_image)_/, '') : '';
var card = regionId ? templateFields.querySelector('[data-region-id="' + regionId + '"]') : null;
return {
@@ -220,7 +251,7 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
}
function handleRegionMediaFileSelection(input, file) {
var card = input && input.name ? templateFields.querySelector('[data-region-id="' + input.name.replace(/^region_(?:image|video)_/, '') + '"]') : null;
var card = input && input.name ? templateFields.querySelector('[data-region-id="' + input.name.replace(/^region_(?:image|video|qr_image)_/, '') + '"]') : null;
var module = getRegionEditorModule(card);
var hookContext = buildRegionMediaHookContext(input, file);
@@ -241,14 +272,19 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
return;
}
var mediaType = card && card.dataset && String(card.dataset.regionMediaType || '').trim() === 'video' ? 'video' : 'image';
var mediaType = card && card.dataset && String(card.dataset.regionMediaType || '').trim() === 'video'
? 'video'
: card && card.querySelector && card.querySelector('input[type="file"][name^="region_qr_image_"]')
? 'qr-image'
: 'image';
var isVideo = mediaType === 'video';
var isQrImage = mediaType === 'qr-image';
previewBox.innerHTML = value
? '<div class="slide-image-region-preview-shell" data-remove-' + (isVideo ? 'region-video' : 'region-image') + '="' + escapeHtml(card.getAttribute('data-region-id') || '') + '" role="button" tabindex="0" aria-label="Remove ' + (isVideo ? 'video' : 'image') + '">' +
? '<div class="slide-image-region-preview-shell" data-remove-' + (isVideo ? 'region-video' : isQrImage ? 'region-qr-image' : 'region-image') + '="' + escapeHtml(card.getAttribute('data-region-id') || '') + '" role="button" tabindex="0" aria-label="Remove ' + (isVideo ? 'video' : isQrImage ? 'QR image' : 'image') + '">' +
(isVideo
? '<video class="slide-image-region-preview" src="' + escapeHtml(value) + '" autoplay loop muted playsinline preload="metadata"></video>'
: '<img class="slide-image-region-preview" src="' + escapeHtml(value) + '" alt="Current image preview" />') +
: '<img class="slide-image-region-preview" src="' + escapeHtml(value) + '" alt="' + (isQrImage ? 'Current QR image preview' : 'Current image preview') + '" />') +
'<span class="slide-image-region-preview-remove" aria-hidden="true"><i class="bi bi-trash3" aria-hidden="true"></i></span>' +
'</div>'
: '<div class="slide-image-region-preview slide-image-region-preview-empty">No ' + (isVideo ? 'video' : 'image') + '</div>';
@@ -389,15 +425,15 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
}
function getRegionImageInputs() {
return Array.prototype.slice.call(templateFields.querySelectorAll('input[type="file"][name^="region_image_"], input[type="file"][name^="region_video_"]'));
return Array.prototype.slice.call(templateFields.querySelectorAll('input[type="file"][name^="region_image_"], input[type="file"][name^="region_video_"], input[type="file"][name^="region_qr_image_"]'));
}
function getRegionMediaInputs() {
return getRegionImageInputs();
return Array.prototype.slice.call(templateFields.querySelectorAll('input[type="file"][name^="region_image_"], input[type="file"][name^="region_video_"], input[type="file"][name^="region_qr_image_"]'));
}
function hasPendingRegionImageUpload() {
return getRegionImageInputs().some(function (input) {
return getRegionMediaInputs().some(function (input) {
return Boolean(input && input.files && input.files.length);
});
}
@@ -448,6 +484,14 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
return;
}
try {
if (previewPopupWindow.location && previewPopupWindow.location.pathname !== '/slides/popup-preview') {
return;
}
} catch (_error) {
return;
}
previewPopupWindow.location.hash = buildPreviewPopupHash();
}
@@ -471,13 +515,18 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
'top=' + top
].join(',');
previewPopupWindow = window.open(buildPreviewPopupUrl(), 'slide-preview-popup', previewPopupFeatures);
previewPopupWindow = window.open('about:blank', 'slide-preview-popup', previewPopupFeatures);
if (!previewPopupWindow) {
return;
}
try {
previewPopupWindow.location.replace(buildPreviewPopupUrl());
} catch (_error) {
previewPopupWindow.location.href = buildPreviewPopupUrl();
}
previewPopupWindow.focus();
syncPopupPreview();
}
function syncSlideEditorSidebar() {
@@ -632,6 +681,7 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
var updateApiSampleDataPanel = slideRegionHelpers.updateApiSampleDataPanel;
var updateApiItemNumberLimit = slideRegionHelpers.updateApiItemNumberLimit;
var getCurrentApiConfig = slideRegionHelpers.getCurrentApiConfig;
var updateRssItemNumberLimit = slideRegionHelpers.updateRssItemNumberLimit;
function renderTemplate() {
templateSelectorLock.reset();
@@ -663,6 +713,9 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
});
slideFormEditorController.renderEditors();
window.requestAnimationFrame(function () {
bindRegionCards();
});
templateFields.querySelectorAll('input[name^="region_api_item_number_"]').forEach(function (input) {
var regionId = input.name.replace(/^region_api_item_number_/, '');
var sourceInput = templateFields.querySelector('select[name="region_api_source_id_' + regionId + '"]');
@@ -671,19 +724,42 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
updateApiItemNumberLimit(regionId, sourceInput.value, pathInput ? pathInput.value : '');
}
});
templateFields.querySelectorAll('input[name^="region_rss_item_number_"]').forEach(function (input) {
var regionId = input.name.replace(/^region_rss_item_number_/, '');
var feedInput = templateFields.querySelector('select[name="region_rss_feed_id_' + regionId + '"]');
if (feedInput) {
updateRssItemNumberLimit(regionId, feedInput.value);
}
});
if (typeof regionUtils.bindRegionMediaRemoveControls === 'function') {
regionUtils.bindRegionMediaRemoveControls(templateFields, {
getCardByRegionId: function (regionId) {
return templateFields.querySelector('[data-region-id="' + regionId + '"]');
},
getMediaType: function (card) {
getMediaType: function (card, button) {
if (button && button.hasAttribute && button.hasAttribute('data-remove-region-qr-image')) {
return 'qr-image';
}
if (button && button.hasAttribute && button.hasAttribute('data-remove-region-video')) {
return 'video';
}
return card && card.dataset && String(card.dataset.regionMediaType || '').trim() === 'video' ? 'video' : 'image';
},
getExistingMediaPrefix: function (mediaType) {
if (String(mediaType || '').trim() === 'qr-image') {
return 'existing_region_qr_image_';
}
return String(mediaType || '').trim() === 'video' ? 'existing_region_video_' : 'existing_region_image_';
},
getMediaPrefix: function (mediaType) {
if (String(mediaType || '').trim() === 'qr-image') {
return 'region_qr_image_';
}
return String(mediaType || '').trim() === 'video' ? 'region_video_' : 'region_image_';
},
getVideoDurationHiddenInput: function (regionId) {
@@ -711,6 +787,7 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
if (input.name.indexOf('region_rss_') === 0) {
var rssFeed = input.name.indexOf('region_rss_feed_id_') === 0 ? input.value : (templateFields.querySelector('select[name="region_rss_feed_id_' + regionId + '"]') || {}).value;
updateRssPlaceholderChips(regionId, rssFeed);
updateRssItemNumberLimit(regionId, rssFeed);
}
if (input.name.indexOf('region_api_') === 0) {
var apiSource = input.name.indexOf('region_api_source_id_') === 0 ? input.value : (templateFields.querySelector('select[name="region_api_source_id_' + regionId + '"]') || {}).value;
@@ -728,6 +805,7 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
if (input.name.indexOf('region_rss_') === 0) {
var rssFeed = input.name.indexOf('region_rss_feed_id_') === 0 ? input.value : (templateFields.querySelector('select[name="region_rss_feed_id_' + regionId + '"]') || {}).value;
updateRssPlaceholderChips(regionId, rssFeed);
updateRssItemNumberLimit(regionId, rssFeed);
}
if (input.name.indexOf('region_api_') === 0) {
var apiSource = input.name.indexOf('region_api_source_id_') === 0 ? input.value : (templateFields.querySelector('select[name="region_api_source_id_' + regionId + '"]') || {}).value;
@@ -742,16 +820,12 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
});
});
if (existingTemplateId) {
if (existingTemplateId && hasExistingSlideContent()) {
templateSelectorLock.arm();
templateSelectorLock.markEdited();
requestPreviewRender();
return;
}
window.requestAnimationFrame(function () {
templateSelectorLock.arm();
});
requestPreviewRender();
}
@@ -766,6 +840,7 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
throw new Error('Wait for the image upload to finish before saving.');
}
await slideFormEditorController.syncEditors();
await syncRegionCards();
},
fallbackSuccessMessage: 'Saved slide.',
afterSuccess: function () {
@@ -792,10 +867,12 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
templateSelect.addEventListener('change', renderTemplate);
templateFields.addEventListener('change', function () {
templateSelectorLock.arm();
templateSelectorLock.markEdited();
requestPreviewRender();
});
templateFields.addEventListener('input', function () {
templateSelectorLock.arm();
templateSelectorLock.markEdited();
requestPreviewRender();
});