let SM = { alert: (title, text, type = 'info') =>{ const data = { position: 'top-end', timer: 7000, toast: true, title: title, text: text, showConfirmButton: false, showCloseButton: true, customClass: { container: type, } } Swal.fire(data); }, copyToClipboard: (text) => { const copyContent = async () => { try { await navigator.clipboard.writeText(text); SM.alert('Link copied', 'The link has been copied to the clipboard.', 'success'); } catch (err) { SM.alert('Copy failed', 'Could not copy the link to the clipboard. It may not have permission in your browser.', 'danger'); } } copyContent().then(() => { /* empty */}); }, updateShippingAddress: () => { const checkboxElement = document.querySelector('input[name="shipping_same_billing"]'); if (checkboxElement) { const itemNames = ['address', 'address2', 'city', 'state', 'postcode', 'country']; if (checkboxElement.checked) { itemNames.forEach((itemName) => { const element = document.querySelector(`input[name="shipping_${itemName}"]`); element.value = document.querySelector(`input[name="billing_${itemName}"]`).value; element.setAttribute('readonly', 'true'); }); } else { itemNames.forEach((itemName) => { const element = document.querySelector(`input[name="shipping_${itemName}"]`); element.removeAttribute('readonly'); }); } } }, confirmDelete: (token, title, content, url) => { Swal.fire({ position: 'top', icon: 'warning', iconColor: '#b91c1c', title: title, html: content, showCancelButton: true, confirmButtonText: 'Delete', confirmButtonColor: '#b91c1c', cancelButtonText: 'Cancel', reverseButtons: true }).then((result) => { if (result.isConfirmed) { axios.delete(url) .then((response) => { if(response.data.success){ window.location.href = response.data.redirect; } }) .catch(() => { window.location.reload(); }); } }); }, upload: (files, callback, titles = []) => { let uploadedFiles = []; if(files.length === 0) { return; } const data = { title: "Checking...", text: "Please wait", imageUrl: "/loading.gif", imageHeight: 100, showConfirmButton: false, allowOutsideClick: false, allowEscapeKey: false, } Swal.fire(data); const showError = (message) => { Swal.fire({ position: 'top', icon: 'error', title: 'An error occurred', html: message, showConfirmButton: true, confirmButtonColor: '#b91c1c', }).then(() => { if(callback) { callback({success: false}); } }); } for(const file of files) { if (file.size > SM.maxUploadSize()) { const size = SM.bytesToString(file.size); const maxSize = SM.bytesToString(SM.maxUploadSize()); showError('The file size is too large (' + size + ').
Please upload a file less than ' + maxSize + '.'); return; } } const uploadFile = (file, start, title, idx, count) => { const showPercentDecimals = (file.size > (1024 * 1024 * 40)); const chunkSize = 1024 * 1024 * 2; const end = Math.min(file.size, start + chunkSize); const chunk = file.slice(start, end); const formData = new FormData(); formData.append('file', chunk); formData.append('filename', file.name); formData.append('filesize', file.size); if (start === 0) { formData.append('filestart', 'true'); } else { formData.append('fileappend', 'true'); } if (title !== '') { formData.append('title', title); } axios.post('/admin/media', formData, { headers: { 'Content-Type': 'multipart/form-data', 'Accept': 'application/json' }, onUploadProgress: (progressEvent) => { let percent = ((start + progressEvent.loaded) / file.size) * 100; if(showPercentDecimals) { percent = percent.toFixed(1); } else { percent = Math.round(percent); } let title = 'Uploading'; if(count > 1) { title += ' ' + (idx + 1) + ' of ' + count; } Swal.update({ title: title + '...', html: `${file.name} - ${percent}%`, }); } }).then((response) => { if (response.status === 200) { if (end >= file.size) { uploadedFiles.push({ file: file, title: title, data: response.data }); if (idx === count - 1) { Swal.fire({ icon: 'success', title: 'Success', html: count > 1 ? `Uploaded ${count} files successfully` : `${response.data.name || file.name} uploaded successfully`, showConfirmButton: false, timer: 3000 }); if (callback) { window.setTimeout(() => { callback({ success: true, files: uploadedFiles }); }, 3000); } return; } else { start = 0; idx += 1; } } else { start = end; } uploadFile(files[idx], start, titles[idx] || '', idx, files.length); } else { showError(response.data.message); } }).catch(() => { showError('An error occurred while uploading the file.'); }); } uploadFile(files[0], 0, titles[0] || '', 0, files.length); }, bytesToString: (bytes) => { bytes = parseInt(bytes); if (isNaN(bytes)) { bytes = 0; } const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; const fixed = [0, 0, 2, 2, 2]; if (bytes === 0) return '0 Bytes'; const i = Math.floor(Math.log(bytes) / Math.log(1024)); const size = parseFloat((bytes / Math.pow(1024, i)).toFixed(fixed[i])); return size + ' ' + sizes[i]; }, maxUploadSize: () => { try { return parseInt(document.querySelector('meta[name="max-upload-size"]').getAttribute('content')); } catch (error) { /* Do nothing */ } return 0; }, /** * Transforms a string to title case. * @param {string} str The string to transform. * @returns {string} A string transformed to title case. */ toTitleCase: (str) => { // Remove leading and trailing spaces str = str.trim(); // Remove file extension str = str.replace(/\.[a-zA-Z0-9]{1,4}$/, ""); // Replace underscores and hyphens with spaces str = str.replace(/[_-]+/g, " "); // Capitalize the first letter of each word and make the rest lowercase str = str.replace(/\b\w+\b/g, (txt) => { return txt.charAt(0).toUpperCase() + txt.slice(1).toLowerCase(); }); // Replace "cdn" with "CDN" str = str.replace(/\bCdn\b/gi, "CDN"); return str; }, mediaDetails: (name, callback) => { axios.get('/media/' + name, { headers: { 'Accept': 'application/json' } }).then((response) => { callback(response.data); }).catch((error) => { console.error(error); callback(null); }); }, mimeMatches: (fileMime, matchMimeList) => { for(const matchMime of matchMimeList.split(',')) { if (matchMime === '*' || matchMime === '*/*') { return true; } const matchMimeArray = matchMime.split('/'); const fileMimeArray = fileMime.split('/'); if (matchMimeArray[1] === '*' && matchMimeArray[0] === fileMimeArray[0]) { return true; } else if(fileMime === matchMime) { return true; } } return false; }, arrayToString: (array, separator = ',') => { return array.map(item => { if (item.includes(separator)) { // If the item contains the separator, wrap it in quotes and escape any quotes within the string return `"${item.replace(/"/g, '\\"')}"`; } else { return item; } }).join(separator); }, stringToArray: (string, separator = ',') => { return string.split(separator).map(item => { // Remove quotes and unescape any escaped quotes within the string return item.replace(/^"|"$/g, '').replace(/\\"/g, '"'); }); }, decodeHtml: (html) => { const ta = document.createElement("textarea"); ta.innerHTML = html; return ta.value; }, toLocalISOString: (date) => { return date.getFullYear() + '-' + (date.getMonth() + 1).toString().padStart(2, '0') + '-' + date.getDate().toString().padStart(2, '0') + 'T' + date.getHours().toString().padStart(2, '0') + ':' + date.getMinutes().toString().padStart(2, '0'); }, updateThumbnail: (name, element) => { axios.get('/media/' + name) .then(response => { if(response.data.status === 'ready') { if(element instanceof HTMLImageElement) { element.src = response.data.thumbnail; } else if(typeof element === 'string') { const imgElement = document.querySelector(element); if(imgElement instanceof HTMLImageElement) { imgElement.src = response.data.thumbnail; } } } else if(response.data.status === 'processing') { setTimeout(() => { SM.updateThumbnail(name, element); }, 5000); } }) .catch(error => { console.error(error); }); }, updateAllThumbnails: () => { const elements = document.querySelectorAll('img[data-thumbnail]'); elements.forEach(element => { SM.updateThumbnail(element.getAttribute('data-thumbnail'), element); }); } }; document.addEventListener('DOMContentLoaded', () => { SM.updateShippingAddress(); SM.updateAllThumbnails(); });