ÿØÿà JFIF ÿÛ „ ( %"1!%)+...383,7(-.+
-+++--++++---+-+-----+---------------+---+-++7-----ÿÀ ß â" ÿÄ ÿÄ H !1AQaq"‘¡2B±ÁÑð#R“Ò Tbr‚²á3csƒ’ÂñDS¢³$CÿÄ ÿÄ % !1AQa"23‘ÿÚ ? ôÿ ¨pŸªáÿ —åYõõ\?àÒü©ŠÄï¨pŸªáÿ —åYõõ\?àÓü©ŠÄá 0Ÿªáÿ Ÿå[úƒ ú®ði~TÁbqÐ8OÕpÿ ƒOò¤Oè`–RÂáœá™êi€ßÉ< FtŸI“öÌ8úDf´°å}“¾œ6
öFá°y¥jñÇh†ˆ¢ã/ÃÐ:ªcÈ
"Y¡ðÑl>ÿ ”ÏËte:qž\oäŠe÷ó²·˜HT4&ÿ ÓÐü6ö®¿øþßèô Ÿ•7Ñi’•j|“ñì>b…þS?*Óôÿ ÓÐü*h¥£ír¶ü UãS炟[AÐaè[ûª•õ&õj?†Éö+EzP—WeÒírJFt ‘BŒ†Ï‡%#tE Øz ¥OÛ«!1›üä±Í™%ºÍãö]°î(–:@<‹ŒÊö×òÆt¦ãº+‡¦%Ìòh´OƒJŒtMÜ>ÀÜÊw3Y´•牋4ÇýÊTì>œú=Íwhyë,¾Ôò×õ¿ßÊa»«þˆÑªQ|%6ž™A õ%:øj<>É—ÿ Å_ˆCbõ¥š±ý¯Ýƒï…¶|RëócÍf溪“t.СøTÿ *Ä¿-{†çàczůŽ_–^XþŒ±miB[X±d 1,é”zEù»&
î9gœf™9Ð'.;—™i}!ôšåîqêÛ٤ёý£½ÆA–àôe"A$ËÚsäÿ
÷Û #°xŸëí(l
»ý3—¥5m!
rt`†0~'j2(]S¦¦kv,ÚÇl¦øJA£Šƒ
J3E8ÙiŽ:cÉžúeZ°€¯\®kÖ(79«Ž:¯X”¾³Š&¡* ….‰Ž(ÜíŸ2¥ª‡×Hi²TF¤ò[¨íÈRëÉä¢mgÑ.Ÿ<öäS0í„ǹÁU´f#Vß;Õ–…P@3ío<ä-±»Ž.L|kªÀê›fÂ6@»eu‚|ÓaÞÆŸ…¨ááå>åŠ?cKü6ùTÍÆ”†sĤÚ;H2RÚ†õ\Ö·Ÿn'¾ ñ#ºI¤Å´%çÁ‚â7›‹qT3Iï¨ÖÚ5I7Ë!ÅOóŸ¶øÝñØôת¦$Tcö‘[«Ö³šÒ';Aþ ¸èíg
A2Z"i¸vdÄ÷.iõ®§)¿]¤À†–‡É&ä{V¶iŽ”.Ó×Õÿ û?h¬Mt–íª[ÿ Ñÿ ÌV(í}=ibÔ¡›¥¢±b Lô¥‡piη_Z<‡z§èŒ)iÖwiÇ 2hÙ3·=’d÷8éŽ1¦¸c¤µ€7›7Ø ð\á)} ¹fËí›pAÃL%âc2 í§æQz¿;T8sæ°qø)QFMð‰XŒÂ±N¢aF¨…8¯!U Z©RÊ ÖPVÄÀÍin™Ì-GˆªÅËŠ›•zË}º±ŽÍFò¹}Uw×#ä5B¤{î}Ð<ÙD
é©¤&‡ïDbàÁôMÁ.// 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 .
/**
* Prefetch module to help lazily load content for use on the current page.
*
* @module core/prefetch
* @copyright 2020 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*
* @example Pre-fetching a set of strings to use later
*
* import prefetch from 'core/prefetch';
*
* // A single string prefetch.
* prefetch.prefetchString('error', 'cannotfindteacher');
*
* // Prefetch multiple strings in the same component.
* prefetch.prefetchStrings('core', [
* 'yes',
* 'no',
* ]);
*
* // Use the strings.
* import {getString, getStrings} from 'core/str';
* getString('cannotfindteacher', 'error')
* .then(str => {
* window.console.log(str); // Cannot find teacher
* })
* .catch();
* getStrings([
* {
* key: 'cannotfindteacher',
* component: 'error',
* },
* {
* key: 'yes',
* component: 'core',
* },
* {
* key: 'no',
* component: 'core',
* },
* ])
* .then((cannotFindTeacher, yes, no) => {
* window.console.log(cannotFindTeacher); // Cannot find teacher
* window.console.log(yes); // Yes
* window.console.log(no); // No
* })
* .catch();
*/
import Config from 'core/config';
// Keep track of whether the initial prefetch has occurred.
let initialPrefetchComplete = false;
// Prefetch templates.
let templateList = [];
// Prefetch strings.
let stringList = {};
let prefetchTimer;
/**
* Fetch all queued items in the queue.
*
* Should only be called via processQueue.
* @private
*/
const fetchQueue = () => {
// Prefetch templates.
if (templateList) {
const templatesToLoad = templateList.slice();
templateList = [];
import('core/templates')
.then(Templates => Templates.prefetchTemplates(templatesToLoad))
.catch();
}
// Prefetch strings.
const mappedStringsToFetch = stringList;
stringList = {};
const stringsToFetch = [];
Object.keys(mappedStringsToFetch).forEach(component => {
stringsToFetch.push(...mappedStringsToFetch[component].map(key => {
return {component, key};
}));
});
if (stringsToFetch) {
import('core/str')
.then(Str => Str.get_strings(stringsToFetch))
.catch();
}
};
/**
* Process the prefetch queues as required.
*
* The initial call will queue the first fetch after a delay.
* Subsequent fetches are immediate.
*
* @private
*/
const processQueue = () => {
if (prefetchTimer) {
// There is a live prefetch timer. The initial prefetch has been scheduled but is not complete.
return;
}
// The initial prefetch has compelted. Just queue as normal.
if (initialPrefetchComplete) {
fetchQueue();
return;
}
// Queue the initial prefetch in a short while.
prefetchTimer = setTimeout(() => {
initialPrefetchComplete = true;
prefetchTimer = null;
// Ensure that the icon system is loaded.
// This can be quite slow and delay UI interactions if it is loaded on demand.
import(Config.iconsystemmodule)
.then(IconSystem => {
const iconSystem = new IconSystem();
prefetchTemplate(iconSystem.getTemplateName());
return iconSystem;
})
.then(iconSystem => {
fetchQueue();
iconSystem.init();
return;
})
.catch();
}, 500);
};
/**
* Add a set of templates to the prefetch queue.
*
* @param {Array} templatesNames A list of the template names to fetch
* @static
*/
const prefetchTemplates = templatesNames => {
templateList = templateList.concat(templatesNames);
processQueue();
};
/**
* Add a single template to the prefetch queue.
*
* @param {String} templateName The template names to fetch
* @static
*/
const prefetchTemplate = templateName => {
prefetchTemplates([templateName]);
};
/**
* Add a set of strings from the same component to the prefetch queue.
*
* @param {String} component The component that all of the strings belongs to
* @param {String[]} keys An array of string identifiers.
* @static
*/
const prefetchStrings = (component, keys) => {
if (!stringList[component]) {
stringList[component] = [];
}
stringList[component] = stringList[component].concat(keys);
processQueue();
};
/**
* Add a single string to the prefetch queue.
*
* @param {String} component The component that the string belongs to
* @param {String} key The string identifier
* @static
*/
const prefetchString = (component, key) => {
if (!stringList[component]) {
stringList[component] = [];
}
stringList[component].push(key);
processQueue();
};
// Prefetch some commonly-used templates.
prefetchTemplates([].concat(
['core/loading'],
['core/modal'],
['core/modal_backdrop'],
));
// And some commonly used strings.
prefetchStrings('core', [
'cancel',
'closebuttontitle',
'loading',
'savechanges',
]);
prefetchStrings('core_form', [
'showless',
'showmore',
]);
export default {
prefetchTemplate,
prefetchTemplates,
prefetchString,
prefetchStrings,
};