From af31f28d235cd81dbf8b149fd60c905d65456586 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Mon, 31 Mar 2025 12:39:17 +0200 Subject: [PATCH 1/2] Highlight related sidebar row when result `.entry` is hovered --- public/css/schedule.less | 22 +++++++++++++++------- public/js/schedule.js | 14 ++++++++++---- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/public/css/schedule.less b/public/css/schedule.less index bcf8c7c9c..bd75e99bb 100644 --- a/public/css/schedule.less +++ b/public/css/schedule.less @@ -67,14 +67,22 @@ /* Design */ -.schedule-detail .entry.highlighted { - outline: 2px solid var(--entry-border-color); - outline-offset: 1px; -} +.schedule-detail { + .entry.highlighted { + outline: 2px solid var(--entry-border-color); + outline-offset: 1px; + } -.schedule-detail .step.highlighted { - background-color: @gray-lighter; - border-color: @gray-light; + .sidebar .row-title.highlighted, + .step.highlighted { + background-color: @gray-lighter; + border-color: @gray-light; + } + + .sidebar .row-title.highlighted { + margin-top: -1px; // cover the border-top area + padding-top: 1px; + } } .schedule-detail .from-scratch-hint { diff --git a/public/js/schedule.js b/public/js/schedule.js index b0020262c..c53c5dcb2 100644 --- a/public/js/schedule.js +++ b/public/js/schedule.js @@ -79,12 +79,15 @@ const entry = event.currentTarget; const overlay = entry.parentElement; const grid = overlay.previousSibling; + const sideBar = grid.previousSibling; let relatedElements; if ('rotationPosition' in entry.dataset) { - relatedElements = grid.querySelectorAll( - '[data-y-position="' + entry.dataset.rotationPosition + '"]' + relatedElements = Array.from( + grid.querySelectorAll('[data-y-position="' + entry.dataset.rotationPosition + '"]') ); + + relatedElements.push(sideBar.childNodes[Number(entry.dataset.rotationPosition)]); } else { relatedElements = overlay.querySelectorAll( '[data-rotation-position="' + entry.dataset.entryPosition + '"]' @@ -116,12 +119,15 @@ const entry = event.currentTarget; const overlay = entry.parentElement; const grid = overlay.previousSibling; + const sideBar = grid.previousSibling; let relatedElements; if ('rotationPosition' in entry.dataset) { - relatedElements = grid.querySelectorAll( - '[data-y-position="' + entry.dataset.rotationPosition + '"]' + relatedElements = Array.from( + grid.querySelectorAll('[data-y-position="' + entry.dataset.rotationPosition + '"]') ); + + relatedElements.push(sideBar.childNodes[Number(entry.dataset.rotationPosition)]); } else { relatedElements = overlay.querySelectorAll( '[data-rotation-position="' + entry.dataset.entryPosition + '"]' From d6fc22c6fe3c4557d178a3c4d890a6873c18a4fe Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Tue, 1 Apr 2025 11:07:56 +0200 Subject: [PATCH 2/2] schedule.js: Optimize duplicate code and add JSDoc --- public/js/schedule.js | 83 +++++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 34 deletions(-) diff --git a/public/js/schedule.js b/public/js/schedule.js index c53c5dcb2..a233226c1 100644 --- a/public/js/schedule.js +++ b/public/js/schedule.js @@ -20,6 +20,11 @@ this.on('mouseleave', '#notifications-schedule .entry', this.onEntryLeave, this); } + /** + * Make the sidebar sortable and add drag&drop support. + * + * @param event The event object. + */ onRendered(event) { if (event.target !== event.currentTarget) { @@ -46,6 +51,11 @@ }); } + /** + * Handle drop event on the sidebar. + * + * @param event The event object. + */ onDrop(event) { event = event.originalEvent; @@ -74,32 +84,19 @@ form.requestSubmit(); } + /** + * Handle hover (`mouseenter`) event on schedule entries. + * + * @param event The mouse event object. + */ onEntryHover(event) { - const entry = event.currentTarget; - const overlay = entry.parentElement; - const grid = overlay.previousSibling; - const sideBar = grid.previousSibling; - - let relatedElements; - if ('rotationPosition' in entry.dataset) { - relatedElements = Array.from( - grid.querySelectorAll('[data-y-position="' + entry.dataset.rotationPosition + '"]') - ); + const [relatedEntries, tooltip] = event.data.self.identifyRelatedEntries(event); - relatedElements.push(sideBar.childNodes[Number(entry.dataset.rotationPosition)]); - } else { - relatedElements = overlay.querySelectorAll( - '[data-rotation-position="' + entry.dataset.entryPosition + '"]' - ); - } - - relatedElements.forEach((relatedElement) => { - relatedElement.classList.add('highlighted'); - }); + relatedEntries.forEach(element => element.classList.add('highlighted')); - const tooltip = entry.querySelector('.rotation-info'); if (tooltip) { + const grid = event.currentTarget.parentElement.previousSibling; requestAnimationFrame(() => { const tooltipRect = tooltip.getBoundingClientRect(); const gridRect = grid.getBoundingClientRect(); @@ -114,34 +111,52 @@ } } + /** + * Handle hover (`mouseleave`) event on schedule entries. + * + * @param event The mouse event object. + */ onEntryLeave(event) { + const [relatedEntries, tooltip] = event.data.self.identifyRelatedEntries(event); + + relatedEntries.forEach(element => element.classList.remove('highlighted')); + + if (tooltip) { + tooltip.classList.remove('is-left', 'is-bottom'); + } + } + + /** + * Identify hover-related entries. + * + * @param event The mouse event object. + * + * @returns {[HTMLElement[]|NodeListOf, HTMLElement|null]} + */ + identifyRelatedEntries(event) { const entry = event.currentTarget; const overlay = entry.parentElement; const grid = overlay.previousSibling; const sideBar = grid.previousSibling; - let relatedElements; + let relatedEntries; if ('rotationPosition' in entry.dataset) { - relatedElements = Array.from( + relatedEntries = Array.from( grid.querySelectorAll('[data-y-position="' + entry.dataset.rotationPosition + '"]') ); - relatedElements.push(sideBar.childNodes[Number(entry.dataset.rotationPosition)]); + relatedEntries.push(sideBar.childNodes[Number(entry.dataset.rotationPosition)]); } else { - relatedElements = overlay.querySelectorAll( + relatedEntries = overlay.querySelectorAll( '[data-rotation-position="' + entry.dataset.entryPosition + '"]' - ); + ) } - relatedElements.forEach((relatedElement) => { - relatedElement.classList.remove('highlighted'); - }); - - const tooltip = entry.querySelector('.rotation-info'); - if (tooltip) { - tooltip.classList.remove('is-left', 'is-bottom'); - } + return [ + relatedEntries, + entry.querySelector('.rotation-info') + ]; } }