Search code examples
javascriptangularswiper.jsmousedownmouseup

mouseup/down on entire SPA angular


In my component class I have

@HostListener('document:mousedown', ['$event'])
onMouseDown() {
    this.holding = true;
}

@HostListener('document:mouseup', ['$event'])
onMouseUp() {
    this.holding = false;
}

In this project I'm also using swiper library. My swiper is 200px height and 100% width. Swiper use some own events catching for "grabing" elements to make it actually swipeable.

Now when I have my mouse on top of swiper element and I click above code doesn't catch the event.

This shoudln't happen but it is. Also what make it even weirder is that it doesn't catch only the left mouse click, right click works correctly.

How to make it works even when mouse is on top of swiper?


Edit

For some reason I'm not able to reproduce issue at online code playground, so I've created very basic app with just two components and I pushed it to git.

In this project I'm displaying {{ holding }} and as you can see (if you clone and ng serve this app) when clicking at the top or bottom of page it change from false to true but when clicking on swiper it doesn't catch onMouseDown and the value doesn't change.


Solution

  • because Swiper prevent the dispatching of internal DOM element, you can use Event API from swiper to get what is happening inside Swiper main dom element.

    For example on your case you can do something like this :

        this.mySwiper = new Swiper('.nav', {
            paginationClickable: false,
            grabCursor: true,
            loop: true,
            autoplay: 1000,
            slidesPerView: 3,
            spaceBetween: 50
        });
    
        this.mySwiper.on('touchStart', () => {
            this.touchService.triggerTouchStart();
        });
        this.mySwiper.on('touchEnd', () => {
            this.touchService.triggerTouchStop();
        });
    

    You can introduce new service on your application to abstract to the rest of your application this trick to be binded on all mousedown | mouseup events. bellow you can find the implementation :

    export class TouchService {
      private _manualControl$: Subject<boolean>;
    
      constructor() {
        this._manualControl$ = new Subject();
        // React to the document mouse event.
        fromEvent(document, 'mousedown').subscribe(() => this.triggerTouchStart());
        fromEvent(document, 'mouseup').subscribe(() => this.triggerTouchStop());
      }
      // Can be call manually to force new state.
      triggerTouchStart(): void {
        this._manualControl$.next(true);
      }
    
      triggerTouchStop(): void {
        this._manualControl$.next(false);
      }
    
      get touch$(): Observable<boolean> {
        return this._manualControl$.asObservable();
      }
    }
    

    Now you have observable which react on native mousedown and mouseup events and can also be trigger by manual API call like

        this.mySwiper.on('touchStart', () => {
            this.touchService.triggerTouchStart();
        });
        this.mySwiper.on('touchEnd', () => {
            this.touchService.triggerTouchStop();
        });
    

    Finally you can use this service like following :

    constructor(private touchService: TouchService) {
        this.touchService.touch$.subscribe(e => this.holding = e);
    }
    

    I can't prupose you pull request on your project because i don't have right to do it. You can see it in action here

    git remote add fork https://bitbucket.org/yghidouche/ng-hover-issue

    git fetch fork issues_1