diff options
author | Phil Hughes <me@iamphill.com> | 2017-08-01 08:49:03 +0100 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2017-08-01 08:49:03 +0100 |
commit | 20bfc4f679bd63f71af716d4910c5c22e33180c0 (patch) | |
tree | 77875dc518481f280051ecf9a2703006d4059ab8 /app | |
parent | f20a48494a4d60ddf311b85ce51ba0cb788390be (diff) | |
download | gitlab-ce-20bfc4f679bd63f71af716d4910c5c22e33180c0.tar.gz |
added mouseleave timeout with JS
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/javascripts/fly_out_nav.js | 90 | ||||
-rw-r--r-- | app/assets/stylesheets/new_sidebar.scss | 3 |
2 files changed, 74 insertions, 19 deletions
diff --git a/app/assets/javascripts/fly_out_nav.js b/app/assets/javascripts/fly_out_nav.js index f2151396d43..93101f123b5 100644 --- a/app/assets/javascripts/fly_out_nav.js +++ b/app/assets/javascripts/fly_out_nav.js @@ -1,3 +1,16 @@ +let hideTimeoutInterval = 0; +let hideTimeout; +let subitems; + +export const getHideTimeoutInterval = () => hideTimeoutInterval; + +export const hideAllSubItems = () => { + subitems.forEach((el) => { + el.parentNode.classList.remove('is-over'); + el.style.display = 'none'; // eslint-disable-line no-param-reassign + }); +}; + export const calculateTop = (boundingRect, outerHeight) => { const windowHeight = window.innerHeight; const bottomOverflow = windowHeight - (boundingRect.top + outerHeight); @@ -6,23 +19,64 @@ export const calculateTop = (boundingRect, outerHeight) => { boundingRect.top; }; +export const showSubLevelItems = (el) => { + const $subitems = el.querySelector('.sidebar-sub-level-items'); + + if (!$subitems) return; + + hideAllSubItems(); + + if (el.classList.contains('is-over')) { + clearTimeout(hideTimeout); + } else { + $subitems.style.display = 'block'; + el.classList.add('is-over'); + } + + const boundingRect = el.getBoundingClientRect(); + const top = calculateTop(boundingRect, $subitems.offsetHeight); + const isAbove = top < boundingRect.top; + + $subitems.style.transform = `translate3d(0, ${top}px, 0)`; + + if (isAbove) { + $subitems.classList.add('is-above'); + } +}; + +export const hideSubLevelItems = (el) => { + const $subitems = el.querySelector('.sidebar-sub-level-items'); + const hideFn = () => { + el.classList.remove('is-over'); + $subitems.style.display = 'none'; + $subitems.classList.remove('is-above'); + + hideTimeoutInterval = 0; + }; + + if ($subitems && hideTimeoutInterval) { + hideTimeout = setTimeout(hideFn, hideTimeoutInterval); + } else if ($subitems) { + hideFn(); + } +}; + +export const setMouseOutTimeout = (el) => { + if (el.closest('.sidebar-sub-level-items')) { + hideTimeoutInterval = 250; + } else { + hideTimeoutInterval = 0; + } +}; + export default () => { - $('.sidebar-top-level-items > li:not(.active)').on('mouseover', (e) => { - const $this = e.currentTarget; - const $subitems = $('.sidebar-sub-level-items', $this).show(); - - if ($subitems.length) { - const boundingRect = $this.getBoundingClientRect(); - const top = calculateTop(boundingRect, $subitems.outerHeight()); - const isAbove = top < boundingRect.top; - - $subitems.css({ - transform: `translate3d(0, ${top}px, 0)`, - }); - - if (isAbove) { - $subitems.addClass('is-above'); - } - } - }).on('mouseout', e => $('.sidebar-sub-level-items', e.currentTarget).hide().removeClass('is-above')); + const items = [...document.querySelectorAll('.sidebar-top-level-items > li:not(.active)')]; + subitems = [...document.querySelectorAll('.sidebar-top-level-items > li:not(.active) .sidebar-sub-level-items')]; + + items.forEach((el) => { + el.addEventListener('mouseenter', e => showSubLevelItems(e.currentTarget)); + el.addEventListener('mouseleave', e => hideSubLevelItems(e.currentTarget)); + }); + + subitems.forEach(el => el.addEventListener('mouseleave', e => setMouseOutTimeout(e.target))); }; diff --git a/app/assets/stylesheets/new_sidebar.scss b/app/assets/stylesheets/new_sidebar.scss index 05b72e9f425..72c12413aba 100644 --- a/app/assets/stylesheets/new_sidebar.scss +++ b/app/assets/stylesheets/new_sidebar.scss @@ -292,7 +292,8 @@ $new-sidebar-width: 220px; } &:not(.active):hover > a, - > a:hover { + > a:hover, + &.is-over > a { background-color: $white-light; } } |