Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
 * Prefetch module to help lazily load content for use on the current page.
18
 *
19
 * @module     core/prefetch
20
 * @copyright  2020 Andrew Nicols <andrew@nicols.co.uk>
21
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22
 *
23
 * @example <caption>Pre-fetching a set of strings to use later</caption>
24
 *
25
 * import prefetch from 'core/prefetch';
26
 *
27
 * // A single string prefetch.
28
 * prefetch.prefetchString('error', 'cannotfindteacher');
29
 *
30
 * // Prefetch multiple strings in the same component.
31
 * prefetch.prefetchStrings('core', [
32
 *     'yes',
33
 *     'no',
34
 * ]);
35
 *
36
 * // Use the strings.
37
 * import {getString, getStrings} from 'core/str';
38
 * getString('cannotfindteacher', 'error')
39
 * .then(str => {
40
 *     window.console.log(str); // Cannot find teacher
41
 * })
42
 * .catch();
43
 * getStrings([
44
 *     {
45
 *         key: 'cannotfindteacher',
46
 *         component: 'error',
47
 *     },
48
 *     {
49
 *         key: 'yes',
50
 *         component: 'core',
51
 *     },
52
 *     {
53
 *         key: 'no',
54
 *         component: 'core',
55
 *     },
56
 * ])
57
 * .then((cannotFindTeacher, yes, no) => {
58
 *     window.console.log(cannotFindTeacher); // Cannot find teacher
59
 *     window.console.log(yes); // Yes
60
 *     window.console.log(no); // No
61
 * })
62
 * .catch();
63
 */
64
import Config from 'core/config';
65
 
66
// Keep track of whether the initial prefetch has occurred.
67
let initialPrefetchComplete = false;
68
 
69
// Prefetch templates.
70
let templateList = [];
71
 
72
// Prefetch strings.
73
let stringList = {};
74
 
75
let prefetchTimer;
76
 
77
/**
78
 * Fetch all queued items in the queue.
79
 *
80
 * Should only be called via processQueue.
81
 * @private
82
 */
83
const fetchQueue = () => {
84
    // Prefetch templates.
85
    if (templateList) {
86
        const templatesToLoad = templateList.slice();
87
        templateList = [];
88
        import('core/templates')
89
        .then(Templates => Templates.prefetchTemplates(templatesToLoad))
90
        .catch();
91
    }
92
 
93
    // Prefetch strings.
94
    const mappedStringsToFetch = stringList;
95
    stringList = {};
96
 
97
    const stringsToFetch = [];
98
    Object.keys(mappedStringsToFetch).forEach(component => {
99
        stringsToFetch.push(...mappedStringsToFetch[component].map(key => {
100
            return {component, key};
101
        }));
102
    });
103
 
104
    if (stringsToFetch) {
105
        import('core/str')
106
        .then(Str => Str.get_strings(stringsToFetch))
107
        .catch();
108
    }
109
};
110
 
111
/**
112
 * Process the prefetch queues as required.
113
 *
114
 * The initial call will queue the first fetch after a delay.
115
 * Subsequent fetches are immediate.
116
 *
117
 * @private
118
 */
119
const processQueue = () => {
120
    if (prefetchTimer) {
121
        // There is a live prefetch timer. The initial prefetch has been scheduled but is not complete.
122
        return;
123
    }
124
 
125
    // The initial prefetch has compelted. Just queue as normal.
126
    if (initialPrefetchComplete) {
127
        fetchQueue();
128
 
129
        return;
130
    }
131
 
132
    // Queue the initial prefetch in a short while.
133
    prefetchTimer = setTimeout(() => {
134
        initialPrefetchComplete = true;
135
        prefetchTimer = null;
136
 
137
        // Ensure that the icon system is loaded.
138
        // This can be quite slow and delay UI interactions if it is loaded on demand.
139
        import(Config.iconsystemmodule)
140
        .then(IconSystem => {
141
            const iconSystem = new IconSystem();
142
            prefetchTemplate(iconSystem.getTemplateName());
143
 
144
            return iconSystem;
145
        })
146
        .then(iconSystem => {
147
            fetchQueue();
148
            iconSystem.init();
149
 
150
            return;
151
        })
152
        .catch();
153
    }, 500);
154
};
155
 
156
/**
157
 * Add a set of templates to the prefetch queue.
158
 *
159
 * @param {Array} templatesNames A list of the template names to fetch
160
 * @static
161
 */
162
const prefetchTemplates = templatesNames => {
163
    templateList = templateList.concat(templatesNames);
164
 
165
    processQueue();
166
};
167
 
168
/**
169
 * Add a single template to the prefetch queue.
170
 *
171
 * @param {String} templateName The template names to fetch
172
 * @static
173
 */
174
const prefetchTemplate = templateName => {
175
    prefetchTemplates([templateName]);
176
};
177
 
178
/**
179
 * Add a set of strings from the same component to the prefetch queue.
180
 *
181
 * @param {String} component The component that all of the strings belongs to
182
 * @param {String[]} keys An array of string identifiers.
183
 * @static
184
 */
185
const prefetchStrings = (component, keys) => {
186
    if (!stringList[component]) {
187
        stringList[component] = [];
188
    }
189
 
190
    stringList[component] = stringList[component].concat(keys);
191
 
192
    processQueue();
193
};
194
 
195
/**
196
 * Add a single string to the prefetch queue.
197
 *
198
 * @param {String} component The component that the string belongs to
199
 * @param {String} key The string identifier
200
 * @static
201
 */
202
const prefetchString = (component, key) => {
203
    if (!stringList[component]) {
204
        stringList[component] = [];
205
    }
206
 
207
    stringList[component].push(key);
208
 
209
    processQueue();
210
};
211
 
212
// Prefetch some commonly-used templates.
213
prefetchTemplates([].concat(
214
    ['core/loading'],
215
    ['core/modal'],
216
    ['core/modal_backdrop'],
217
));
218
 
219
// And some commonly used strings.
220
prefetchStrings('core', [
221
    'cancel',
222
    'closebuttontitle',
223
    'loading',
224
    'savechanges',
225
]);
226
prefetchStrings('core_form', [
227
    'showless',
228
    'showmore',
229
]);
230
 
231
export default {
232
    prefetchTemplate,
233
    prefetchTemplates,
234
    prefetchString,
235
    prefetchStrings,
236
};