Rev 11 | AutorÃa | Comparar con el anterior | Ultima modificación | Ver Log |
// This file is part of Moodle - http://moodle.org///// Moodle is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Moodle is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Moodle. If not, see <http://www.gnu.org/licenses/>./*** Tiny Media plugin Image class for Moodle.** @module tiny_media/image* @copyright 2022 Huong Nguyen <huongnv13@gmail.com>* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/import Selectors from './selectors';import ImageModal from './imagemodal';import {getImagePermissions} from './options';import {getFilePicker} from 'editor_tiny/options';import {ImageInsert} from 'tiny_media/imageinsert';import {ImageDetails} from 'tiny_media/imagedetails';import {prefetchStrings} from 'core/prefetch';import {getString} from 'core/str';import {body,footer,hideElements,showElements,isPercentageValue,} from './helpers';import {MAX_LENGTH_ALT} from './imagehelpers';prefetchStrings('tiny_media', ['imageurlrequired','sizecustom_help',]);export default class MediaImage {canShowFilePicker = false;editor = null;currentModal = null;/*** @type {HTMLElement|null} The root element.*/root = null;constructor(editor) {const permissions = getImagePermissions(editor);const options = getFilePicker(editor, 'image');// Indicates whether the file picker can be shown.this.canShowFilePicker = permissions.filepicker&& (typeof options !== 'undefined')&& Object.keys(options.repositories).length > 0;// Indicates whether the drop zone area can be shown.this.canShowDropZone = (typeof options !== 'undefined') &&Object.values(options.repositories).some(repository => repository.type === 'upload');this.editor = editor;}async displayDialogue() {const currentImageData = await this.getCurrentImageData();this.currentModal = await ImageModal.create();this.root = this.currentModal.getRoot()[0];if (currentImageData && currentImageData.src) {this.loadPreviewImage(currentImageData.src);} else {this.loadInsertImage();}}/*** Displays an insert image view asynchronously.** @returns {Promise<void>}*/loadInsertImage = async function() {const templateContext = {elementid: this.editor.id,showfilepicker: this.canShowFilePicker,showdropzone: this.canShowDropZone,bodyTemplate: Selectors.IMAGE.template.body.insertImageBody,footerTemplate: Selectors.IMAGE.template.footer.insertImageFooter,selector: Selectors.IMAGE.type,};Promise.all([body(templateContext, this.root), footer(templateContext, this.root)]).then(() => {const imageinsert = new ImageInsert(this.root,this.editor,this.currentModal,this.canShowFilePicker,this.canShowDropZone,);imageinsert.init();return;}).catch(error => {window.console.log(error);});};async getTemplateContext(data) {return {elementid: this.editor.id,showfilepicker: this.canShowFilePicker,...data,};}async getCurrentImageData() {const selectedImageProperties = this.getSelectedImageProperties();if (!selectedImageProperties) {return {};}const properties = {...selectedImageProperties};if (properties.src) {properties.haspreview = true;}if (!properties.alt) {properties.presentation = true;}return properties;}/*** Asynchronously loads and previews an image from the provided URL.** @param {string} url - The URL of the image to load and preview.* @returns {Promise<void>}*/loadPreviewImage = async function(url) {this.startImageLoading();const image = new Image();image.src = url;image.addEventListener('error', async() => {const urlWarningLabelEle = this.root.querySelector(Selectors.IMAGE.elements.urlWarning);urlWarningLabelEle.innerHTML = await getString('imageurlrequired', 'tiny_media');showElements(Selectors.IMAGE.elements.urlWarning, this.root);this.stopImageLoading();});image.addEventListener('load', async() => {const currentImageData = await this.getCurrentImageData();let templateContext = await this.getTemplateContext(currentImageData);templateContext.sizecustomhelpicon = {text: await getString('sizecustom_help', 'tiny_media')};templateContext.bodyTemplate = Selectors.IMAGE.template.body.insertImageDetailsBody;templateContext.footerTemplate = Selectors.IMAGE.template.footer.insertImageDetailsFooter;templateContext.selector = Selectors.IMAGE.type;templateContext.maxlengthalt = MAX_LENGTH_ALT;Promise.all([body(templateContext, this.root), footer(templateContext, this.root)]).then(() => {this.stopImageLoading();return;}).then(() => {const imagedetails = new ImageDetails(this.root,this.editor,this.currentModal,this.canShowFilePicker,this.canShowDropZone,url,image,);imagedetails.init();return;}).catch(error => {window.console.log(error);});});};getSelectedImageProperties() {const image = this.getSelectedImage();if (!image) {this.selectedImage = null;return null;}const properties = {src: null,alt: null,width: null,height: null,presentation: false,customStyle: '', // Custom CSS styles applied to the image.};const getImageHeight = (image) => {if (!isPercentageValue(String(image.height))) {return parseInt(image.height, 10);}return image.height;};const getImageWidth = (image) => {if (!isPercentageValue(String(image.width))) {return parseInt(image.width, 10);}return image.width;};// Get the current selection.this.selectedImage = image;properties.customStyle = image.style.cssText;const width = getImageWidth(image);if (width !== 0) {properties.width = width;}const height = getImageHeight(image);if (height !== 0) {properties.height = height;}properties.src = image.getAttribute('src');properties.alt = image.getAttribute('alt') || '';properties.presentation = (image.getAttribute('role') === 'presentation');return properties;}getSelectedImage() {const imgElm = this.editor.selection.getNode();const figureElm = this.editor.dom.getParent(imgElm, 'figure.image');if (figureElm) {return this.editor.dom.select('img', figureElm)[0];}if (imgElm && (imgElm.nodeName.toUpperCase() !== 'IMG' || this.isPlaceholderImage(imgElm))) {return null;}return imgElm;}isPlaceholderImage(imgElm) {if (imgElm.nodeName.toUpperCase() !== 'IMG') {return false;}return (imgElm.hasAttribute('data-mce-object') || imgElm.hasAttribute('data-mce-placeholder'));}/*** Displays the upload loader and disables UI elements while loading a file.*/startImageLoading() {showElements(Selectors.IMAGE.elements.loaderIcon, this.root);hideElements(Selectors.IMAGE.elements.insertImage, this.root);}/*** Displays the upload loader and disables UI elements while loading a file.*/stopImageLoading() {hideElements(Selectors.IMAGE.elements.loaderIcon, this.root);showElements(Selectors.IMAGE.elements.insertImage, this.root);}}