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..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,29 +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 [relatedEntries, tooltip] = event.data.self.identifyRelatedEntries(event); - let relatedElements; - if ('rotationPosition' in entry.dataset) { - relatedElements = grid.querySelectorAll( - '[data-y-position="' + 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(); @@ -111,31 +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 = grid.querySelectorAll( - '[data-y-position="' + entry.dataset.rotationPosition + '"]' + relatedEntries = Array.from( + grid.querySelectorAll('[data-y-position="' + 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') + ]; } }