Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 1
// This file is part of Moodle - http://moodle.org/
2
//
3
// Moodle is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, either version 3 of the License, or
6
// (at your option) any later version.
7
//
8
// Moodle is distributed in the hope that it will be useful,
9
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
// GNU General Public License for more details.
12
//
13
// You should have received a copy of the GNU General Public License
14
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
15
 
16
/**
17
 * Tiny media plugin helpers for image and embed.
18
 *
19
 * @module      tiny_media/helpers
20
 * @copyright   2024 Stevani Andolo <stevani@hotmail.com.au>
21
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22
 */
23
 
24
import Templates from 'core/templates';
25
import Selectors from './selectors';
26
import Config from 'core/config';
27
 
28
/**
29
 * Renders and inserts the body template for inserting an media into the modal.
30
 *
31
 * @param {object} templateContext - The context for rendering the template.
32
 * @param {HTMLElement} root - The root element where the template will be inserted.
33
 * @returns {Promise<void>}
34
 */
35
export const body = async(templateContext, root) => {
36
    return Templates.renderForPromise(templateContext.bodyTemplate, {...templateContext})
37
    .then(({html, js}) => {
38
        Templates.replaceNodeContents(root.querySelector(Selectors[templateContext.selector].elements.bodyTemplate), html, js);
39
        return;
40
    })
41
    .catch(error => {
42
        window.console.log(error);
43
    });
44
};
45
 
46
/**
47
 * Renders and inserts the footer template for inserting an media into the modal.
48
 *
49
 * @param {object} templateContext - The context for rendering the template.
50
 * @param {HTMLElement} root - The root element where the template will be inserted.
51
 * @returns {Promise<void>}
52
 */
53
export const footer = async(templateContext, root) => {
54
    return Templates.renderForPromise(templateContext.footerTemplate, {...templateContext})
55
    .then(({html, js}) => {
56
        Templates.replaceNodeContents(root.querySelector(Selectors[templateContext.selector].elements.footerTemplate), html, js);
57
        return;
58
    })
59
    .catch(error => {
60
        window.console.log(error);
61
    });
62
};
63
 
64
/**
65
 * Set extra properties on an instance using incoming data.
66
 *
67
 * @param {object} instance
68
 * @param {object} data
69
 * @return {object} Modified instance
70
 */
71
export const setPropertiesFromData = async(instance, data) => {
72
    for (const property in data) {
73
        if (typeof data[property] !== 'function') {
74
            instance[property] = data[property];
75
        }
76
    }
77
    return instance;
78
};
79
 
80
/**
81
 * Check if given string is a valid URL.
82
 *
83
 * @param {String} urlString URL the link will point to.
84
 * @returns {boolean} True is valid, otherwise false.
85
 */
86
export const isValidUrl = urlString => {
87
    const urlPattern = new RegExp('^(https?:\\/\\/)?' + // Protocol.
88
                                '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // Domain name.
89
                                '((\\d{1,3}\\.){3}\\d{1,3})|localhost)' + // OR ip (v4) address, localhost.
90
                                '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'); // Port and path.
91
    return !!urlPattern.test(urlString);
92
};
93
 
94
/**
95
 * Hide the element(s).
96
 *
97
 * @param {string|string[]} elements - The CSS selector for the elements to toggle.
98
 * @param {object} root - The CSS selector for the elements to toggle.
99
 */
100
export const hideElements = (elements, root) => {
101
    if (elements instanceof Array) {
102
        elements.forEach((elementSelector) => {
103
            const element = root.querySelector(elementSelector);
104
            if (element) {
105
                element.classList.add('d-none');
106
            }
107
        });
108
    } else {
109
        const element = root.querySelector(elements);
110
        if (element) {
111
            element.classList.add('d-none');
112
        }
113
    }
114
};
115
 
116
/**
117
 * Show the element(s).
118
 *
119
 * @param {string|string[]} elements - The CSS selector for the elements to toggle.
120
 * @param {object} root - The CSS selector for the elements to toggle.
121
 */
122
export const showElements = (elements, root) => {
123
    if (elements instanceof Array) {
124
        elements.forEach((elementSelector) => {
125
            const element = root.querySelector(elementSelector);
126
            if (element) {
127
                element.classList.remove('d-none');
128
            }
129
        });
130
    } else {
131
        const element = root.querySelector(elements);
132
        if (element) {
133
            element.classList.remove('d-none');
134
        }
135
    }
136
};
137
 
138
/**
139
 * Displays the upload loader and disables UI elements while loading a file.
140
 *
141
 * @param {html} root Modal element
142
 * @param {string} selector String of type IMAGE/EMBED
143
 */
144
export const startMediaLoading = (root, selector) => {
145
    showElements(Selectors[selector].elements.loaderIcon, root);
146
    const elementsToHide = [
147
        Selectors[selector].elements.insertMedia,
148
        Selectors[selector].elements.urlWarning,
149
        Selectors[selector].elements.modalFooter,
150
    ];
151
    hideElements(elementsToHide, root);
152
};
153
 
154
/**
155
 * Hide the upload loader and enable UI elements when loaded.
156
 *
157
 * @param {html} root Modal element
158
 * @param {string} selector String of type IMAGE/EMBED
159
 */
160
export const stopMediaLoading = (root, selector) => {
161
    hideElements(Selectors[selector].elements.loaderIcon, root);
162
    const elementsToShow = [
163
        Selectors[selector].elements.insertMedia,
164
        Selectors[selector].elements.modalFooter,
165
    ];
166
    showElements(elementsToShow, root);
167
};
168
 
169
/**
170
 * Return true or false if the url is external.
171
 *
172
 * @param {string} url
173
 * @returns {boolean} True if the URL is external, otherwise false.
174
 */
175
export const isExternalUrl = (url) => {
176
    const regex = new RegExp(`${Config.wwwroot}`);
177
 
178
    // True if the URL is from external, otherwise false.
179
    return regex.test(url) === false;
180
};
181
 
182
/**
183
 * Set the string for the URL label element.
184
 *
185
 * @param {object} props - The label text to set.
186
 */
187
export const setFilenameLabel = (props) => {
188
    const urlLabelEle = props.root.querySelector(props.fileNameSelector);
189
    if (urlLabelEle) {
190
        urlLabelEle.innerHTML = props.label;
191
        urlLabelEle.setAttribute("title", props.label);
192
    }
193
};
194
 
195
/**
196
 * This function checks whether an image URL is local (within the same website's domain) or external (from an external source).
197
 * Depending on the result, it dynamically updates the visibility and content of HTML elements in a user interface.
198
 * If the image is local then we only show it's filename.
199
 * If the image is external then it will show full URL and it can be updated.
200
 *
201
 * @param {object} props
202
 */
203
export const sourceTypeChecked = (props) => {
204
    if (props.fetchedTitle) {
205
        props.label = props.fetchedTitle;
206
    } else {
207
        if (!isExternalUrl(props.source)) {
208
            // Split the URL by '/' to get an array of segments.
209
            const segments = props.source.split('/');
210
            // Get the last segment, which should be the filename.
211
            const filename = segments.pop().split('?')[0];
212
            // Show the file name.
213
            props.label = decodeURI(filename);
214
        } else {
215
            props.label = decodeURI(props.source);
216
        }
217
    }
218
    setFilenameLabel(props);
219
};
220
 
221
/**
222
 * Get filename from the name label.
223
 *
224
 * @param {string} fileLabel
225
 * @returns {string}
226
 */
227
export const getFileName = (fileLabel) => {
228
    if (fileLabel.includes('/')) {
229
        const split = fileLabel.split('/');
230
        let fileName = split[split.length - 1];
231
        fileName = fileName.split('.');
232
        if (fileName.length > 1) {
233
            return decodeURI(fileName.slice(0, (fileName.length - 1)).join('.'));
234
        } else {
235
            return decodeURI(fileName[0]);
236
        }
237
    } else {
238
        return decodeURI(fileLabel.split('.')[0]);
239
    }
240
};
241
 
242
/**
243
 * Return true or false if % is found.
244
 *
245
 * @param {string} value
246
 * @returns {boolean}
247
 */
248
export const isPercentageValue = (value) => {
249
    return value.match(/\d+%/);
250
};