Release v2.13.1
This commit is contained in:
@@ -0,0 +1,282 @@
|
||||
// Shared media library picker for editor forms.
|
||||
|
||||
(function () {
|
||||
var modal = document.getElementById('media-picker-modal');
|
||||
if (!modal) {
|
||||
return;
|
||||
}
|
||||
|
||||
var activeButton = null;
|
||||
var items = Array.prototype.slice.call(modal.querySelectorAll('[data-media-picker-item]'));
|
||||
var grid = modal.querySelector('[data-media-picker-grid]');
|
||||
var search = modal.querySelector('[data-media-picker-search]');
|
||||
var sort = modal.querySelector('[data-media-picker-sort]');
|
||||
var noResults = modal.querySelector('[data-media-picker-no-results]');
|
||||
var loadMoreWrap = modal.querySelector('[data-media-picker-load-more-wrap]');
|
||||
var loadMoreButton = modal.querySelector('[data-media-picker-load-more]');
|
||||
var confirmButton = modal.querySelector('[data-media-picker-confirm]');
|
||||
var cancelButton = modal.querySelector('[data-media-picker-cancel]');
|
||||
var uploadButton = modal.querySelector('[data-media-picker-upload]');
|
||||
var currentPath = '';
|
||||
var pendingPath = '';
|
||||
var pendingType = '';
|
||||
var visibleRowLimit = 4;
|
||||
var loadedAssets = [];
|
||||
var mediaOffset = 0;
|
||||
var mediaHasMore = false;
|
||||
var refreshSequence = 0;
|
||||
|
||||
function getColumnsPerRow() {
|
||||
return window.innerWidth >= 992 ? 4 : window.innerWidth >= 768 ? 3 : 2;
|
||||
}
|
||||
|
||||
function renderItems(assets) {
|
||||
if (!grid) {
|
||||
return;
|
||||
}
|
||||
grid.innerHTML = (Array.isArray(assets) ? assets : []).map(function (asset) {
|
||||
var type = String(asset.media_type || '');
|
||||
var path = escapeHtml(asset.media_path);
|
||||
var name = escapeHtml(asset.original_name);
|
||||
var createdAt = escapeHtml(asset.created_at);
|
||||
var preview = type === 'video'
|
||||
? '<video src="' + path + '" muted playsinline preload="metadata"></video>'
|
||||
: '<img src="' + path + '" alt="" loading="lazy" />';
|
||||
return '<div class="col-6 col-md-4 col-lg-3" data-media-picker-item data-media-type="' + escapeHtml(type) + '" data-media-name="' + name + '" data-media-created-at="' + createdAt + '">' +
|
||||
'<button type="button" class="media-picker-item w-100 text-start" data-media-picker-path="' + path + '" data-media-picker-type="' + escapeHtml(type) + '">' +
|
||||
'<span class="media-picker-item-preview">' + preview + '</span>' +
|
||||
'<span class="media-picker-item-name text-truncate d-block">' + name + '</span>' +
|
||||
'<span class="media-picker-item-statuses"><span class="media-picker-item-current" data-media-picker-current hidden><i class="bi bi-check-circle me-1" aria-hidden="true"></i>Current</span><span class="media-picker-item-selected" data-media-picker-selected hidden><i class="bi bi-check-circle-fill me-1" aria-hidden="true"></i>Selected</span></span>' +
|
||||
'</button></div>';
|
||||
}).join('');
|
||||
items = Array.prototype.slice.call(modal.querySelectorAll('[data-media-picker-item]'));
|
||||
}
|
||||
|
||||
function getQueryParams(offset, limit) {
|
||||
var params = new URLSearchParams();
|
||||
var type = activeButton ? activeButton.getAttribute('data-media-picker-type') || 'image' : 'image';
|
||||
params.set('offset', String(offset));
|
||||
params.set('limit', String(limit));
|
||||
params.set('search', String(search && search.value || '').trim());
|
||||
params.set('type', type);
|
||||
params.set('sort', sort && sort.value || 'date-desc');
|
||||
return params.toString();
|
||||
}
|
||||
|
||||
async function refreshItems() {
|
||||
var requestSequence = ++refreshSequence;
|
||||
try {
|
||||
var response = await fetch('/media-library/assets?' + getQueryParams(0, 4 * getColumnsPerRow()), { credentials: 'same-origin', headers: { Accept: 'application/json' } });
|
||||
if (!response.ok) {
|
||||
return;
|
||||
}
|
||||
var payload = await response.json();
|
||||
if (requestSequence !== refreshSequence) {
|
||||
return;
|
||||
}
|
||||
loadedAssets = Array.isArray(payload.assets) ? payload.assets : [];
|
||||
mediaOffset = Number(payload.nextOffset || loadedAssets.length);
|
||||
mediaHasMore = Boolean(payload.hasMore);
|
||||
renderItems(loadedAssets);
|
||||
updateSelection();
|
||||
applyFilterAndSort();
|
||||
} catch (_error) {
|
||||
// Keep the server-rendered list if refreshing is unavailable.
|
||||
}
|
||||
}
|
||||
|
||||
function escapeHtml(value) {
|
||||
return String(value || '').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
|
||||
}
|
||||
|
||||
function showModal() {
|
||||
if (window.pulseModal && typeof window.pulseModal.show === 'function') {
|
||||
window.pulseModal.show(modal);
|
||||
} else if (window.bootstrap && window.bootstrap.Modal) {
|
||||
window.bootstrap.Modal.getOrCreateInstance(modal).show();
|
||||
}
|
||||
}
|
||||
|
||||
function hideModal() {
|
||||
if (window.pulseModal && typeof window.pulseModal.hide === 'function') {
|
||||
window.pulseModal.hide(modal);
|
||||
} else if (window.bootstrap && window.bootstrap.Modal) {
|
||||
window.bootstrap.Modal.getOrCreateInstance(modal).hide();
|
||||
}
|
||||
}
|
||||
|
||||
function applyFilterAndSort() {
|
||||
var visibleItems = items.slice();
|
||||
var columnsPerRow = getColumnsPerRow();
|
||||
var visibleItemLimit = visibleRowLimit * columnsPerRow;
|
||||
items.forEach(function (item) { item.hidden = true; });
|
||||
visibleItems.slice(0, visibleItemLimit).forEach(function (item) {
|
||||
item.hidden = false;
|
||||
if (grid) grid.appendChild(item);
|
||||
});
|
||||
if (noResults) noResults.hidden = visibleItems.length > 0;
|
||||
if (loadMoreWrap) loadMoreWrap.hidden = !mediaHasMore || visibleItems.length === 0;
|
||||
}
|
||||
|
||||
function resetVisibleItemLimit() {
|
||||
visibleRowLimit = 4;
|
||||
if (activeButton) {
|
||||
refreshItems();
|
||||
}
|
||||
}
|
||||
|
||||
function updateSelection() {
|
||||
items.forEach(function (item) {
|
||||
var itemButton = item.querySelector('[data-media-picker-path]');
|
||||
var path = itemButton && itemButton.getAttribute('data-media-picker-path');
|
||||
var current = Boolean(currentPath && path === currentPath);
|
||||
var selected = Boolean(pendingPath && path === pendingPath);
|
||||
item.classList.toggle('media-picker-item-current-card', current);
|
||||
item.classList.toggle('media-picker-item-selected-card', selected);
|
||||
if (itemButton) {
|
||||
itemButton.setAttribute('aria-pressed', selected ? 'true' : 'false');
|
||||
var currentLabel = itemButton.querySelector('[data-media-picker-current]');
|
||||
if (currentLabel) currentLabel.hidden = !current;
|
||||
var selectedLabel = itemButton.querySelector('[data-media-picker-selected]');
|
||||
if (selectedLabel) selectedLabel.hidden = !selected;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getActiveHidden() {
|
||||
var hiddenKey = activeButton && activeButton.getAttribute('data-media-picker-hidden');
|
||||
return hiddenKey && (document.getElementById(hiddenKey) || document.querySelector('[name="' + hiddenKey + '"]'));
|
||||
}
|
||||
|
||||
function closePicker() {
|
||||
activeButton = null;
|
||||
currentPath = '';
|
||||
pendingPath = '';
|
||||
pendingType = '';
|
||||
hideModal();
|
||||
}
|
||||
|
||||
function getActiveFileInput() {
|
||||
if (!activeButton) {
|
||||
return null;
|
||||
}
|
||||
var hiddenKey = activeButton.getAttribute('data-media-picker-hidden');
|
||||
if (hiddenKey) {
|
||||
var inputFromHidden = document.getElementById(hiddenKey.replace(/^existing_/, ''));
|
||||
if (inputFromHidden) {
|
||||
return inputFromHidden;
|
||||
}
|
||||
}
|
||||
var inputId = activeButton.getAttribute('for');
|
||||
if (inputId) {
|
||||
return document.getElementById(inputId);
|
||||
}
|
||||
var region = activeButton.closest ? activeButton.closest('[data-region-id]') : null;
|
||||
return region ? region.querySelector('input[type="file"]') : null;
|
||||
}
|
||||
|
||||
function updatePreview(hidden, path, type) {
|
||||
var region = hidden.closest ? hidden.closest('[data-region-id]') : null;
|
||||
if (region) {
|
||||
var previewBox = region.querySelector('.slide-image-region-preview-box');
|
||||
if (previewBox) {
|
||||
var safePath = escapeHtml(path);
|
||||
previewBox.innerHTML = type === 'video'
|
||||
? '<div class="slide-image-region-preview-shell"><video class="slide-image-region-preview" src="' + safePath + '" muted playsinline preload="metadata"></video></div>'
|
||||
: '<div class="slide-image-region-preview-shell"><img class="slide-image-region-preview" src="' + safePath + '" alt="Selected media preview" /></div>';
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var backgroundPreview = document.getElementById('background-preview');
|
||||
var backgroundEmpty = document.getElementById('background-empty');
|
||||
if (backgroundPreview && path) {
|
||||
backgroundPreview.src = path;
|
||||
backgroundPreview.style.display = 'block';
|
||||
if (backgroundEmpty) backgroundEmpty.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('click', function (event) {
|
||||
var uploadTrigger = event.target && event.target.closest ? event.target.closest('[data-media-picker-upload]') : null;
|
||||
if (uploadTrigger) {
|
||||
event.preventDefault();
|
||||
var fileInput = getActiveFileInput();
|
||||
if (fileInput) {
|
||||
fileInput.addEventListener('click', function (inputEvent) {
|
||||
inputEvent.stopPropagation();
|
||||
}, { once: true });
|
||||
fileInput.click();
|
||||
closePicker();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var button = event.target && event.target.closest ? event.target.closest('[data-media-picker]') : null;
|
||||
if (button) {
|
||||
event.preventDefault();
|
||||
activeButton = button;
|
||||
var hidden = getActiveHidden();
|
||||
currentPath = hidden ? String(hidden.value || '') : '';
|
||||
pendingPath = currentPath;
|
||||
pendingType = button.getAttribute('data-media-picker-type') || 'image';
|
||||
if (search) search.value = '';
|
||||
if (sort) sort.value = 'date-desc';
|
||||
visibleRowLimit = 4;
|
||||
updateSelection();
|
||||
applyFilterAndSort();
|
||||
showModal();
|
||||
refreshItems();
|
||||
return;
|
||||
}
|
||||
|
||||
var itemButton = event.target && event.target.closest ? event.target.closest('[data-media-picker-path]') : null;
|
||||
if (!itemButton || !activeButton) {
|
||||
return;
|
||||
}
|
||||
|
||||
pendingPath = itemButton.getAttribute('data-media-picker-path') || '';
|
||||
pendingType = itemButton.getAttribute('data-media-picker-type') || activeButton.getAttribute('data-media-picker-type') || 'image';
|
||||
updateSelection();
|
||||
});
|
||||
|
||||
if (search) search.addEventListener('input', resetVisibleItemLimit);
|
||||
if (sort) sort.addEventListener('change', resetVisibleItemLimit);
|
||||
if (loadMoreButton) loadMoreButton.addEventListener('click', async function () {
|
||||
loadMoreButton.disabled = true;
|
||||
try {
|
||||
var response = await fetch('/media-library/assets?' + getQueryParams(mediaOffset, 4 * getColumnsPerRow()), { credentials: 'same-origin', headers: { Accept: 'application/json' } });
|
||||
if (!response.ok) {
|
||||
return;
|
||||
}
|
||||
var payload = await response.json();
|
||||
loadedAssets = loadedAssets.concat(Array.isArray(payload.assets) ? payload.assets : []);
|
||||
mediaOffset = Number(payload.nextOffset || mediaOffset);
|
||||
mediaHasMore = Boolean(payload.hasMore);
|
||||
renderItems(loadedAssets);
|
||||
visibleRowLimit += 4;
|
||||
updateSelection();
|
||||
applyFilterAndSort();
|
||||
} finally {
|
||||
loadMoreButton.disabled = false;
|
||||
}
|
||||
});
|
||||
if (confirmButton) confirmButton.addEventListener('click', function () {
|
||||
var hidden = getActiveHidden();
|
||||
if (!hidden || !pendingPath) {
|
||||
closePicker();
|
||||
return;
|
||||
}
|
||||
hidden.value = pendingPath;
|
||||
updatePreview(hidden, pendingPath, pendingType);
|
||||
hidden.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
closePicker();
|
||||
});
|
||||
if (cancelButton) cancelButton.addEventListener('click', closePicker);
|
||||
modal.addEventListener('hidden.bs.modal', function () {
|
||||
activeButton = null;
|
||||
currentPath = '';
|
||||
pendingPath = '';
|
||||
pendingType = '';
|
||||
});
|
||||
})();
|
||||
@@ -41,12 +41,12 @@
|
||||
bodyHtml: '' +
|
||||
'<div class="row g-3 align-items-start">' +
|
||||
'<div class="col-12 col-md-8 d-flex flex-column">' +
|
||||
'<label class="slide-image-region-upload-zone" data-region-upload-zone="' + region.id + '" for="region_image_' + region.id + '">' +
|
||||
'<label class="slide-image-region-upload-zone" data-region-upload-zone="' + region.id + '" data-media-picker data-media-picker-type="image" data-media-picker-hidden="existing_region_image_' + region.id + '" for="region_image_' + region.id + '">' +
|
||||
'<input type="file" id="region_image_' + region.id + '" name="region_image_' + region.id + '" class="visually-hidden" accept="' + escapeHtml(uploadAccept) + '" data-slide-image-cropper-region-ratio="' + escapeHtml(regionRatio) + '" data-slide-image-cropper-region-ratio-label="Region" />' +
|
||||
'<span class="slide-image-region-upload-zone-content">' +
|
||||
'<span class="slide-image-region-upload-zone-icon"><i class="bi bi-cloud-arrow-up" aria-hidden="true"></i></span>' +
|
||||
'<span class="slide-image-region-upload-zone-copy">' +
|
||||
'<strong>Drop an image here or click to upload</strong>' +
|
||||
'<strong>Drop an image here or click to select existing</strong>' +
|
||||
'<span>' + escapeHtml(uploadHelpText) + '</span>' +
|
||||
'<span class="slide-image-region-upload-zone-limit">Max ' + escapeHtml(uploadMaxLabel) + ' per file</span>' +
|
||||
'</span>' +
|
||||
|
||||
@@ -982,12 +982,12 @@
|
||||
var imageOptionsHtml = '' +
|
||||
'<div class="row g-3 align-items-start">' +
|
||||
'<div class="col-12 col-md-8">' +
|
||||
'<label class="slide-image-region-upload-zone" data-region-upload-zone="' + region.id + '" for="region_qr_image_' + region.id + '">' +
|
||||
'<label class="slide-image-region-upload-zone" data-region-upload-zone="' + region.id + '" data-media-picker data-media-picker-type="image" data-media-picker-hidden="existing_region_qr_image_' + region.id + '" for="region_qr_image_' + region.id + '">' +
|
||||
'<input type="file" id="region_qr_image_' + region.id + '" name="region_qr_image_' + region.id + '" class="visually-hidden" accept="image/*" />' +
|
||||
'<span class="slide-image-region-upload-zone-content">' +
|
||||
'<span class="slide-image-region-upload-zone-icon"><i class="bi bi-cloud-arrow-up" aria-hidden="true"></i></span>' +
|
||||
'<span class="slide-image-region-upload-zone-copy">' +
|
||||
'<strong>Drop an image here or click to upload</strong>' +
|
||||
'<strong>Drop an image here or click to select existing</strong>' +
|
||||
'<span>PNG, JPG, GIF, or WebP</span>' +
|
||||
'<span class="slide-image-region-upload-zone-limit">Replaces the QR image logo</span>' +
|
||||
'</span>' +
|
||||
|
||||
@@ -46,12 +46,12 @@
|
||||
bodyHtml: '' +
|
||||
'<div class="row g-3 align-items-start">' +
|
||||
'<div class="col-12 col-md-8 d-flex flex-column">' +
|
||||
'<label class="slide-image-region-upload-zone" data-region-upload-zone="' + region.id + '" for="region_video_' + region.id + '">' +
|
||||
'<label class="slide-image-region-upload-zone" data-region-upload-zone="' + region.id + '" data-media-picker data-media-picker-type="video" data-media-picker-hidden="existing_region_video_' + region.id + '" for="region_video_' + region.id + '">' +
|
||||
'<input type="file" id="region_video_' + region.id + '" name="region_video_' + region.id + '" class="visually-hidden" accept="' + escapeHtml(uploadAccept) + '" />' +
|
||||
'<span class="slide-image-region-upload-zone-content">' +
|
||||
'<span class="slide-image-region-upload-zone-icon"><i class="bi bi-camera-video" aria-hidden="true"></i></span>' +
|
||||
'<span class="slide-image-region-upload-zone-copy">' +
|
||||
'<strong>Drop a video here or click to upload</strong>' +
|
||||
'<strong>Drop a video here or click to select existing</strong>' +
|
||||
'<span>' + escapeHtml(uploadHelpText) + '</span>' +
|
||||
'<span class="slide-image-region-upload-zone-limit">Max ' + escapeHtml(uploadVideoMaxLabel) + ' per file</span>' +
|
||||
'</span>' +
|
||||
|
||||
@@ -0,0 +1,559 @@
|
||||
const modal = document.getElementById('media-gallery-preview-modal');
|
||||
const body = modal && modal.querySelector('[data-media-gallery-preview-body]');
|
||||
const title = modal && modal.querySelector('#media-gallery-preview-modal-label');
|
||||
const gallery = document.querySelector('.media-gallery');
|
||||
const search = gallery && gallery.querySelector('[data-media-gallery-search]');
|
||||
const typeFilter = gallery && gallery.querySelector('[data-media-gallery-type-filter]');
|
||||
const usageFilter = gallery && gallery.querySelector('[data-media-gallery-usage-filter]');
|
||||
const sort = gallery && gallery.querySelector('[data-media-gallery-sort]');
|
||||
const galleryCount = gallery && gallery.querySelector('[data-media-gallery-count]');
|
||||
const noResults = gallery && gallery.querySelector('[data-media-gallery-no-results]');
|
||||
const loadMoreWrap = gallery && gallery.querySelector('[data-media-gallery-load-more-wrap]');
|
||||
const loadMoreButton = gallery && gallery.querySelector('[data-media-gallery-load-more]');
|
||||
const selectModeButton = gallery && gallery.querySelector('[data-media-gallery-select-mode]');
|
||||
const deleteSelectedButton = gallery && gallery.querySelector('[data-media-gallery-delete-selected]');
|
||||
let galleryItems = gallery ? Array.from(gallery.querySelectorAll('[data-media-gallery-column]')) : [];
|
||||
let visibleRowLimit = 4;
|
||||
let galleryOffset = gallery ? Number(gallery.dataset.mediaGalleryOffset || galleryItems.length) : 0;
|
||||
let galleryHasMore = gallery ? gallery.dataset.mediaGalleryHasMore === 'true' : false;
|
||||
let galleryTotal = galleryCount ? Number(galleryCount.textContent || galleryItems.length) : galleryItems.length;
|
||||
let galleryRefreshSequence = 0;
|
||||
let selectionMode = false;
|
||||
const selectedAssetIds = new Set();
|
||||
const uploadForm = document.querySelector('form[action="/media-library"]');
|
||||
const uploadInput = document.querySelector('[data-media-library-upload]');
|
||||
const uploadZone = document.querySelector('[data-media-library-upload-zone]');
|
||||
const uploadName = document.querySelector('[data-media-library-upload-name]');
|
||||
const cropModal = document.getElementById('media-library-crop-modal');
|
||||
const cropImage = cropModal && cropModal.querySelector('#media-library-crop-image');
|
||||
const cropApply = cropModal && cropModal.querySelector('[data-media-library-crop-apply]');
|
||||
const cropCancel = cropModal && cropModal.querySelector('[data-media-library-crop-cancel]');
|
||||
const cropStatus = cropModal && cropModal.querySelector('#media-library-crop-status');
|
||||
const cropFrame = cropModal && cropModal.querySelector('.slide-image-cropper-frame');
|
||||
let cropper = null;
|
||||
let cropObjectUrl = '';
|
||||
let cropSourceFile = null;
|
||||
let cropFlipX = 1;
|
||||
let cropFlipY = 1;
|
||||
|
||||
function getColumnsPerRow() {
|
||||
return window.innerWidth >= 1200 ? 6 : window.innerWidth >= 992 ? 3 : window.innerWidth >= 576 ? 2 : 1;
|
||||
}
|
||||
|
||||
function showUploadMessage(message) {
|
||||
if (typeof window.showToast === 'function') {
|
||||
window.showToast(message, 'warning');
|
||||
return;
|
||||
}
|
||||
window.alert(message);
|
||||
}
|
||||
|
||||
function showUploadModal() {
|
||||
if (window.pulseModal && typeof window.pulseModal.show === 'function') {
|
||||
window.pulseModal.show(cropModal);
|
||||
} else if (window.bootstrap && window.bootstrap.Modal) {
|
||||
window.bootstrap.Modal.getOrCreateInstance(cropModal).show();
|
||||
}
|
||||
}
|
||||
|
||||
function hideUploadModal() {
|
||||
if (window.pulseModal && typeof window.pulseModal.hide === 'function') {
|
||||
window.pulseModal.hide(cropModal);
|
||||
} else if (window.bootstrap && window.bootstrap.Modal) {
|
||||
window.bootstrap.Modal.getOrCreateInstance(cropModal).hide();
|
||||
}
|
||||
}
|
||||
|
||||
function clearCropper() {
|
||||
if (cropper) {
|
||||
cropper.destroy();
|
||||
cropper = null;
|
||||
}
|
||||
if (cropObjectUrl) {
|
||||
URL.revokeObjectURL(cropObjectUrl);
|
||||
cropObjectUrl = '';
|
||||
}
|
||||
cropSourceFile = null;
|
||||
cropFlipX = 1;
|
||||
cropFlipY = 1;
|
||||
if (cropStatus) cropStatus.textContent = '';
|
||||
if (cropFrame) cropFrame.classList.remove('is-loading');
|
||||
}
|
||||
|
||||
function setCropperActionState(disabled) {
|
||||
if (!cropModal) return;
|
||||
cropModal.querySelectorAll('[data-media-library-crop-action]').forEach(function (button) {
|
||||
button.disabled = Boolean(disabled);
|
||||
});
|
||||
}
|
||||
function appendGalleryAsset(asset) {
|
||||
if (!gallery || !asset) return;
|
||||
const column = document.createElement('div');
|
||||
column.className = 'col-12 col-sm-6 col-lg-4 col-xl-2';
|
||||
column.dataset.mediaGalleryColumn = '';
|
||||
column.dataset.mediaId = String(asset.id || '');
|
||||
column.dataset.mediaType = asset.media_type || '';
|
||||
column.dataset.mediaUsed = asset.inUse ? 'true' : 'false';
|
||||
const article = document.createElement('article');
|
||||
article.className = 'media-gallery-card';
|
||||
article.dataset.mediaCreatedAt = asset.created_at || '';
|
||||
article.dataset.mediaFileSize = asset.file_size || '0';
|
||||
const preview = document.createElement('button');
|
||||
preview.type = 'button';
|
||||
preview.className = 'media-gallery-preview';
|
||||
preview.dataset.mediaGalleryPreview = '';
|
||||
preview.dataset.mediaPath = asset.media_path || '';
|
||||
preview.dataset.mediaType = asset.media_type || '';
|
||||
preview.dataset.mediaName = asset.original_name || '';
|
||||
preview.setAttribute('aria-label', 'Preview ' + (asset.original_name || 'media'));
|
||||
const media = asset.media_type === 'video' ? document.createElement('video') : document.createElement('img');
|
||||
media.src = asset.media_path || '';
|
||||
if (asset.media_type === 'video') {
|
||||
media.muted = true;
|
||||
media.playsInline = true;
|
||||
media.preload = 'metadata';
|
||||
} else {
|
||||
media.alt = asset.original_name || '';
|
||||
media.loading = 'lazy';
|
||||
}
|
||||
preview.appendChild(media);
|
||||
if (asset.media_type === 'video') {
|
||||
const play = document.createElement('span');
|
||||
play.className = 'media-gallery-play';
|
||||
play.setAttribute('aria-hidden', 'true');
|
||||
play.innerHTML = '<i class="bi bi-play-fill"></i>';
|
||||
preview.appendChild(play);
|
||||
}
|
||||
const format = document.createElement('span');
|
||||
format.className = 'media-gallery-type';
|
||||
format.textContent = asset.mediaFormat || '';
|
||||
preview.appendChild(format);
|
||||
const details = document.createElement('div');
|
||||
details.className = 'media-gallery-details';
|
||||
const header = document.createElement('div');
|
||||
header.className = 'media-gallery-header';
|
||||
const name = document.createElement('h4');
|
||||
name.className = 'media-gallery-name';
|
||||
name.title = asset.original_name || '';
|
||||
name.textContent = asset.original_name || '';
|
||||
header.appendChild(name);
|
||||
if (asset.canDelete) {
|
||||
if (asset.inUse) {
|
||||
const lock = document.createElement('button');
|
||||
lock.type = 'button';
|
||||
lock.className = 'btn btn-outline-secondary btn-sm media-gallery-action';
|
||||
lock.disabled = true;
|
||||
lock.title = 'Media is in use';
|
||||
lock.innerHTML = '<i class="bi bi-lock" aria-hidden="true"></i><span class="visually-hidden">Media is in use</span>';
|
||||
header.appendChild(lock);
|
||||
} else {
|
||||
const form = document.createElement('form');
|
||||
form.method = 'post';
|
||||
form.action = '/media-library/' + encodeURIComponent(asset.id) + '/delete';
|
||||
form.dataset.confirmMessage = 'Delete this media?';
|
||||
form.className = 'media-gallery-action';
|
||||
form.innerHTML = '<button type="submit" class="btn btn-outline-danger btn-sm" title="Delete media"><i class="bi bi-trash" aria-hidden="true"></i><span class="visually-hidden">Delete media</span></button>';
|
||||
header.appendChild(form);
|
||||
}
|
||||
}
|
||||
const meta = document.createElement('div');
|
||||
meta.className = 'media-gallery-meta';
|
||||
meta.textContent = (asset.displayFileSize || '') + ' · Used ' + Number(asset.referenceCount || 0) + ' time' + (Number(asset.referenceCount || 0) === 1 ? '' : 's');
|
||||
details.appendChild(header);
|
||||
details.appendChild(meta);
|
||||
article.appendChild(preview);
|
||||
article.appendChild(details);
|
||||
column.appendChild(article);
|
||||
gallery.querySelector('.media-gallery-scroll .row').appendChild(column);
|
||||
galleryItems.push(column);
|
||||
column.querySelector('.media-gallery-card').classList.toggle('media-gallery-card-selected', selectedAssetIds.has(String(asset.id || '')));
|
||||
}
|
||||
|
||||
function applyCropRatio(value) {
|
||||
if (!cropper) return;
|
||||
cropper.setAspectRatio(value === 'free' ? NaN : Number(value.split(':')[0]) / Number(value.split(':')[1]));
|
||||
cropModal.querySelectorAll('[data-media-library-crop-action="ratio"]').forEach(function (button) {
|
||||
const active = button.dataset.mediaLibraryCropRatio === value;
|
||||
button.classList.toggle('active', active);
|
||||
button.setAttribute('aria-pressed', active ? 'true' : 'false');
|
||||
});
|
||||
}
|
||||
|
||||
function initMediaCropper() {
|
||||
if (!cropSourceFile || !cropImage || !window.Cropper || cropper) return;
|
||||
if (cropFrame) cropFrame.classList.add('is-loading');
|
||||
cropper = new window.Cropper(cropImage, {
|
||||
aspectRatio: NaN,
|
||||
autoCropArea: 1,
|
||||
background: false,
|
||||
dragMode: 'move',
|
||||
initialAspectRatio: NaN,
|
||||
movable: true,
|
||||
responsive: true,
|
||||
rotatable: true,
|
||||
scalable: true,
|
||||
viewMode: 1,
|
||||
zoomOnTouch: true,
|
||||
zoomOnWheel: true,
|
||||
ready: function () {
|
||||
if (cropFrame) cropFrame.classList.remove('is-loading');
|
||||
if (cropper && cropper.container) {
|
||||
cropper.container.style.width = '100%';
|
||||
cropper.container.style.height = '560px';
|
||||
cropper.container.style.maxHeight = '70vh';
|
||||
}
|
||||
const containerData = cropper.getContainerData();
|
||||
const imageData = cropper.getImageData();
|
||||
const fitRatio = Math.min(Number(containerData.width || 0) / Number(imageData.naturalWidth || 1), Number(containerData.height || 0) / Number(imageData.naturalHeight || 1), 1);
|
||||
if (fitRatio > 0) cropper.zoomTo(fitRatio);
|
||||
applyCropRatio('free');
|
||||
setCropperActionState(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setUploadFile(file, shouldCrop) {
|
||||
if (!uploadInput || !file) {
|
||||
return;
|
||||
}
|
||||
const allowedTypes = String(uploadInput.accept || '').split(',').map(function (value) { return value.trim().toLowerCase(); }).filter(Boolean);
|
||||
const fileType = String(file.type || '').toLowerCase();
|
||||
const matchesType = allowedTypes.length === 0 || allowedTypes.indexOf(fileType) !== -1;
|
||||
const maxBytes = fileType.indexOf('video/') === 0 ? Number(uploadInput.dataset.videoMaxBytes) : Number(uploadInput.dataset.imageMaxBytes);
|
||||
if (!matchesType) {
|
||||
showUploadMessage('This media type is disabled in Media Uploads settings.');
|
||||
uploadInput.value = '';
|
||||
return;
|
||||
}
|
||||
if (maxBytes && file.size > maxBytes) {
|
||||
showUploadMessage('This file is larger than the configured upload limit.');
|
||||
uploadInput.value = '';
|
||||
return;
|
||||
}
|
||||
|
||||
const transfer = new DataTransfer();
|
||||
transfer.items.add(file);
|
||||
uploadInput.files = transfer.files;
|
||||
if (uploadName) {
|
||||
uploadName.textContent = file.name;
|
||||
}
|
||||
|
||||
if (shouldCrop && fileType.indexOf('image/') === 0 && cropModal && cropImage && window.Cropper) {
|
||||
clearCropper();
|
||||
setCropperActionState(true);
|
||||
cropSourceFile = file;
|
||||
cropObjectUrl = URL.createObjectURL(file);
|
||||
cropImage.src = cropObjectUrl;
|
||||
if (cropFrame) cropFrame.classList.add('is-loading');
|
||||
showUploadModal();
|
||||
}
|
||||
}
|
||||
|
||||
function submitUpload() {
|
||||
if (!uploadForm) {
|
||||
return;
|
||||
}
|
||||
if (typeof uploadForm.requestSubmit === 'function') {
|
||||
uploadForm.requestSubmit();
|
||||
} else {
|
||||
uploadForm.submit();
|
||||
}
|
||||
}
|
||||
|
||||
if (uploadInput) {
|
||||
uploadInput.addEventListener('change', function () {
|
||||
const file = uploadInput.files && uploadInput.files[0];
|
||||
if (file) {
|
||||
setUploadFile(file, true);
|
||||
if (String(file.type || '').toLowerCase().indexOf('image/') !== 0 || !(cropModal && cropImage && window.Cropper)) {
|
||||
submitUpload();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (uploadZone) {
|
||||
uploadZone.addEventListener('dragover', function (event) {
|
||||
event.preventDefault();
|
||||
uploadZone.classList.add('is-dragover');
|
||||
});
|
||||
uploadZone.addEventListener('dragleave', function () {
|
||||
uploadZone.classList.remove('is-dragover');
|
||||
});
|
||||
uploadZone.addEventListener('drop', function (event) {
|
||||
event.preventDefault();
|
||||
uploadZone.classList.remove('is-dragover');
|
||||
const file = event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files[0];
|
||||
if (file) {
|
||||
setUploadFile(file, true);
|
||||
if (String(file.type || '').toLowerCase().indexOf('image/') !== 0 || !(cropModal && cropImage && window.Cropper)) {
|
||||
submitUpload();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (cropApply) {
|
||||
cropApply.addEventListener('click', function () {
|
||||
if (!cropper || !cropSourceFile || !uploadInput) {
|
||||
hideUploadModal();
|
||||
return;
|
||||
}
|
||||
const outputType = cropSourceFile.type === 'image/jpeg' || cropSourceFile.type === 'image/webp' ? cropSourceFile.type : 'image/png';
|
||||
cropper.getCroppedCanvas().toBlob(function (blob) {
|
||||
if (!blob) {
|
||||
showUploadMessage('Unable to crop this image.');
|
||||
return;
|
||||
}
|
||||
const extension = outputType === 'image/jpeg' ? '.jpg' : outputType === 'image/webp' ? '.webp' : '.png';
|
||||
const croppedFile = new File([blob], cropSourceFile.name.replace(/\.[^.]+$/, '') + extension, { type: outputType, lastModified: Date.now() });
|
||||
clearCropper();
|
||||
setUploadFile(croppedFile, false);
|
||||
hideUploadModal();
|
||||
submitUpload();
|
||||
}, outputType, 0.92);
|
||||
});
|
||||
}
|
||||
|
||||
if (cropCancel) {
|
||||
cropCancel.addEventListener('click', function () {
|
||||
clearCropper();
|
||||
if (uploadInput) uploadInput.value = '';
|
||||
if (uploadName) uploadName.textContent = 'No file selected';
|
||||
hideUploadModal();
|
||||
});
|
||||
}
|
||||
|
||||
if (cropModal) {
|
||||
cropModal.addEventListener('click', function (event) {
|
||||
const button = event.target && event.target.closest ? event.target.closest('[data-media-library-crop-action]') : null;
|
||||
if (!button || !cropper) return;
|
||||
const action = button.dataset.mediaLibraryCropAction;
|
||||
if (action === 'rotate-left') cropper.rotate(-90);
|
||||
if (action === 'rotate-right') cropper.rotate(90);
|
||||
if (action === 'flip-horizontal') {
|
||||
cropFlipX *= -1;
|
||||
cropper.scaleX(cropFlipX);
|
||||
}
|
||||
if (action === 'flip-vertical') {
|
||||
cropFlipY *= -1;
|
||||
cropper.scaleY(cropFlipY);
|
||||
}
|
||||
if (action === 'ratio') applyCropRatio(button.dataset.mediaLibraryCropRatio || 'free');
|
||||
if (action === 'reset') {
|
||||
cropper.reset();
|
||||
cropFlipX = 1;
|
||||
cropFlipY = 1;
|
||||
applyCropRatio('free');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (cropModal) {
|
||||
cropModal.addEventListener('shown.bs.modal', function () {
|
||||
if (cropSourceFile && cropImage && window.Cropper && !cropper) {
|
||||
initMediaCropper();
|
||||
}
|
||||
});
|
||||
cropModal.addEventListener('hidden.bs.modal', function () {
|
||||
clearCropper();
|
||||
});
|
||||
}
|
||||
|
||||
if (uploadForm) {
|
||||
uploadForm.addEventListener('submit', function (event) {
|
||||
if (uploadInput && !uploadInput.files.length) {
|
||||
event.preventDefault();
|
||||
showUploadMessage('Choose an image or video to upload.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getGalleryQuery(offset, limit) {
|
||||
const params = new URLSearchParams();
|
||||
params.set('offset', String(offset));
|
||||
params.set('limit', String(limit));
|
||||
params.set('search', String(search && search.value || '').trim());
|
||||
params.set('type', typeFilter ? typeFilter.value : 'all');
|
||||
params.set('usage', usageFilter ? usageFilter.value : 'all');
|
||||
params.set('sort', sort ? sort.value : 'date-desc');
|
||||
return params.toString();
|
||||
}
|
||||
|
||||
function updateSearchResults() {
|
||||
const columnsPerRow = getColumnsPerRow();
|
||||
const visibleItemLimit = visibleRowLimit * columnsPerRow;
|
||||
let visibleCount = 0;
|
||||
galleryItems.forEach(function (card) {
|
||||
card.hidden = visibleCount >= visibleItemLimit;
|
||||
if (!card.hidden) {
|
||||
visibleCount += 1;
|
||||
}
|
||||
});
|
||||
|
||||
if (galleryCount) {
|
||||
galleryCount.textContent = String(galleryTotal);
|
||||
}
|
||||
if (noResults) {
|
||||
noResults.hidden = galleryTotal > 0;
|
||||
}
|
||||
if (loadMoreWrap) {
|
||||
loadMoreWrap.hidden = !galleryHasMore || galleryTotal === 0;
|
||||
}
|
||||
updateBulkDeleteActions();
|
||||
}
|
||||
|
||||
function updateBulkDeleteActions() {
|
||||
if (selectModeButton) {
|
||||
selectModeButton.setAttribute('aria-pressed', selectionMode ? 'true' : 'false');
|
||||
selectModeButton.textContent = selectionMode ? 'Done' : 'Select';
|
||||
}
|
||||
if (deleteSelectedButton) {
|
||||
deleteSelectedButton.hidden = !selectionMode;
|
||||
deleteSelectedButton.disabled = selectedAssetIds.size === 0;
|
||||
}
|
||||
galleryItems.forEach(function (item) {
|
||||
const id = String(item.dataset.mediaId || '');
|
||||
const card = item.querySelector('.media-gallery-card');
|
||||
if (card) card.classList.toggle('media-gallery-card-selected', selectionMode && selectedAssetIds.has(id));
|
||||
});
|
||||
}
|
||||
|
||||
function clearSelectedAssets() {
|
||||
selectedAssetIds.clear();
|
||||
}
|
||||
|
||||
function setSelectionMode(enabled) {
|
||||
selectionMode = Boolean(enabled);
|
||||
if (!selectionMode) clearSelectedAssets();
|
||||
if (gallery) gallery.classList.toggle('media-gallery-selection-mode', selectionMode);
|
||||
updateBulkDeleteActions();
|
||||
}
|
||||
|
||||
function submitBulkDelete() {
|
||||
if (!selectedAssetIds.size || !window.confirm('Delete ' + selectedAssetIds.size + ' selected media asset' + (selectedAssetIds.size === 1 ? '' : 's') + '?')) {
|
||||
return;
|
||||
}
|
||||
const form = document.createElement('form');
|
||||
form.method = 'post';
|
||||
form.action = '/media-library/delete';
|
||||
selectedAssetIds.forEach(function (id) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = 'assetIds[]';
|
||||
input.value = id;
|
||||
form.appendChild(input);
|
||||
});
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
}
|
||||
|
||||
async function refreshGallery() {
|
||||
const requestSequence = ++galleryRefreshSequence;
|
||||
try {
|
||||
const response = await fetch('/media-library/assets?' + getGalleryQuery(0, 4 * getColumnsPerRow()), { headers: { Accept: 'application/json' } });
|
||||
if (!response.ok) throw new Error('Unable to refresh media.');
|
||||
const result = await response.json();
|
||||
if (requestSequence !== galleryRefreshSequence) return;
|
||||
galleryItems.forEach(function (item) { item.remove(); });
|
||||
galleryItems = [];
|
||||
clearSelectedAssets();
|
||||
(result.assets || []).forEach(appendGalleryAsset);
|
||||
galleryOffset = Number(result.nextOffset || 0);
|
||||
galleryHasMore = Boolean(result.hasMore);
|
||||
galleryTotal = Number(result.total || 0);
|
||||
visibleRowLimit = 4;
|
||||
updateSearchResults();
|
||||
} catch (error) {
|
||||
showUploadMessage(error.message || 'Unable to refresh media.');
|
||||
}
|
||||
}
|
||||
|
||||
function resetVisibleItemLimit() {
|
||||
visibleRowLimit = 4;
|
||||
refreshGallery();
|
||||
}
|
||||
|
||||
if (search) {
|
||||
search.addEventListener('input', resetVisibleItemLimit);
|
||||
}
|
||||
if (typeFilter) typeFilter.addEventListener('change', resetVisibleItemLimit);
|
||||
if (usageFilter) usageFilter.addEventListener('change', resetVisibleItemLimit);
|
||||
if (sort) sort.addEventListener('change', resetVisibleItemLimit);
|
||||
if (gallery) {
|
||||
gallery.addEventListener('click', function (event) {
|
||||
if (!selectionMode) return;
|
||||
const column = event.target && event.target.closest ? event.target.closest('[data-media-gallery-column]') : null;
|
||||
if (!column || !gallery.contains(column)) return;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (column.dataset.mediaUsed === 'true') return;
|
||||
const id = String(column.dataset.mediaId || '');
|
||||
if (!id) return;
|
||||
if (selectedAssetIds.has(id)) selectedAssetIds.delete(id);
|
||||
else selectedAssetIds.add(id);
|
||||
updateBulkDeleteActions();
|
||||
});
|
||||
}
|
||||
if (selectModeButton) selectModeButton.addEventListener('click', function () { setSelectionMode(!selectionMode); });
|
||||
if (deleteSelectedButton) deleteSelectedButton.addEventListener('click', submitBulkDelete);
|
||||
if (loadMoreButton) {
|
||||
loadMoreButton.addEventListener('click', async function () {
|
||||
loadMoreButton.disabled = true;
|
||||
try {
|
||||
const response = await fetch('/media-library/assets?' + getGalleryQuery(galleryOffset, 4 * getColumnsPerRow()), { headers: { Accept: 'application/json' } });
|
||||
if (!response.ok) throw new Error('Unable to load more media.');
|
||||
const result = await response.json();
|
||||
(result.assets || []).forEach(appendGalleryAsset);
|
||||
galleryOffset = Number(result.nextOffset || galleryOffset);
|
||||
galleryHasMore = Boolean(result.hasMore);
|
||||
galleryTotal = Number(result.total || galleryTotal);
|
||||
visibleRowLimit += 4;
|
||||
updateSearchResults();
|
||||
} catch (error) {
|
||||
showUploadMessage(error.message || 'Unable to load more media.');
|
||||
} finally {
|
||||
loadMoreButton.disabled = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
updateSearchResults();
|
||||
|
||||
function showModal() {
|
||||
if (window.pulseModal && typeof window.pulseModal.show === 'function') {
|
||||
window.pulseModal.show(modal);
|
||||
} else if (window.bootstrap && window.bootstrap.Modal) {
|
||||
window.bootstrap.Modal.getOrCreateInstance(modal).show();
|
||||
}
|
||||
}
|
||||
|
||||
if (modal && body) {
|
||||
document.addEventListener('click', function (event) {
|
||||
const preview = event.target && event.target.closest ? event.target.closest('[data-media-gallery-preview]') : null;
|
||||
if (!preview) {
|
||||
return;
|
||||
}
|
||||
|
||||
const path = preview.getAttribute('data-media-path') || '';
|
||||
const type = preview.getAttribute('data-media-type') || 'image';
|
||||
const name = preview.getAttribute('data-media-name') || 'Media preview';
|
||||
body.replaceChildren();
|
||||
if (title) {
|
||||
title.textContent = name;
|
||||
}
|
||||
|
||||
const media = document.createElement(type === 'video' ? 'video' : 'img');
|
||||
media.src = path;
|
||||
media.alt = type === 'video' ? '' : name;
|
||||
if (type === 'video') {
|
||||
media.controls = true;
|
||||
media.playsInline = true;
|
||||
}
|
||||
body.appendChild(media);
|
||||
showModal();
|
||||
});
|
||||
|
||||
modal.addEventListener('hidden.bs.modal', function () {
|
||||
body.replaceChildren();
|
||||
});
|
||||
}
|
||||
@@ -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 weatherLocations = Array.isArray(settings.weatherLocations) ? settings.weatherLocations : [];
|
||||
var mediaAssets = Array.isArray(settings.mediaAssets) ? settings.mediaAssets : [];
|
||||
var getRegionTypeModule = typeof settings.getRegionTypeModule === 'function' ? settings.getRegionTypeModule : function () { return null; };
|
||||
var requestPreviewRender = typeof settings.requestPreviewRender === 'function' ? settings.requestPreviewRender : function () {};
|
||||
var placeholderUtils = window.placeholderUtils || {};
|
||||
@@ -570,7 +571,8 @@ export function createSlideFormRegionHelpers(options) {
|
||||
: [],
|
||||
sampleDataPreview: buildApiSampleDataMarkup(getCurrentApiConfig(region).source_id, getCurrentApiConfig(region).item_number, getCurrentApiConfig(region).items_path),
|
||||
timetableGroups: timetableGroups,
|
||||
weatherLocations: weatherLocations
|
||||
weatherLocations: weatherLocations,
|
||||
mediaAssets: mediaAssets
|
||||
}, existingContent, region.region_type === 'rss' ? rssFeeds : region.region_type === 'timetable' ? timetableGroups : region.region_type === 'weather' ? weatherLocations : apiSources);
|
||||
}
|
||||
|
||||
@@ -612,7 +614,8 @@ export function createSlideFormRegionHelpers(options) {
|
||||
: [],
|
||||
sampleDataPreview: buildApiSampleDataMarkup(apiConfig.source_id, apiConfig.item_number, apiItemsPath),
|
||||
timetableGroups: timetableGroups,
|
||||
weatherLocations: weatherLocations
|
||||
weatherLocations: weatherLocations,
|
||||
mediaAssets: mediaAssets
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -169,6 +169,7 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
|
||||
apiSources: apiSources,
|
||||
timetableGroups: timetableGroups,
|
||||
weatherLocations: weatherLocations,
|
||||
mediaAssets: Array.isArray(slideEditorData.mediaAssets) ? slideEditorData.mediaAssets : [],
|
||||
defaultFontSize: DEFAULT_FONT_SIZE,
|
||||
uploadMaxLabel: uploadMaxLabel,
|
||||
uploadVideoMaxLabel: uploadVideoMaxLabel,
|
||||
@@ -927,7 +928,7 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
|
||||
}
|
||||
|
||||
templateSelect.addEventListener('change', renderTemplate);
|
||||
templateFields.addEventListener('change', function () {
|
||||
templateFields.addEventListener('change', function (event) {
|
||||
var webpageInput = event.target && typeof event.target.matches === 'function' && event.target.matches('input[type="url"][name^="region_webpage_"]');
|
||||
if (webpageInput) {
|
||||
templateSelectorLock.arm();
|
||||
|
||||
@@ -1776,16 +1776,25 @@
|
||||
|
||||
renderAddRegionOptions();
|
||||
}
|
||||
backgroundInput.addEventListener('change', function () {
|
||||
var file = backgroundInput.files && backgroundInput.files[0];
|
||||
if (file) {
|
||||
updateBackgroundPreview(file);
|
||||
}
|
||||
});
|
||||
if (backgroundInput) {
|
||||
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 = '';
|
||||
var backgroundPathInput = document.getElementById('existing-background-image-path');
|
||||
if (backgroundPathInput) {
|
||||
backgroundPathInput.value = '';
|
||||
backgroundPathInput.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
}
|
||||
if (backgroundInput) {
|
||||
backgroundInput.value = '';
|
||||
}
|
||||
backgroundPreview.removeAttribute('src');
|
||||
backgroundPreview.style.display = 'none';
|
||||
backgroundEmpty.style.display = 'block';
|
||||
|
||||
Reference in New Issue
Block a user