Rev 1 | AutorÃa | Comparar con el anterior | Ultima modificación | Ver Log |
{"version":3,"file":"imageinsert.min.js","sources":["../src/imageinsert.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Tiny media plugin image insertion class for Moodle.\n *\n * @module tiny_media/imageinsert\n * @copyright 2024 Meirza <meirza.arson@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or l
ater\n */\n\nimport Selectors from './selectors';\nimport Dropzone from 'core/dropzone';\nimport uploadFile from 'editor_tiny/uploader';\nimport {prefetchStrings} from 'core/prefetch';\nimport {getStrings} from 'core/str';\nimport {component} from \"./common\";\nimport {getFilePicker} from 'editor_tiny/options';\nimport {displayFilepicker} from 'editor_tiny/utils';\nimport {ImageDetails} from 'tiny_media/imagedetails';\nimport {\n body,\n footer,\n hideElements,\n showElements,\n isValidUrl,\n} from './helpers';\nimport {MAX_LENGTH_ALT} from './imagehelpers';\n\nprefetchStrings('tiny_media', [\n 'insertimage',\n 'enterurl',\n 'enterurlor',\n 'imageurlrequired',\n 'uploading',\n 'loading',\n 'addfilesdrop',\n 'sizecustom_help',\n]);\n\nexport class ImageInsert {\n\n constructor(\n root,\n editor,\n currentModal,\n canShowFilePicker,\n canShowDropZone,\n ) {\n this.root = root;\n this.editor = editor;\n this.cu
rrentModal = currentModal;\n this.canShowFilePicker = canShowFilePicker;\n this.canShowDropZone = canShowDropZone;\n }\n\n init = async function() {\n // Get the localization lang strings and turn them into object.\n const langStringKeys = [\n 'insertimage',\n 'enterurl',\n 'enterurlor',\n 'imageurlrequired',\n 'uploading',\n 'loading',\n 'addfilesdrop',\n 'sizecustom_help',\n ];\n const langStringvalues = await getStrings([...langStringKeys].map((key) => ({key, component})));\n\n // Convert array to object.\n this.langStrings = Object.fromEntries(langStringKeys.map((key, index) => [key, langStringvalues[index]]));\n this.currentModal.setTitle(this.langStrings.insertimage);\n if (this.canShowDropZone) {\n const dropZoneEle = document.querySelector(Selectors.IMAGE.elements.dropzoneContainer);\n\n // Accepted types can be eithe
r a string or an array.\n let acceptedTypes = getFilePicker(this.editor, 'image').accepted_types;\n if (Array.isArray(acceptedTypes)) {\n acceptedTypes = acceptedTypes.join(',');\n }\n\n const dropZone = new Dropzone(\n dropZoneEle,\n acceptedTypes,\n files => {\n this.handleUploadedFile(files);\n }\n );\n dropZone.setLabel(this.langStrings.addfilesdrop);\n dropZone.init();\n }\n await this.registerEventListeners();\n };\n\n /**\n * Enables or disables the URL-related buttons in the footer based on the current URL and input value.\n */\n toggleUrlButton() {\n const urlInput = this.root.querySelector(Selectors.IMAGE.elements.url);\n const url = urlInput.value;\n const addUrl = this.root.querySelector(Selectors.IMAGE.actions.addUrl);\n addUrl.disabled = !(url !== \"\" && isValidUrl(ur
l));\n }\n\n /**\n * Handles changes in the image URL input field and loads a preview of the image if the URL has changed.\n */\n urlChanged() {\n hideElements(Selectors.IMAGE.elements.urlWarning, this.root);\n const input = this.root.querySelector(Selectors.IMAGE.elements.url);\n if (input.value && input.value !== this.currentUrl) {\n this.loadPreviewImage(input.value);\n }\n }\n\n /**\n * Loads and displays a preview image based on the provided URL, and handles image loading events.\n *\n * @param {string} url - The URL of the image to load and display.\n */\n loadPreviewImage = function(url) {\n this.startImageLoading();\n this.currentUrl = url;\n const image = new Image();\n image.src = url;\n image.addEventListener('error', () => {\n const urlWarningLabelEle = this.root.querySelector(Selectors.IMAGE.elements.urlWarning);\n urlWarningLabelEle.innerHTML = this.langStrin
gs.imageurlrequired;\n showElements(Selectors.IMAGE.elements.urlWarning, this.root);\n this.currentUrl = \"\";\n this.stopImageLoading();\n });\n\n image.addEventListener('load', () => {\n let templateContext = {};\n templateContext.sizecustomhelpicon = {text: this.langStrings.sizecustom_help};\n templateContext.bodyTemplate = Selectors.IMAGE.template.body.insertImageDetailsBody;\n templateContext.footerTemplate = Selectors.IMAGE.template.footer.insertImageDetailsFooter;\n templateContext.selector = Selectors.IMAGE.type;\n templateContext.maxlengthalt = MAX_LENGTH_ALT;\n\n Promise.all([body(templateContext, this.root), footer(templateContext, this.root)])\n .then(() => {\n const imagedetails = new ImageDetails(\n this.root,\n this.editor,\n this.currentModal,\n t
his.canShowFilePicker,\n this.canShowDropZone,\n this.currentUrl,\n image,\n );\n imagedetails.init();\n return;\n }).then(() => {\n this.stopImageLoading();\n return;\n })\n .catch(error => {\n window.console.log(error);\n });\n });\n };\n\n /**\n * Displays the upload loader and disables UI elements while loading a file.\n */\n startImageLoading() {\n showElements(Selectors.IMAGE.elements.loaderIcon, this.root);\n const elementsToHide = [\n Selectors.IMAGE.elements.insertImage,\n Selectors.IMAGE.elements.urlWarning,\n Selectors.IMAGE.elements.modalFooter,\n ];\n hideElements(elementsToHide, this.root);\n }\n\n /**\n * Displays the upload loader and disables UI elements while
loading a file.\n */\n stopImageLoading() {\n hideElements(Selectors.IMAGE.elements.loaderIcon, this.root);\n const elementsToShow = [\n Selectors.IMAGE.elements.insertImage,\n Selectors.IMAGE.elements.modalFooter,\n ];\n showElements(elementsToShow, this.root);\n }\n\n filePickerCallback(params) {\n if (params.url) {\n this.loadPreviewImage(params.url);\n }\n }\n\n /**\n * Updates the content of the loader icon.\n *\n * @param {HTMLElement} root - The root element containing the loader icon.\n * @param {object} langStrings - An object containing language strings.\n * @param {number|null} progress - The progress percentage (optional).\n * @returns {void}\n */\n updateLoaderIcon = (root, langStrings, progress = null) => {\n const loaderIcon = root.querySelector(Selectors.IMAGE.elements.loaderIconContainer + ' div');\n loaderIcon.innerHTML = progress !== null ? `${langStri
ngs.uploading} ${Math.round(progress)}%` : langStrings.loading;\n };\n\n /**\n * Handles the uploaded file, initiates the upload process, and updates the UI during the upload.\n *\n * @param {FileList} files - The list of files to upload (usually from a file input field).\n * @returns {Promise<void>} A promise that resolves when the file is uploaded and processed.\n */\n handleUploadedFile = async(files) => {\n try {\n this.startImageLoading();\n const fileURL = await uploadFile(this.editor, 'image', files[0], files[0].name, (progress) => {\n this.updateLoaderIcon(this.root, this.langStrings, progress);\n });\n // Set the loader icon content to \"loading\" after the file upload completes.\n this.updateLoaderIcon(this.root, this.langStrings);\n this.filePickerCallback({url: fileURL});\n } catch (error) {\n // Handle the error.\n const urlWarningLabelEle = this.root.
querySelector(Selectors.IMAGE.elements.urlWarning);\n urlWarningLabelEle.innerHTML = error.error !== undefined ? error.error : error;\n showElements(Selectors.IMAGE.elements.urlWarning, this.root);\n this.stopImageLoading();\n }\n };\n\n registerEventListeners() {\n this.root.addEventListener('click', async(e) => {\n const addUrlEle = e.target.closest(Selectors.IMAGE.actions.addUrl);\n if (addUrlEle) {\n this.urlChanged();\n }\n\n const imageBrowserAction = e.target.closest(Selectors.IMAGE.actions.imageBrowser);\n if (imageBrowserAction && this.canShowFilePicker) {\n e.preventDefault();\n const params = await displayFilepicker(this.editor, 'image');\n this.filePickerCallback(params);\n }\n });\n\n this.root.addEventListener('input', (e) => {\n const urlEle = e.target.closest(Selectors.IMAGE.elements.url);\n
if (urlEle) {\n this.toggleUrlButton();\n }\n });\n\n const fileInput = this.root.querySelector(Selectors.IMAGE.elements.fileInput);\n if (fileInput) {\n fileInput.addEventListener('change', () => {\n this.handleUploadedFile(fileInput.files);\n });\n }\n }\n}\n"],"names":["constructor","root","editor","currentModal","canShowFilePicker","canShowDropZone","async","langStringKeys","langStringvalues","map","key","component","langStrings","Object","fromEntries","index","setTitle","this","insertimage","dropZoneEle","document","querySelector","Selectors","IMAGE","elements","dropzoneContainer","acceptedTypes","accepted_types","Array","isArray","join","dropZone","Dropzone","files","handleUploadedFile","setLabel","addfilesdrop","init","registerEventListeners","url","startImageLoading","currentUrl","image","Image","src","addEventListener","urlWarning","innerHTML","imageurlrequired","stopImageLoading","templateContex
t","sizecustomhelpicon","text","sizecustom_help","bodyTemplate","template","body","insertImageDetailsBody","footerTemplate","footer","insertImageDetailsFooter","selector","type","maxlengthalt","MAX_LENGTH_ALT","Promise","all","then","ImageDetails","catch","error","window","console","log","progress","loaderIcon","loaderIconContainer","uploading","Math","round","loading","fileURL","name","updateLoaderIcon","filePickerCallback","undefined","toggleUrlButton","value","actions","addUrl","disabled","urlChanged","input","loadPreviewImage","elementsToHide","insertImage","modalFooter","elementsToShow","params","e","target","closest","imageBrowser","preventDefault","fileInput"],"mappings":"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"}