Release v2.13.1
This commit is contained in:
@@ -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();
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user