Runtime Terror
Runtime Terror

Reputation: 6752

Hide element when mouse leaves the element for x-amount of ms

I'm struggling with creation of this observable. I have a hide-able element in my Angular app. When the user leaves with mouse over this element and he doesn't enters lets say in 500ms, the element should hide.

The marble diagram:

onleave --x-------x------------------------>
onenter -----x----------------------------->
                  <--500ms-->
_________________________________________
hide    ---------------------x------------->
const leave$ = fromEvent(this.selector.nativeElement,"mouseleave");
const enter$ = fromEvent(this.selector.nativeElement,"mouseenter");

const hide$ = // ToDo: implement logic

EDIT:

I've created an observable, but it does't work the way I would like:

const leave$ = fromEvent(this.backgroundSelector.nativeElement, "mouseleave");
const enter$ = fromEvent(this.backgroundSelector.nativeElement, "mouseenter");

const hide$ = leave$.pipe(
      mergeMap(event =>
          of(event).pipe(
                delay(500),
                takeUntil(enter$)
          )
      )
);

hide$.pipe(takeUntil(this.destroy$)).subscribe(_ => this.hideSelector());

The issue is, the element is hiding only when I return with mouse cursor after 500ms.

Upvotes: 2

Views: 340

Answers (1)

Armen Stepanyan
Armen Stepanyan

Reputation: 1846

You can use debounceTime operator on mouseleave event. As mentioned at documentation

DebounceTime discard emitted values that take less than the specified time between output

On mouseenter event you need to discard emitted values from mouseleave event. And for this case you can simple use switchMap operator, which will discard inner observable emit values.

const main = document.getElementById('main');
const content = document.getElementById('content');    

 fromEvent(main, 'mouseenter')
 .pipe(   
   switchMap(event => {
     content.style.display = 'block';
     return fromEvent(main, 'mouseleave').pipe(debounceTime(500));
   }))
 .subscribe(val => {
  content.style.display = 'none';
});

Here is example on Stackblitz

Upvotes: 1

Related Questions