(function () { var dataElement = document.getElementById('template-editor-data'); if (!dataElement) { return; } var utils = window.templateDesignerUtils || {}; var templateData = {}; try { templateData = JSON.parse(dataElement.getAttribute('data-json') || dataElement.textContent || '{}') || {}; } catch (_error) { templateData = {}; } var existingRegions = Array.isArray(templateData.regions) ? templateData.regions : (Array.isArray(templateData) ? templateData : []); var stage = document.getElementById('designer-stage'); var overlay = document.getElementById('designer-overlay'); var regionList = document.getElementById('region-list'); var regionSelect = document.getElementById('region-select'); var canvasSizeSelect = document.getElementById('canvas-size-select'); var canvasSizeIdInput = document.getElementById('canvas-size-id'); var canvasSizeSummary = document.getElementById('canvas-size-summary'); var canvasWidthInput = document.getElementById('canvas-width'); var canvasHeightInput = document.getElementById('canvas-height'); var backgroundInput = document.getElementById('background-image'); var backgroundColorInput = document.getElementById('background-color'); var backgroundPreview = document.getElementById('background-preview'); var backgroundEmpty = document.getElementById('background-empty'); var removeBackgroundButton = document.getElementById('remove-background-image'); var removeBackgroundFlag = document.getElementById('remove-background-image-flag'); var addRegionButton = document.getElementById('add-region-button'); var regionAddModal = document.getElementById('region-add-modal'); var regionCardTemplate = document.getElementById('region-card-template'); var regionsJsonInput = document.getElementById('regions-json'); var templateForm = document.getElementById('template-form'); var draft = null; var selectedIndex = -1; var overlayRenderFrame = 0; function escapeHtml(value) { return utils.escapeHtml ? utils.escapeHtml(value) : String(value === undefined || value === null ? '' : value); } function valueOrDefault(value, fallback) { return utils.valueOrDefault ? utils.valueOrDefault(value, fallback) : (value === undefined || value === null || value === '' ? fallback : value); } function getCanvasSize() { return { width: Math.max(1, Number(canvasWidthInput.value || 1920)), height: Math.max(1, Number(canvasHeightInput.value || 1080)) }; } function clamp(value, min, max) { return utils.clamp ? utils.clamp(value, min, max) : Math.max(min, Math.min(max, value)); } function normalizeLockRatio(value) { return utils.normalizeLockRatio ? utils.normalizeLockRatio(value) : String(value || '').trim().replace(/\s+/g, ''); } function parseLockRatio(value) { if (utils.parseLockRatio) { return utils.parseLockRatio(value); } var normalized = normalizeLockRatio(value); if (!normalized || !/^\d+:\d+$/.test(normalized)) { return null; } var parts = normalized.split(':'); var width = Number(parts[0]); var height = Number(parts[1]); if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) { return null; } return { label: normalized, ratio: width / height }; } function getDefaultRegionSize(regionType, lockRatio) { if (utils.getDefaultRegionSize) { return utils.getDefaultRegionSize(regionType, lockRatio); } var ratio = parseLockRatio(lockRatio); var locked = regionType === 'image' || regionType === 'webpage' || regionType === 'html' || regionType === 'rtmp' || regionType === 'rss'; if (ratio) { if (ratio.ratio >= 1) { var baseWidth = locked ? 420 : 300; return { width: Math.max(12, Math.round(baseWidth)), height: Math.max(12, Math.round(baseWidth / ratio.ratio)) }; } var baseHeight = locked ? 300 : 240; return { width: Math.max(12, Math.round(baseHeight * ratio.ratio)), height: Math.max(12, Math.round(baseHeight)) }; } return { width: locked ? 420 : 300, height: locked ? 240 : 120 }; } function getCards() { return Array.prototype.slice.call(regionList.querySelectorAll('.region-item')); } function cardAt(index) { return getCards()[index] || null; } function getRegionName(card) { return utils.getRegionName ? utils.getRegionName(card) : String(card.querySelector('[name="region_name[]"]').value || '').trim(); } function syncRegionIdentity(card, value) { if (utils.syncRegionIdentity) { utils.syncRegionIdentity(card, value); return; } var next = String(value || '').trim(); card.querySelector('[name="region_name[]"]').value = next; card.querySelector('[name="region_key[]"]').value = next; card.querySelector('[name="region_label[]"]').value = next; } function validateRegionNames() { var cards = getCards(); var names = {}; var hasDuplicate = false; cards.forEach(function (card) { var input = card.querySelector('[name="region_name[]"]'); if (!input) { return; } var normalized = String(input.value || '').trim().toLowerCase(); if (!normalized) { input.setCustomValidity('Region name is required.'); return; } if (!names[normalized]) { names[normalized] = []; } names[normalized].push(input); }); Object.keys(names).forEach(function (key) { var inputs = names[key]; if (inputs.length > 1) { hasDuplicate = true; inputs.forEach(function (input) { input.setCustomValidity('Region names must be unique on this template.'); }); } else { inputs[0].setCustomValidity(''); } }); return !hasDuplicate; } function readCard(card) { return utils.readCard ? utils.readCard(card) : { region_key: getRegionName(card), label: getRegionName(card), region_type: card.querySelector('[name="region_type[]"]').value, font_family: card.querySelector('[name="font_family[]"]').value, lock_ratio: normalizeLockRatio(card.querySelector('[name="region_lock_ratio[]"]').value), x: Number(card.querySelector('[name="region_x[]"]').value || 0), y: Number(card.querySelector('[name="region_y[]"]').value || 0), width: Number(card.querySelector('[name="region_width[]"]').value || 0), height: Number(card.querySelector('[name="region_height[]"]').value || 0), z_index: Number(card.querySelector('[name="region_z[]"]').value || 0) }; } function writeCard(card, values) { if (utils.writeCard) { utils.writeCard(card, values); return; } if (values.region_name !== undefined) { syncRegionIdentity(card, values.region_name); } else if (values.region_key !== undefined) { syncRegionIdentity(card, values.region_key); } else if (values.label !== undefined) { syncRegionIdentity(card, values.label); } if (values.region_type !== undefined) { card.querySelector('[name="region_type[]"]').value = values.region_type; } if (values.font_family !== undefined) { card.querySelector('[name="font_family[]"]').value = values.font_family; } if (values.lock_ratio !== undefined) { card.querySelector('[name="region_lock_ratio[]"]').value = normalizeLockRatio(values.lock_ratio); } if (values.x !== undefined) { card.querySelector('[name="region_x[]"]').value = Math.round(values.x); } if (values.y !== undefined) { card.querySelector('[name="region_y[]"]').value = Math.round(values.y); } if (values.width !== undefined) { card.querySelector('[name="region_width[]"]').value = Math.round(values.width); } if (values.height !== undefined) { card.querySelector('[name="region_height[]"]').value = Math.round(values.height); } if (values.z_index !== undefined) { card.querySelector('[name="region_z[]"]').value = Math.round(values.z_index); } } function getOverlayRect() { return utils.getOverlayRect ? utils.getOverlayRect(overlay) : overlay.getBoundingClientRect(); } function toCanvasPoint(event) { return utils.toCanvasPoint ? utils.toCanvasPoint(event, overlay, getCanvasSize()) : { x: 0, y: 0 }; } function canvasRectToPixels(region) { return utils.canvasRectToPixels ? utils.canvasRectToPixels(region, overlay, getCanvasSize()) : { left: 0, top: 0, width: 0, height: 0 }; } function updateAspectRatio() { var size = getCanvasSize(); stage.style.aspectRatio = size.width + ' / ' + size.height; } function updateCanvasSizeSummary() { var option = canvasSizeSelect.options[canvasSizeSelect.selectedIndex]; canvasSizeSummary.textContent = option ? option.textContent : ''; } function updateCanvasSizeLock() { var lockOnExistingTemplate = canvasSizeSelect.dataset.lockOnExistingTemplate === 'true'; var locked = lockOnExistingTemplate && getCards().length > 0; canvasSizeSelect.disabled = locked; canvasSizeSummary.classList.toggle('is-locked', locked); } function syncCanvasSizeSelection() { var option = canvasSizeSelect.options[canvasSizeSelect.selectedIndex]; if (!option) { return; } if (canvasSizeIdInput) { canvasSizeIdInput.value = option.value; } canvasWidthInput.value = Math.max(1, Number(option.dataset.width || canvasWidthInput.value || 1920)); canvasHeightInput.value = Math.max(1, Number(option.dataset.height || canvasHeightInput.value || 1080)); updateAspectRatio(); updateCanvasSizeSummary(); } function updateBackgroundPreview(file) { if (!file) { return; } if (removeBackgroundFlag) { removeBackgroundFlag.checked = false; } var reader = new FileReader(); reader.onload = function () { backgroundPreview.src = reader.result; backgroundPreview.style.display = 'block'; backgroundEmpty.style.display = 'none'; }; reader.readAsDataURL(file); } function updateStageBackgroundColor() { if (!stage) { return; } stage.style.backgroundColor = backgroundColorInput && backgroundColorInput.value ? backgroundColorInput.value : '#111111'; } function updateRegionLockBadge(card) { var lockChip = card.querySelector('[data-region-lock-chip]'); if (!lockChip) { return; } var lockRatio = normalizeLockRatio(card.querySelector('[name="region_lock_ratio[]"]').value); if (!lockRatio) { lockChip.hidden = true; lockChip.textContent = ''; return; } lockChip.hidden = false; lockChip.textContent = 'Locked ' + lockRatio; } function getRegionLockRatio(card) { return normalizeLockRatio(card.querySelector('[name="region_lock_ratio[]"]').value); } function isRegionLocked(card) { return Boolean(getRegionLockRatio(card)); } function syncLockedDimensions(card, changedField) { var lockRatio = getRegionLockRatio(card); var aspect = lockRatio ? parseLockRatio(lockRatio) : null; if (!aspect) { return; } var widthInput = card.querySelector('[name="region_width[]"]'); var heightInput = card.querySelector('[name="region_height[]"]'); var width = Math.max(1, Number(widthInput.value || 0)); var height = Math.max(1, Number(heightInput.value || 0)); if (changedField === 'width') { heightInput.value = Math.max(1, Math.round(width / aspect.ratio)); } else if (changedField === 'height') { widthInput.value = Math.max(1, Math.round(height * aspect.ratio)); } } function getRegionChipLabel(regionType) { return regionType === 'image' ? 'Image' : regionType === 'video' ? 'Video' : regionType === 'webpage' ? 'Webpage' : regionType === 'html' ? 'HTML' : regionType === 'rtmp' ? 'RTMP' : regionType === 'rss' ? 'RSS' : 'Text'; } function populateRegionCard(card, region) { var chip = card.querySelector('[data-region-chip]'); var title = card.querySelector('[data-region-title]'); var nameInput = card.querySelector('[name="region_name[]"]'); var fontFamilyInput = card.querySelector('[name="font_family[]"]'); var regionTypeInput = card.querySelector('[name="region_type[]"]'); var regionKeyInput = card.querySelector('[name="region_key[]"]'); var regionLabelInput = card.querySelector('[name="region_label[]"]'); if (title) { title.textContent = region.label || region.region_key || 'Region'; } if (chip) { chip.textContent = getRegionChipLabel(region.region_type); } if (nameInput) { nameInput.value = region.region_key || region.label || ''; } if (fontFamilyInput) { fontFamilyInput.value = region.region_type === 'image' || region.region_type === 'video' || region.region_type === 'rtmp' ? '' : (region.font_family || 'Arial'); } if (regionTypeInput) { regionTypeInput.value = region.region_type || 'text'; } if (regionKeyInput) { regionKeyInput.value = region.region_key || region.label || ''; } if (regionLabelInput) { regionLabelInput.value = region.label || region.region_key || ''; } var regionLockRatioInput = card.querySelector('[name="region_lock_ratio[]"]'); if (regionLockRatioInput) { regionLockRatioInput.value = normalizeLockRatio(region.lock_ratio); } card.querySelector('[name="region_x[]"]').value = valueOrDefault(region.x, 80); card.querySelector('[name="region_y[]"]').value = valueOrDefault(region.y, 80); card.querySelector('[name="region_z[]"]').value = valueOrDefault(region.z_index, 1); card.querySelector('[name="region_width[]"]').value = valueOrDefault(region.width, 300); card.querySelector('[name="region_height[]"]').value = valueOrDefault(region.height, 120); updateRegionLockBadge(card); } function updateRegionLabel(card) { var label = getRegionName(card) || 'Region'; var cards = getCards(); var index = cards.indexOf(card); var title = card.querySelector('.template-field-head strong'); if (title) { title.textContent = label; } if (index >= 0 && regionSelect.options[index]) { regionSelect.options[index].textContent = label; } } function makeRegionCard(region) { var card; if (regionCardTemplate && regionCardTemplate.content) { card = regionCardTemplate.content.firstElementChild.cloneNode(true); } else { card = document.createElement('div'); card.className = 'card card-outline card-secondary admin-form-card region-item mb-3'; } populateRegionCard(card, region); var nameInput = card.querySelector('[name="region_name[]"]'); var lockRatioInput = card.querySelector('[name="region_lock_ratio[]"]'); var widthInput = card.querySelector('[name="region_width[]"]'); var heightInput = card.querySelector('[name="region_height[]"]'); nameInput.addEventListener('input', function () { syncRegionIdentity(card, nameInput.value); updateRegionLabel(card); validateRegionNames(); renderRegionSidebar(); renderOverlay(); }); if (lockRatioInput) { lockRatioInput.addEventListener('input', function () { updateRegionLockBadge(card); requestOverlayRender(); }); } if (widthInput) { widthInput.addEventListener('input', function () { if (isRegionLocked(card)) { syncLockedDimensions(card, 'width'); updateRegionLockBadge(card); } requestOverlayRender(); }); } if (heightInput) { heightInput.addEventListener('input', function () { if (isRegionLocked(card)) { syncLockedDimensions(card, 'height'); updateRegionLockBadge(card); } requestOverlayRender(); }); } card.addEventListener('click', function (event) { if (event.target && event.target.classList && event.target.classList.contains('remove-region')) { return; } setSelected(getCards().indexOf(card)); }); card.querySelector('.remove-region').addEventListener('click', function (event) { event.preventDefault(); card.remove(); if (!getCards().length) { selectedIndex = -1; } else if (selectedIndex >= getCards().length) { selectedIndex = getCards().length - 1; } renderRegionSidebar(); renderOverlay(); }); return card; } function renderRegionList(initialRegions) { regionList.innerHTML = ''; initialRegions.forEach(function (region) { regionList.appendChild(makeRegionCard(region)); }); } function renderRegionSidebar() { var cards = getCards(); regionSelect.innerHTML = ''; if (!cards.length) { regionSelect.disabled = true; regionList.innerHTML = ''; updateCanvasSizeLock(); return; } regionSelect.disabled = false; if (selectedIndex < 0 || selectedIndex >= cards.length) { selectedIndex = 0; } cards.forEach(function (card, index) { var option = document.createElement('option'); option.value = String(index); option.textContent = getRegionName(card) || ('Region ' + (index + 1)); if (index === selectedIndex) { option.selected = true; } regionSelect.appendChild(option); card.hidden = index !== selectedIndex; }); regionSelect.value = String(selectedIndex); updateCanvasSizeLock(); validateRegionNames(); } function renderOverlay() { var cards = getCards(); var selectedCard = selectedIndex >= 0 ? cards[selectedIndex] : null; var selectedNow = selectedCard ? cards.indexOf(selectedCard) : -1; var regions = cards.map(readCard); regionsJsonInput.value = JSON.stringify(regions); overlay.innerHTML = regions.map(function (region, index) { var box = canvasRectToPixels(region); var selected = index === selectedNow ? ' selected' : ''; return '
' + escapeHtml(region.label || region.region_key || 'Region') + '
'; }).join(''); if (draft) { var rect = getOverlayRect(); var size = getCanvasSize(); var draftBox = { x: Math.min(draft.start.x, draft.end.x), y: Math.min(draft.start.y, draft.end.y), width: Math.abs(draft.end.x - draft.start.x), height: Math.abs(draft.end.y - draft.start.y) }; overlay.innerHTML += '
'; } } function requestOverlayRender() { if (overlayRenderFrame) { return; } overlayRenderFrame = window.requestAnimationFrame(function () { overlayRenderFrame = 0; renderOverlay(); }); } function render() { updateAspectRatio(); renderRegionSidebar(); renderOverlay(); } function setSelected(index) { var cards = getCards(); if (!cards.length) { selectedIndex = -1; } else if (index < 0) { selectedIndex = 0; } else { selectedIndex = clamp(index, 0, cards.length - 1); } renderRegionSidebar(); renderOverlay(); } function addRegion(region) { var hint = regionList.querySelector('.muted'); if (hint) { hint.remove(); } regionList.appendChild(makeRegionCard(region)); setSelected(getCards().length - 1); } function openAddRegionModal() { if (!window.pulseModal) { return; } window.pulseModal.show(regionAddModal); } function createDefaultRegion(type) { var count = getCards().length + 1; var name = 'region_' + count; var size = getDefaultRegionSize(type, ''); return { region_key: name, label: name, region_type: type, font_family: type === 'text' || type === 'html' || type === 'rss' || type === 'api' ? 'Arial' : '', x: 80, y: 80, width: size.width, height: size.height, lock_ratio: '', z_index: 1 }; } function clampRegion(region) { var size = getCanvasSize(); var minSize = 12; var x = clamp(region.x, 0, size.width - minSize); var y = clamp(region.y, 0, size.height - minSize); var width = Math.max(minSize, region.width); var height = Math.max(minSize, region.height); if (x + width > size.width) { width = size.width - x; } if (y + height > size.height) { height = size.height - y; } return { x: Math.round(x), y: Math.round(y), width: Math.round(Math.max(minSize, width)), height: Math.round(Math.max(minSize, height)) }; } function startDraw(event) { var start = toCanvasPoint(event); draft = { start: start, end: start }; renderOverlay(); function moveHandler(moveEvent) { draft.end = toCanvasPoint(moveEvent); requestOverlayRender(); } function upHandler(upEvent) { draft.end = toCanvasPoint(upEvent); var width = Math.abs(draft.end.x - draft.start.x); var height = Math.abs(draft.end.y - draft.start.y); if (width >= 8 && height >= 8) { var region = clampRegion({ x: Math.min(draft.start.x, draft.end.x), y: Math.min(draft.start.y, draft.end.y), width: width, height: height }); addRegion({ region_key: 'region_' + (getCards().length + 1), label: 'Region ' + (getCards().length + 1), region_type: 'text', x: region.x, y: region.y, width: region.width, height: region.height, z_index: 1 }); } draft = null; requestOverlayRender(); document.removeEventListener('mousemove', moveHandler); document.removeEventListener('mouseup', upHandler); } document.addEventListener('mousemove', moveHandler); document.addEventListener('mouseup', upHandler); } function startMove(index, event) { var startPoint = toCanvasPoint(event); var startRegion = readCard(cardAt(index)); function moveHandler(moveEvent) { var currentPoint = toCanvasPoint(moveEvent); var dx = currentPoint.x - startPoint.x; var dy = currentPoint.y - startPoint.y; var next = clampRegion({ x: startRegion.x + dx, y: startRegion.y + dy, width: startRegion.width, height: startRegion.height }); writeCard(cardAt(index), { x: next.x, y: next.y }); requestOverlayRender(); } function upHandler() { document.removeEventListener('mousemove', moveHandler); document.removeEventListener('mouseup', upHandler); } document.addEventListener('mousemove', moveHandler); document.addEventListener('mouseup', upHandler); } function resizeFromHandle(index, dir, event) { var startPoint = toCanvasPoint(event); var startRegion = readCard(cardAt(index)); var lockRatio = normalizeLockRatio(startRegion.lock_ratio); var aspect = lockRatio ? parseLockRatio(lockRatio) : null; function fitFromWidth(width) { var nextWidth = Math.max(12, Math.round(width)); return { width: nextWidth, height: aspect ? Math.max(12, Math.round(nextWidth / aspect.ratio)) : startRegion.height }; } function fitFromHeight(height) { var nextHeight = Math.max(12, Math.round(height)); return { width: aspect ? Math.max(12, Math.round(nextHeight * aspect.ratio)) : startRegion.width, height: nextHeight }; } function moveHandler(moveEvent) { var currentPoint = toCanvasPoint(moveEvent); var dx = currentPoint.x - startPoint.x; var dy = currentPoint.y - startPoint.y; var next = { x: startRegion.x, y: startRegion.y, width: startRegion.width, height: startRegion.height }; if (aspect) { if (dir === 'e') { var eastSize = fitFromWidth(startRegion.width + dx); next.width = eastSize.width; next.height = eastSize.height; next.y = startRegion.y + Math.round((startRegion.height - next.height) / 2); } else if (dir === 'w') { var westSize = fitFromWidth(startRegion.width - dx); next.width = westSize.width; next.height = westSize.height; next.x = startRegion.x + startRegion.width - next.width; next.y = startRegion.y + Math.round((startRegion.height - next.height) / 2); } else if (dir === 'n') { var northSize = fitFromHeight(startRegion.height - dy); next.width = northSize.width; next.height = northSize.height; next.x = startRegion.x + Math.round((startRegion.width - next.width) / 2); next.y = startRegion.y + startRegion.height - next.height; } else if (dir === 's') { var southSize = fitFromHeight(startRegion.height + dy); next.width = southSize.width; next.height = southSize.height; next.x = startRegion.x + Math.round((startRegion.width - next.width) / 2); } else { var useWidth = Math.abs(dx) >= Math.abs(dy * aspect.ratio); var cornerSize = useWidth ? fitFromWidth(dir.indexOf('w') !== -1 ? startRegion.width - dx : startRegion.width + dx) : fitFromHeight(dir.indexOf('n') !== -1 ? startRegion.height - dy : startRegion.height + dy); next.width = cornerSize.width; next.height = cornerSize.height; if (dir.indexOf('w') !== -1) { next.x = startRegion.x + startRegion.width - next.width; } if (dir.indexOf('n') !== -1) { next.y = startRegion.y + startRegion.height - next.height; } if (dir.indexOf('e') !== -1) { next.x = startRegion.x; } if (dir.indexOf('s') !== -1) { next.y = startRegion.y; } } } else { if (dir.indexOf('w') !== -1) { next.x = startRegion.x + dx; next.width = startRegion.width - dx; } if (dir.indexOf('e') !== -1) { next.width = startRegion.width + dx; } if (dir.indexOf('n') !== -1) { next.y = startRegion.y + dy; next.height = startRegion.height - dy; } if (dir.indexOf('s') !== -1) { next.height = startRegion.height + dy; } } if (next.width < 12) { if (dir.indexOf('w') !== -1) { next.x -= 12 - next.width; } next.width = 12; } if (next.height < 12) { if (dir.indexOf('n') !== -1) { next.y -= 12 - next.height; } next.height = 12; } next = clampRegion(next); writeCard(cardAt(index), { x: next.x, y: next.y, width: next.width, height: next.height }); requestOverlayRender(); } function upHandler() { document.removeEventListener('mousemove', moveHandler); document.removeEventListener('mouseup', upHandler); } document.addEventListener('mousemove', moveHandler); document.addEventListener('mouseup', upHandler); } if (addRegionButton && regionAddModal) { var addRegionTypeButtons = regionAddModal.querySelectorAll('[data-add-region-type]'); addRegionButton.addEventListener('click', function () { openAddRegionModal(); }); Array.prototype.forEach.call(addRegionTypeButtons, function (button) { button.addEventListener('click', function () { var regionType = button.getAttribute('data-add-region-type'); addRegion(createDefaultRegion(regionType)); if (window.pulseModal) { window.pulseModal.hide(regionAddModal); } }); }); } backgroundInput.addEventListener('change', function () { var file = backgroundInput.files && backgroundInput.files[0]; if (file) { updateBackgroundPreview(file); } }); if (removeBackgroundButton && removeBackgroundFlag) { removeBackgroundButton.addEventListener('click', function () { removeBackgroundFlag.checked = true; backgroundInput.value = ''; backgroundPreview.removeAttribute('src'); backgroundPreview.style.display = 'none'; backgroundEmpty.style.display = 'block'; }); } if (backgroundColorInput) { backgroundColorInput.addEventListener('input', updateStageBackgroundColor); } canvasSizeSelect.addEventListener('change', function () { syncCanvasSizeSelection(); render(); }); canvasWidthInput.addEventListener('input', render); canvasHeightInput.addEventListener('input', render); regionSelect.addEventListener('change', function () { setSelected(Number(regionSelect.value || 0)); }); overlay.addEventListener('mousedown', function (event) { var rect = event.target.closest('.designer-rect'); if (rect) { var index = Number(rect.getAttribute('data-index')); var handle = event.target.closest('.resize-handle'); event.preventDefault(); setSelected(index); if (handle) { resizeFromHandle(index, handle.getAttribute('data-dir'), event); } else { startMove(index, event); } return; } if (event.target !== overlay && !event.target.classList.contains('designer-overlay')) { return; } event.preventDefault(); setSelected(-1); startDraw(event); }); if (templateForm) { templateForm.addEventListener('formdata', function (event) { if (!validateRegionNames()) { event.preventDefault(); return; } getCards().forEach(function (card) { if (isRegionLocked(card)) { syncLockedDimensions(card, 'width'); updateRegionLockBadge(card); } }); syncCanvasSizeSelection(); event.formData.set('regions_json', JSON.stringify(getCards().map(readCard))); }); templateForm.addEventListener('submit', function () { if (!validateRegionNames()) { return; } getCards().forEach(function (card) { if (isRegionLocked(card)) { syncLockedDimensions(card, 'width'); updateRegionLockBadge(card); } }); syncCanvasSizeSelection(); regionsJsonInput.value = JSON.stringify(getCards().map(readCard)); }); } renderRegionList(existingRegions); syncCanvasSizeSelection(); updateStageBackgroundColor(); render(); })();