Skip to content

Commit

Permalink
T256213: Add a small delay to onMouseLeave (#20)
Browse files Browse the repository at this point in the history
* Add 300 ms delay to onMouseLeve

* Handle quick exit and re-enter

* Define previewElement at top of the scope

* Fix issue when quickly transitioning to a new popup

* stack timeout listener (#23)

* POC - stack all event listener and timeout event

* remove unused comment line

* naming clearAllEventListener

* var -> let

* Fix touch interaction

Co-authored-by: Huei Tan <hueitan@users.noreply.github.com>
  • Loading branch information
medied and hueitan authored Jul 27, 2020
1 parent fd9bf82 commit 513b876
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 20 deletions.
65 changes: 45 additions & 20 deletions src/event.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,43 @@
import { isTouch } from './utils'

export const customEvents = popup => {
const onMouseLeave = e => {
const toElement = e.toElement || e.relatedTarget || e.target
if ( toElement !== popup.element.currentTargetElement &&
!popup.element.contains( toElement ) ) {
popup.hide()

let eventListenerStack = [],
timeoutStack = []
const addTimeout = ( func, timeout ) => {
const id = setTimeout( func, timeout )
timeoutStack.push( id )
return id
},
clearAllTimeout = () => {
timeoutStack.forEach( timeoutId => {
clearTimeout( timeoutId )
} )
timeoutStack = []
},
addEventListener = ( target, type, listener, options = undefined ) => {
target.addEventListener( type, listener, options )
eventListenerStack.push( [ target, type, listener, options ] )
},
clearAllEventListener = () => {
eventListenerStack.forEach( eventListener => {
const [ target, type, listener, options ] = eventListener
target.removeEventListener( type, listener, options )
} )
eventListenerStack = []
},
onMouseLeave = e => {
const toElement = e.toElement || e.relatedTarget || e.target,
previewElement = popup.element.currentTargetElement

if ( toElement !== previewElement && !popup.element.contains( toElement ) ) {
let timeoutId
const persistPopup = () => {
clearTimeout( timeoutId )
}

timeoutId = addTimeout( popup.hide, 300 )
addEventListener( popup.element, 'mouseenter', persistPopup )
}
},

Expand All @@ -20,16 +52,9 @@ export const customEvents = popup => {
}
},

onHide = element => {
element.component.closeBtn.removeEventListener( 'click', popup.hide )
element.component.readMore.removeEventListener( 'click', onExpand )

if ( isTouch ) {
document.removeEventListener( 'touchstart', onTouchStart, true )
} else {
element.removeEventListener( 'mouseleave', onMouseLeave )
element.currentTargetElement.removeEventListener( 'mouseleave', onMouseLeave )
}
onHide = () => {
clearAllEventListener()
clearAllTimeout()
},

onShow = element => {
Expand All @@ -45,14 +70,14 @@ export const customEvents = popup => {
onExpand( element )
}

element.component.closeBtn.addEventListener( 'click', popup.hide )
element.component.readMore.addEventListener( 'click', onExpand )
addEventListener( element.component.closeBtn, 'click', popup.hide )
addEventListener( element.component.readMore, 'click', onExpand )

if ( isTouch ) {
document.addEventListener( 'touchstart', onTouchStart, true )
addEventListener( document, 'touchstart', onTouchStart, true )
} else {
element.addEventListener( 'mouseleave', onMouseLeave )
element.currentTargetElement.addEventListener( 'mouseleave', onMouseLeave )
addEventListener( element, 'mouseleave', onMouseLeave )
addEventListener( element.currentTargetElement, 'mouseleave', onMouseLeave )
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@ function init( {
createPopup( popupContainer ),
events = customEvents( popup ),
showPopup = ( { target } ) => {
if ( popup.element.style.visibility === 'visible' ) {
popup.hide()
}

const title = target.getAttribute( 'data-wp-title' ) || target.textContent,
lang = target.getAttribute( 'data-wp-lang' ) || globalLang

requestPagePreview( lang, title, isTouch, data => {
if ( data ) {
popup.show( renderPreview( lang, data, isTouch ), target )
Expand Down

0 comments on commit 513b876

Please sign in to comment.