diff --git a/tools/cldr-apps/js/src/esm/cldrSideways.mjs b/tools/cldr-apps/js/src/esm/cldrSideways.mjs index 35ddbaebb24..30f8441a740 100644 --- a/tools/cldr-apps/js/src/esm/cldrSideways.mjs +++ b/tools/cldr-apps/js/src/esm/cldrSideways.mjs @@ -8,10 +8,10 @@ import * as cldrLoad from "./cldrLoad.mjs"; import * as cldrStatus from "./cldrStatus.mjs"; import * as cldrSurvey from "./cldrSurvey.mjs"; -const SIDEWAYS_DEBUG = true; +const SIDEWAYS_DEBUG = false; -const escape = "\u00A0\u00A0\u00A0"; // non-breaking spaces -const unequalSign = "\u2260\u00A0"; // U+2260 = "≠" +const NON_BREAKING_SPACES = "\u00A0\u00A0\u00A0"; // non-breaking spaces +const UNEQUALS_SIGN = "\u2260\u00A0"; // U+2260 = "≠" /** * Array storing all only-1 sublocales @@ -19,16 +19,37 @@ const unequalSign = "\u2260\u00A0"; // U+2260 = "≠" const oneLocales = []; /** - * Timeout for showing sideways view + * Ordinarily, wait a couple seconds before fetching the data for the menu. + * One reason for this delay is that the Info Panel is often shown for a given + * row only briefly before the user moves on to the next row, and there's a + * performance penalty if the data is fetched unnecessarily. At the end of the + * delay, if the current row has changed, the fetch will be cancelled. + * However, when the user chooses a related locale from the menu, there + * should be no delay. */ -let sidewaysShowTimeout = -1; +const USUAL_DELAY_MILLISECONDS = 2000; +const ZERO_DELAY_MILLISECONDS = 0; + +let fetchDelayMilliseconds = USUAL_DELAY_MILLISECONDS; + +/** + * Timeout ID for fetching and showing the menu + */ +let sidewaysShowTimeoutId = -1; const sidewaysCache = new cldrCache.LRU(); +let locmap = null; + +let curLocale = null; + function loadMenu(regionalVariantsWrapper, xpstrid) { - const curLocale = cldrStatus.getCurrentLocale(); + if (!locmap) { + locmap = cldrLoad.getTheLocaleMap(); + } + curLocale = cldrStatus.getCurrentLocale(); if (!curLocale || oneLocales[curLocale] || !xpstrid) { - regionalVariantsWrapper.setData(null); + regionalVariantsWrapper.setData(null, null); if (SIDEWAYS_DEBUG) { console.log("cldrSideways.loadMenu, nothing to display"); } @@ -40,24 +61,19 @@ function loadMenu(regionalVariantsWrapper, xpstrid) { if (SIDEWAYS_DEBUG) { console.log("cldrSideways.loadMenu, using cached data"); } - regionalVariantsWrapper.setData(cachedData); + regionalVariantsWrapper.setData(curLocale, cachedData); } else { if (SIDEWAYS_DEBUG) { console.log("cldrSideways.loadMenu, fetching new data"); } - fetchAndLoadMenu(regionalVariantsWrapper, curLocale, xpstrid, cacheKey); + fetchAndLoadMenu(regionalVariantsWrapper, xpstrid, cacheKey); } } -function fetchAndLoadMenu( - regionalVariantsWrapper, - curLocale, - xpstrid, - cacheKey -) { +function fetchAndLoadMenu(regionalVariantsWrapper, xpstrid, cacheKey) { clearMyTimeout(); regionalVariantsWrapper.setLoading(); - sidewaysShowTimeout = window.setTimeout(function () { + sidewaysShowTimeoutId = window.setTimeout(function () { clearMyTimeout(); if ( curLocale !== cldrStatus.getCurrentLocale() || @@ -77,14 +93,15 @@ function fetchAndLoadMenu( setMenuFromData(regionalVariantsWrapper, json, cacheKey); } ); - }, 2000); // wait 2 seconds before loading this. + }, fetchDelayMilliseconds); + fetchDelayMilliseconds = USUAL_DELAY_MILLISECONDS; } function clearMyTimeout() { - if (sidewaysShowTimeout != -1) { + if (sidewaysShowTimeoutId != -1) { // https://www.w3schools.com/jsref/met_win_clearinterval.asp - window.clearInterval(sidewaysShowTimeout); - sidewaysShowTimeout = -1; + window.clearInterval(sidewaysShowTimeoutId); + sidewaysShowTimeoutId = -1; } } @@ -121,115 +138,131 @@ function setMenuFromData(regionalVariantsWrapper, json, cacheKey) { } // if there is 1 sublocale (+ 1 default), show nothing if (Object.keys(relatedLocales).length <= 2) { - oneLocales[cldrStatus.getCurrentLocale()] = true; - regionalVariantsWrapper.setData(null); + oneLocales[curLocale] = true; + regionalVariantsWrapper.setData(null, null); } else { if (!json.others) { - regionalVariantsWrapper.setData(null); + regionalVariantsWrapper.setData(null, null); } else { - const topLocale = json.topLocale; - const locmap = cldrLoad.getTheLocaleMap(); - const curLocaleName = locmap.getRegionAndOrVariantName(topLocale); - let readLocale = null; - - // merge the read-only sublocale to base locale - var mergeReadBase = function mergeReadBase(list) { - let baseValue = null; - // find the base locale, remove it and store its value - for (let l = 0; l < list.length; l++) { - const loc = list[l][0]; - if (loc === topLocale) { - baseValue = list[l][1]; - list.splice(l, 1); - break; - } - } - - // replace the default locale(read-only) with base locale, store its name for label - for (let l = 0; l < list.length; l++) { - const loc = list[l][0]; - const bund = locmap.getLocaleInfo(loc); - if (bund && bund.readonly) { - readLocale = locmap.getRegionAndOrVariantName(loc); - list[l][0] = topLocale; - list[l][1] = baseValue; - break; - } - } - }; - - // compare all sublocale values - function appendLocaleList(list, curValue) { - popupSelect.label = "Regional Variants for " + curLocaleName; - - for (let l = 0; l < list.length; l++) { - const loc = list[l][0]; - const title = list[l][1]; - const item = { value: loc }; - let str = locmap.getRegionAndOrVariantName(loc); - if (loc === topLocale) { - str += " (= " + readLocale + ")"; - } - - if (loc === cldrStatus.getCurrentLocale()) { - str = escape + str; - item.disabled = true; - } else if (title != curValue) { - str = unequalSign + str; - item.disabled = false; - } else { - str = escape + str; - item.disabled = false; - } - item.str = str; - popupSelect.items.push(item); - } - } + setMenuFromNontrivialData(regionalVariantsWrapper, json, cacheKey); + } + } +} - const dataList = []; - const popupSelect = {}; - popupSelect.items = []; - for (let s in json.others) { - for (let t in json.others[s]) { - dataList.push([json.others[s][t], s]); - } - } +function setMenuFromNontrivialData(regionalVariantsWrapper, json, cacheKey) { + const dataList = initializeDataList(json.others); + const curValue = getCurrentValue(dataList); - /* - * Set curValue = the value for cldrStatus.getCurrentLocale() - */ - let curValue = null; - for (let l = 0; l < dataList.length; l++) { - const loc = dataList[l][0]; - if (loc === cldrStatus.getCurrentLocale()) { - curValue = dataList[l][1]; - break; - } - } - /* - * Force the use of unequalSign in the regional comparison pop-up for locales in - * json.novalue, by assigning a value that's different from curValue. - */ - if (json.novalue) { - const differentValue = curValue === "A" ? "B" : "A"; // anything different from curValue - for (let s in json.novalue) { - dataList.push([json.novalue[s], differentValue]); - } - } - mergeReadBase(dataList); + /* + * Force the use of unequalSign in the regional comparison pop-up for locales in + * json.novalue, by assigning a value that's different from curValue. + */ + if (json.novalue) { + const differentValue = curValue === "A" ? "B" : "A"; // anything different from curValue + for (let s in json.novalue) { + dataList.push([json.novalue[s], differentValue]); + } + } + const readLocale = mergeReadBase(dataList, json.topLocale); - // then sort by sublocale name - const sortedDataList = dataList.sort(function (a, b) { - return ( - locmap.getRegionAndOrVariantName(a[0]) > - locmap.getRegionAndOrVariantName(b[0]) - ); - }); - appendLocaleList(sortedDataList, curValue); - sidewaysCache.set(cacheKey, popupSelect); - regionalVariantsWrapper.setData(popupSelect); + // then sort by sublocale name + const sortedDataList = dataList.sort(function (a, b) { + return ( + locmap.getRegionAndOrVariantName(a[0]) > + locmap.getRegionAndOrVariantName(b[0]) + ); + }); + const popupSelect = appendLocaleList( + sortedDataList, + curValue, + json.topLocale, + readLocale + ); + sidewaysCache.set(cacheKey, popupSelect); + regionalVariantsWrapper.setData(curLocale, popupSelect); +} + +function initializeDataList(others) { + const dataList = []; + for (let s in others) { + for (let t in others[s]) { + dataList.push([others[s][t], s]); } } + return dataList; +} + +/** + * Get the value for the current locale + */ +function getCurrentValue(dataList) { + for (let l = 0; l < dataList.length; l++) { + const loc = dataList[l][0]; + if (loc === curLocale) { + return dataList[l][1]; + } + } + return null; +} + +// merge the read-only sublocale to base locale +function mergeReadBase(list, topLocale) { + let readLocale = null; + let baseValue = null; + // find the base locale, remove it and store its value + for (let l = 0; l < list.length; l++) { + const loc = list[l][0]; + if (loc === topLocale) { + baseValue = list[l][1]; + list.splice(l, 1); + break; + } + } + + // replace the default locale(read-only) with base locale, store its name for label + for (let l = 0; l < list.length; l++) { + const loc = list[l][0]; + const bund = locmap.getLocaleInfo(loc); + if (bund && bund.readonly) { + readLocale = locmap.getRegionAndOrVariantName(loc); + list[l][0] = topLocale; + list[l][1] = baseValue; + break; + } + } + return readLocale; +} + +function appendLocaleList(list, curValue, topLocale, readLocale) { + const popupSelect = { + items: [], + label: + "Regional Variants for " + locmap.getRegionAndOrVariantName(topLocale), + }; + // compare all sublocale values + for (let l = 0; l < list.length; l++) { + const loc = list[l][0]; + const title = list[l][1]; + const item = { value: loc }; + let str = locmap.getRegionAndOrVariantName(loc); + if (loc === topLocale) { + str += " (= " + readLocale + ")"; + } + + if (loc === curLocale) { + str = NON_BREAKING_SPACES + str; + item.disabled = true; + } else if (title != curValue) { + str = UNEQUALS_SIGN + str; + item.disabled = false; + } else { + str = NON_BREAKING_SPACES + str; + item.disabled = false; + } + item.str = str; + popupSelect.items.push(item); + } + return popupSelect; } function makeCacheKey(curLocale, xpstrid) { @@ -240,4 +273,10 @@ function clearCache() { sidewaysCache.clear(); } -export { clearCache, loadMenu }; +function goToLocale(localeId) { + cldrStatus.setCurrentLocale(localeId); + cldrLoad.reloadV(); + fetchDelayMilliseconds = ZERO_DELAY_MILLISECONDS; +} + +export { clearCache, goToLocale, loadMenu }; diff --git a/tools/cldr-apps/js/src/views/InfoRegionalVariants.vue b/tools/cldr-apps/js/src/views/InfoRegionalVariants.vue index 57ea725e21f..7d00b8d6ff4 100644 --- a/tools/cldr-apps/js/src/views/InfoRegionalVariants.vue +++ b/tools/cldr-apps/js/src/views/InfoRegionalVariants.vue @@ -11,7 +11,7 @@