From 265767d20f9e4c6a7e8a19b0f41d65de2a30c945 Mon Sep 17 00:00:00 2001 From: Tom Bishop Date: Tue, 9 Jul 2024 15:31:08 -0400 Subject: [PATCH] CLDR-17759 Move non-Info-Panel code from cldrInfo to cldrTable (#3858) --- tools/cldr-apps/js/src/esm/cldrInfo.mjs | 113 ++--------------------- tools/cldr-apps/js/src/esm/cldrTable.mjs | 102 ++++++++++++++++++-- tools/cldr-apps/js/src/esm/cldrVote.mjs | 4 +- 3 files changed, 104 insertions(+), 115 deletions(-) diff --git a/tools/cldr-apps/js/src/esm/cldrInfo.mjs b/tools/cldr-apps/js/src/esm/cldrInfo.mjs index 9d107b6209a..d9a39f1887e 100644 --- a/tools/cldr-apps/js/src/esm/cldrInfo.mjs +++ b/tools/cldr-apps/js/src/esm/cldrInfo.mjs @@ -3,7 +3,6 @@ */ import * as cldrDeferHelp from "./cldrDeferHelp.mjs"; import * as cldrDom from "./cldrDom.mjs"; -import * as cldrEvent from "./cldrEvent.mjs"; import * as cldrForumPanel from "./cldrForumPanel.mjs"; import * as cldrLoad from "./cldrLoad.mjs"; import * as cldrNotify from "./cldrNotify.mjs"; @@ -28,7 +27,6 @@ let panelInitialized = false; let panelVisible = false; let unShow = null; -let lastShown = null; let selectedItemWrapper = null; let regionalVariantsWrapper = null; @@ -161,48 +159,6 @@ function updateOpenPanelButtons() { }); } -/** - * Make the object "theObj" cause the info window to show when clicked. - * - * @param {String} str the string to display - * @param {Node} tr the TR element that is clicked - * @param {Node} theObj to listen to, a.k.a. "hideIfLast" - * @param {Function} fn the draw function - */ -// TODO: simplify this and related code to enable a cleaner and better organized -// appearance using modern components. The fn parameter (a.k.a. showFn) shouldn't -// need to be preconstructed for each item in each row, attached to DOM elements, -// and passed around as a parameter in such a complicated way. -// Reference: https://unicode-org.atlassian.net/browse/CLDR-7536 -// Currently this method is called as follows: -// cldrTable.mjs: cldrInfo.listen("", tr, cell, null); -// cldrTable.mjs: cldrInfo.listen(JSON.stringify(theRow), tr, js, null); -// cldrTable.mjs: cldrInfo.listen("", tr, cell, null); -// cldrTable.mjs: cldrInfo.listen(null, tr, cell, null); -// cldrTable.mjs: cldrInfo.listen(null, tr, cell, cell.showFn); -// cldrTable.mjs: cldrInfo.listen(null, tr, cell); -// cldrTable.mjs: cldrInfo.listen(historyText, tr, historyTag, null); -// cldrTable.mjs: cldrInfo.listen(null, tr, div, td.showFn); -// cldrTable.mjs: cldrInfo.listen(null, tr, noCell); -// cldrVote.mjs: cldrInfo.listen(null, tr, ourDiv, ourShowFn); -function listen(str, tr, theObj, fn) { - cldrDom.listenFor(theObj, "click", function (e) { - if (panelShouldBeShown()) { - show(str, tr, theObj /* hideIfLast */, fn); - } else if (tr?.sethash) { - // These methods, updateCurrentId and setLastShown may be called from show(), if - // panelShouldBeShown() returned true. If the Info Panel is hidden then they still - // need to be called. Since they don't involve the Info Panel, the implementation - // should be changed to make them independent of the Info Panel and they should be - // called from a different module, not cldrInfo. - cldrLoad.updateCurrentId(tr.sethash); - setLastShown(theObj); - } - cldrEvent.stopPropagation(e); - return false; - }); -} - // This method is now only used for getGuidanceMessage, for the Page table // before any row has been selected. Avoid using it for anything else. // cldrLoad.mjs: cldrInfo.showMessage(getGuidanceMessage(json.canModify)); @@ -212,11 +168,10 @@ function showMessage(str) { } } -// TODO: simplify, similar problems to cldrInfo.listen. Reference: https://unicode-org.atlassian.net/browse/CLDR-7536 -// Currently called as follows: -// cldrLoad.mjs: cldrInfo.showRowObjFunc(xtr, xtr.proposedcell, xtr.proposedcell.showFn); -// cldrTable.mjs: cldrInfo.showRowObjFunc(tr, tr.proposedcell, tr.proposedcell.showFn); -// cldrVote.mjs: cldrInfo.showRowObjFunc(tr, ourDiv, ourShowFn); +// Major tech debt here. Currently called as follows: +// cldrLoad.mjs: cldrInfo.showRowObjFunc(xtr, xtr.proposedcell, xtr.proposedcell.showFn); +// cldrTable.mjs: cldrInfo.showRowObjFunc(tr, tr.proposedcell, tr.proposedcell.showFn); +// cldrVote.mjs: cldrInfo.showRowObjFunc(tr, ourDiv, ourShowFn); function showRowObjFunc(tr, hideIfLast, fn) { if (panelShouldBeShown()) { show(null, tr, hideIfLast, fn); @@ -257,10 +212,12 @@ function show(str, tr, hideIfLast, fn) { unShow(); unShow = null; } + // Ideally, updateCurrentId and setLastShown should be called from cldrTable, not cldrInfo, + // however it's not clear whether they need to be called after openPanel and unShow if (tr?.sethash) { cldrLoad.updateCurrentId(tr.sethash); } - setLastShown(hideIfLast); + cldrTable.setLastShown(hideIfLast); addDeferredHelp(tr?.theRow); // if !tr.theRow, erase (as when click Next/Previous) addPlaceholderHelp(tr?.theRow); // ditto addInfoMessage(str); @@ -519,38 +476,6 @@ function addVoterInfoHover() { ); } -function setLastShown(obj) { - if (lastShown && obj != lastShown) { - cldrDom.removeClass(lastShown, "pu-select"); - const partr = parentOfType("TR", lastShown); - if (partr) { - cldrDom.removeClass(partr, "selectShow"); - } - } - if (obj) { - cldrDom.addClass(obj, "pu-select"); - const partr = parentOfType("TR", obj); - if (partr) { - cldrDom.addClass(partr, "selectShow"); - } - } - lastShown = obj; -} - -function reset() { - lastShown = null; -} - -function parentOfType(tag, obj) { - if (!obj) { - return null; - } - if (obj.nodeName === tag) { - return obj; - } - return parentOfType(tag, obj.parentElement); -} - /** * Update the vote info for this row. * @@ -965,25 +890,6 @@ function createVoter(v) { return div; } -/** - * Return a function that will show info for the given item in the Info Panel. - * - * @param {Object} theRow the data row - * @param {JSON} item JSON of the specific candidate item we are adding - * @returns the function - * - * Called only by cldrTable.addVitem, as follows: - * - * td.showFn = item.showFn = cldrInfo.showItemInfoFn(theRow, item); - * ... - * cldrInfo.listen(null, tr, div, td.showFn); - */ -function showItemInfoFn(theRow, item) { - return function (td) { - theRow.selectedItem = item; - }; -} - function getItemDescription(itemClass, inheritedLocale) { /* * itemClass may be "winner, "alias", "fallback", "fallback_code", "fallback_root", or "loser". @@ -1016,9 +922,8 @@ export { clearCachesAndReload, closePanel, initialize, - listen, - reset, - showItemInfoFn, + panelShouldBeShown, + show, showMessage, showRowObjFunc, updateRowVoteInfo, diff --git a/tools/cldr-apps/js/src/esm/cldrTable.mjs b/tools/cldr-apps/js/src/esm/cldrTable.mjs index f9d34a173e9..104fea7f26b 100644 --- a/tools/cldr-apps/js/src/esm/cldrTable.mjs +++ b/tools/cldr-apps/js/src/esm/cldrTable.mjs @@ -39,6 +39,8 @@ const NO_WINNING_VALUE = "no-winning-value"; */ const EMPTY_ELEMENT_VALUE = "❮EMPTY❯"; +let lastShown = null; + /** * Prepare rows to be inserted into the table * @@ -658,7 +660,7 @@ function updateRowStatusCell(tr, theRow, cell) { cell.className = "d-dr-" + statusClass + " statuscell"; cell.innerHTML = getStatusIcon(statusClass); if (!cell.isSetup) { - cldrInfo.listen("", tr, cell, null); + listen("", tr, cell, null); cell.isSetup = true; } @@ -738,7 +740,7 @@ function updateRowCodeCell(tr, theRow, cell) { cldrSurvey.appendExtraAttributes(cell, theRow); } if (!cell.isSetup) { - cldrInfo.listen("", tr, cell, null); + listen("", tr, cell, null); cell.isSetup = true; } } @@ -781,7 +783,7 @@ function updateRowEnglishComparisonCell(tr, theRow, cell) { } cell.appendChild(infos); } - cldrInfo.listen(null, tr, cell, null); + listen(null, tr, cell, null); if (cldrStatus.getPermissions()?.userIsTC) { cldrAddAlt.addButton(cell, theRow.xpstrid); } @@ -826,7 +828,7 @@ function updateRowProposedWinningCell(tr, theRow, cell, protoButton) { } else { cell.showFn = function () {}; // nothing else to show } - cldrInfo.listen(null, tr, cell, cell.showFn); + listen(null, tr, cell, cell.showFn); } /** @@ -977,7 +979,7 @@ function updateRowOthersCell(tr, theRow, cell, protoButton, formAdd) { } if (!hadOtherItems /*!onIE*/) { - cldrInfo.listen(null, tr, cell); + listen(null, tr, cell); } if ( tr.myProposal && @@ -1055,7 +1057,7 @@ function addVitem(td, tr, theRow, item, newButton) { const historyText = " ☛" + item.history; const historyTag = cldrDom.createChunk(historyText, "span", ""); choiceField.appendChild(historyTag); - cldrInfo.listen(historyText, tr, historyTag, null); + listen(historyText, tr, historyTag, null); } const surveyUser = cldrStatus.getSurveyUser(); @@ -1077,9 +1079,9 @@ function addVitem(td, tr, theRow, item, newButton) { div.appendChild(choiceField); // wire up the onclick function for the Info Panel - td.showFn = item.showFn = cldrInfo.showItemInfoFn(theRow, item); + td.showFn = item.showFn = showItemInfoFn(theRow, item); div.popParent = tr; - cldrInfo.listen(null, tr, div, td.showFn); + listen(null, tr, div, td.showFn); td.appendChild(div); if (item.example && item.value != item.examples) { @@ -1087,6 +1089,20 @@ function addVitem(td, tr, theRow, item, newButton) { } } +/** + * Return a function that will set theRow.selectedItem, which will result in + * showing info for the given candidate item in the Info Panel. + * + * @param {Object} theRow the data row + * @param {JSON} item JSON of the specific candidate item we are adding + * @returns the function + */ +function showItemInfoFn(theRow, item) { + return function (td) { + theRow.selectedItem = item; + }; +} + /** * Check if we need LRM/RLM marker to display * @param field choice field to append if needed @@ -1227,7 +1243,7 @@ function updateRowNoAbstainCell(tr, theRow, noCell, proposedCell, protoButton) { noOpinion.value = null; const wrap = cldrVote.wrapRadio(noOpinion); noCell.appendChild(wrap); - cldrInfo.listen(null, tr, noCell); + listen(null, tr, noCell); } else if (tr.ticketOnly) { // ticket link if (!tr.theTable.json.canModify) { @@ -1334,6 +1350,71 @@ function goToHeaderId(headerId) { } } +/** + * Make the object "theObj" respond to being clicked. Clicking a cell in the main + * vetting table should make the cell highlighted, update the URL bar to show + * the hex id of the path for the row in question, and update the Info Panel if + * the Info Panel is open. + * + * This function suffers from extreme tech debt. It was formerly in the cldrInfo module. + * The fn parameter (a.k.a. showFn) shouldn't need to be preconstructed for each item in + * each row, attached to DOM elements, and passed around as a parameter in such a complicated way. + * + * @param {String} str the string to display + * @param {Node} tr the TR element that is clicked + * @param {Node} theObj to listen to, a.k.a. "hideIfLast" + * @param {Function} fn the draw function + */ +function listen(str, tr, theObj, fn) { + cldrDom.listenFor(theObj, "click", function (e) { + if (cldrInfo.panelShouldBeShown()) { + cldrInfo.show(str, tr, theObj /* hideIfLast */, fn); + } else if (tr?.sethash) { + // These methods, updateCurrentId and setLastShown may be called from cldrInfo.show, if + // panelShouldBeShown() returned true. If the Info Panel is hidden then they still + // need to be called. Since they don't involve the Info Panel, the implementation + // should be changed to make them independent of the Info Panel and they should be + // called from a different module, not cldrInfo. + cldrLoad.updateCurrentId(tr.sethash); + setLastShown(theObj); + } + cldrEvent.stopPropagation(e); + return false; + }); +} + +function setLastShown(obj) { + if (lastShown && obj != lastShown) { + cldrDom.removeClass(lastShown, "pu-select"); + const partr = parentOfType("TR", lastShown); + if (partr) { + cldrDom.removeClass(partr, "selectShow"); + } + } + if (obj) { + cldrDom.addClass(obj, "pu-select"); + const partr = parentOfType("TR", obj); + if (partr) { + cldrDom.addClass(partr, "selectShow"); + } + } + lastShown = obj; +} + +function resetLastShown() { + lastShown = null; +} + +function parentOfType(tag, obj) { + if (!obj) { + return null; + } + if (obj.nodeName === tag) { + return obj; + } + return parentOfType(tag, obj.parentElement); +} + export { NO_WINNING_VALUE, EMPTY_ELEMENT_VALUE, @@ -1344,8 +1425,11 @@ export { goToHeaderId, insertRows, isHeaderId, + listen, makeRowId, refreshSingleRow, + resetLastShown, + setLastShown, updateRow, /* * The following are meant to be accessible for unit testing only: diff --git a/tools/cldr-apps/js/src/esm/cldrVote.mjs b/tools/cldr-apps/js/src/esm/cldrVote.mjs index 093cb45fe50..1615a860348 100644 --- a/tools/cldr-apps/js/src/esm/cldrVote.mjs +++ b/tools/cldr-apps/js/src/esm/cldrVote.mjs @@ -117,7 +117,7 @@ async function handleWiredClick(tr, theRow, vHash, newValue, button) { tr.myProposal = null; // mark any pending proposal as invalid. } tr.wait = true; - cldrInfo.reset(); + cldrTable.resetLastShown(); theRow.proposedResults = null; if (CLDR_VOTE_DEBUG) { logVote(tr.rowHash, vHash, value); @@ -424,7 +424,7 @@ function showProposedItem(inTd, tr, theRow, value, tests, json) { } return retFn; }; - cldrInfo.listen(null, tr, ourDiv, ourShowFn); + cldrTable.listen(null, tr, ourDiv, ourShowFn); cldrInfo.showRowObjFunc(tr, ourDiv, ourShowFn); } return false;