MDL-62497 javascript: rewrite core/str using ES6 syntax
authorRyan Wyllie <ryan@ryanwyllie.com>
Thu, 12 Jul 2018 01:01:13 +0000 (09:01 +0800)
committerAndrew Nicols <andrew@nicols.co.uk>
Fri, 19 Jul 2019 06:12:49 +0000 (14:12 +0800)
lib/amd/build/str.min.js
lib/amd/build/str.min.js.map
lib/amd/src/str.js

index e66c691..45da245 100644 (file)
Binary files a/lib/amd/build/str.min.js and b/lib/amd/build/str.min.js differ
index 069a033..48670ed 100644 (file)
Binary files a/lib/amd/build/str.min.js.map and b/lib/amd/build/str.min.js.map differ
index 93ef0a1..e0ce6ea 100644 (file)
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  * @since      2.9
  */
-// Disable no-restriced-properties because M.str is expected here:
-/* eslint-disable no-restricted-properties */
-define(['jquery', 'core/ajax', 'core/localstorage'], function($, ajax, storage) {
-
-    var promiseCache = [];
-
-    return /** @alias module:core/str */ {
-        // Public variables and functions.
-        /**
-         * Return a promise object that will be resolved into a string eventually (maybe immediately).
-         *
-         * @method get_string
-         * @param {string} key The language string key
-         * @param {string} component The language string component
-         * @param {string} param The param for variable expansion in the string.
-         * @param {string} lang The users language - if not passed it is deduced.
-         * @return {Promise}
-         */
-         // eslint-disable-next-line camelcase
-        get_string: function(key, component, param, lang) {
-            var request = this.get_strings([{
-                key: key,
-                component: component,
-                param: param,
-                lang: lang
-            }]);
-
-            return request.then(function(results) {
-                return results[0];
-            });
-        },
-
-        /**
-         * Make a batch request to load a set of strings
-         *
-         * @method get_strings
-         * @param {Object[]} requests Array of { key: key, component: component, param: param, lang: lang };
-         *                                      See get_string for more info on these args.
-         * @return {Promise}
-         */
-         // eslint-disable-next-line camelcase
-        get_strings: function(requests) {
-
-            var deferred = $.Deferred();
-            var results = [];
-            var i = 0;
-            var missing = false;
-            var request;
-
-            // Try from local storage. If it's there - put it in M.str and resolve it.
-
-            for (i = 0; i < requests.length; i++) {
-                request = requests[i];
-                if (typeof request.lang === "undefined") {
-                    request.lang = $('html').attr('lang').replace(/-/g, '_');
-                }
-                request.cacheKey = 'core_str/' + request.key + '/' + request.component + '/' + request.lang;
-                if (typeof M.str[request.component] === "undefined" ||
-                        typeof M.str[request.component][request.key] === "undefined") {
-                    // Try and revive it from local storage.
-                    var cached = storage.get(request.cacheKey);
-                    if (cached) {
-                        if (typeof M.str[request.component] === "undefined") {
-                            M.str[request.component] = [];
-                        }
-                        M.str[request.component][request.key] = cached;
-                    } else {
-                        // It's really not here.
-                        missing = true;
-                    }
-                }
-            }
+import $ from 'jquery';
+import Ajax from 'core/ajax';
+import LocalStorage from 'core/localstorage';
+
+// Module cache for the promises so that we don't make multiple
+// unnecessary requests.
+let promiseCache = [];
+
+/**
+ * Return a promise object that will be resolved into a string eventually (maybe immediately).
+ *
+ * @method get_string
+ * @param {string} key The language string key
+ * @param {string} component The language string component
+ * @param {string} param The param for variable expansion in the string.
+ * @param {string} lang The users language - if not passed it is deduced.
+ * @return {Promise}
+ */
+export const get_string = (key, component, param, lang) => {
+    return get_strings([{key, component, param, lang}])
+        .then(results => results[0]);
+};
+
+/**
+ * Make a batch request to load a set of strings
+ *
+ * @method get_strings
+ * @param {Object[]} requests Array of { key: key, component: component, param: param, lang: lang };
+ *                                      See get_string for more info on these args.
+ * @return {Promise}
+ */
+export const get_strings = (requests) => {
+    let requestData = [];
+    const pageLang = $('html').attr('lang').replace(/-/g, '_');
+    // Helper function to construct the cache key.
+    const getCacheKey = ({key, component, lang = pageLang}) => `core_str/${key}/${component}/${lang}`;
+
+    const stringPromises = requests.map((request) => {
+        const cacheKey = getCacheKey(request);
+        const {component, key, lang} = request;
+        // Helper function to add the promise to cache.
+        const buildReturn = (promise) => {
+            // Make sure the promise cache contains our promise.
+            promiseCache[cacheKey] = promise;
+            return promise;
+        };
+
+        // Check if we can serve the string straight from M.str.
+        if (component in M.str && key in M.str[component]) {
+            return buildReturn(new Promise((resolve) => {
+                resolve(M.str[component][key]);
+            }));
+        }
+
+        // Check if the string is in the browser's local storage.
+        const cached = LocalStorage.get(cacheKey);
+        if (cached) {
+            M.str[component] = {...M.str[component], [key]: cached};
+            return buildReturn(new Promise((resolve) => {
+                resolve(M.str[component][key]);
+            }));
+        }
 
-            if (!missing) {
-                // We have all the strings already.
-                for (i = 0; i < requests.length; i++) {
-                    request = requests[i];
-
-                    results[i] = M.util.get_string(request.key, request.component, request.param);
-                }
-                deferred.resolve(results);
-            } else {
-                var ajaxrequests = [];
-                var fetchpromises = [];
-
-                // Done handler for ajax call. Must be bound to the current fetchpromise. We do this
-                // to avoid creating a function in a loop.
-                var doneFunc = function(str) {
-                    this.resolve(str);
-                };
-
-                var failFunc = function(reason) {
-                    this.reject(reason);
-                };
-
-                for (i = 0; i < requests.length; i++) {
-                    request = requests[i];
-
-                    // If we ever fetched this string with a promise, reuse it.
-                    if (typeof promiseCache[request.cacheKey] !== 'undefined') {
-                        fetchpromises.push(promiseCache[request.cacheKey]);
-                    } else {
-                        // Add this to the list we need to really fetch.
-                        var fetchpromise = $.Deferred();
-
-                        ajaxrequests.push({
-                            methodname: 'core_get_string',
-                            args: {
-                                stringid: request.key,
-                                component: request.component,
-                                lang: request.lang,
-                                stringparams: []
-                            },
-                            done: doneFunc.bind(fetchpromise),
-                            fail: failFunc.bind(fetchpromise)
-                        });
-
-                        promiseCache[request.cacheKey] = fetchpromise.promise();
-                        fetchpromises.push(promiseCache[request.cacheKey]);
-                    }
-                }
-
-                // Everything might already be queued so we need to check if we have real ajax requests to run.
-                if (ajaxrequests.length > 0) {
-                    ajax.call(ajaxrequests, true, false, false, 0, M.cfg.langrev);
-                }
-
-                $.when.apply(null, fetchpromises).done(
-                    function() {
-                        // Turn the list of arguments (unknown length) into a real array.
-                        var i = 0;
-                        for (i = 0; i < arguments.length; i++) {
-                            request = requests[i];
-                            // Cache all the string templates.
-                            if (typeof M.str[request.component] === "undefined") {
-                                M.str[request.component] = [];
-                            }
-                            M.str[request.component][request.key] = arguments[i];
-                            storage.set('core_str/' + request.key + '/' + request.component + '/' + request.lang, arguments[i]);
-                            // And set the results.
-                            results[i] = M.util.get_string(request.key, request.component, request.param).trim();
-                        }
-                        deferred.resolve(results);
-                    }
-                ).fail(
-                    function(ex) {
-                        deferred.reject(ex);
-                    }
-                );
+        // Check if we've already loaded this string from the server.
+        if (cacheKey in promiseCache) {
+            return buildReturn(promiseCache[cacheKey]);
+        } else {
+            // We're going to have to ask the server for the string so
+            // add this string to the list of requests to be sent.
+            return buildReturn(new Promise((resolve, reject) => {
+                requestData.push({
+                    methodname: 'core_get_string',
+                    args: {
+                        stringid: key,
+                        stringparams: [],
+                        component,
+                        lang,
+                    },
+                    done: (str) => {
+                        // When we get the response from the server
+                        // we should update M.str and the browser's
+                        // local storage before resolving this promise.
+                        M.str[component] = {...M.str[component], [key]: str};
+                        LocalStorage.set(cacheKey, str);
+                        resolve(str);
+                    },
+                    fail: reject
+                });
+            }));
+        }
+    });
+
+    if (requestData.length) {
+        // If we need to load any strings from the server then send
+        // off the request.
+        Ajax.call(requestData, true, false, false, 0, M.cfg.langrev);
+    }
+
+    // We need to use jQuery here because some calling code uses the
+    // .done handler instead of the .then handler.
+    return $.when.apply($, stringPromises)
+        .then((...strings) => strings);
+};
+
+/**
+ * Add a list of strings to the caches.
+ *
+ * @method cache_strings
+ * @param {Object[]} strings Array of { key: key, component: component, lang: lang, value: value }
+ */
+export const cache_strings = (strings) => {
+    const defaultLang = $('html').attr('lang').replace(/-/g, '_');
+
+    strings.forEach(({key, component, value, lang = defaultLang}) => {
+        const cacheKey = ['core_str', key, component, lang].join('/');
+
+        // Check M.str caching.
+        if (!(component in M.str) || !(key in M.str[component])) {
+            if (!(component in M.str)) {
+                M.str[component] = {};
             }
 
-            return deferred.promise();
-        },
-        /**
-         * Add a list of strings to the caches.
-         *
-         * @method cache_strings
-         * @param {Object[]} strings Array of { key: key, component: component, lang: lang, value: value }
-         */
-         // eslint-disable-next-line camelcase
-        cache_strings: function(strings) {
-            var defaultLang = $('html').attr('lang').replace(/-/g, '_');
-            strings.forEach(function(string) {
-                var lang = !(lang in string) ? defaultLang : string.lang;
-                var key = string.key;
-                var component = string.component;
-                var value = string.value;
-                var cacheKey = ['core_str', key, component, lang].join('/');
-
-                // Check M.str caching.
-                if (!(component in M.str) || !(key in M.str[component])) {
-                    if (!(component in M.str)) {
-                        M.str[component] = {};
-                    }
-
-                    M.str[component][key] = value;
-                }
-
-                // Check local storage.
-                if (!storage.get(cacheKey)) {
-                    storage.set(cacheKey, value);
-                }
-
-                // Check the promises cache.
-                if (!(cacheKey in promiseCache)) {
-                    promiseCache[cacheKey] = $.Deferred().resolve(value).promise();
-                }
-            });
+            M.str[component][key] = value;
+        }
+
+        // Check local storage.
+        if (!LocalStorage.get(cacheKey)) {
+            LocalStorage.set(cacheKey, value);
+        }
+
+        // Check the promises cache.
+        if (!(cacheKey in promiseCache)) {
+            promiseCache[cacheKey] = $.Deferred().resolve(value).promise();
         }
-    };
-});
+    });
+};