Search code examples
javascriptjqueryhtml

Make "scrollLeft" / "scrollTop" changes not trigger scroll event listener


Currently my program is in a spot where it both listens for the user to scroll a certain element, but also, at times, automatically scrolls this element by itself. (Not a gradual, pretty scroll, but an instant jump. It makes sense in context, I swear.)

Is there a way to make the scroll event not trigger if the scrolling was done by setting scrollLeft or scrollTop? My first thought was a basic switch, like:

ignoreScrollEvents = true;
element.scrollLeft = x;
ignoreScrollEvents = false;

function onScroll() {
  if(ignoreScrollEvents) return false;
}

but since events don't trigger immediately (oops, duhh), that's not a workable solution. What other sort of answers could I try? I'm also using jQuery, if that helps anything.


Solution

  • Easiest generic method? Just reset the flag in the event handler. You'll want to check first if you're actually changing the value, as otherwise an event won't be fired - as Rodrigo notes, a good practice here is to factor this out into so-called "setter" functions:

    function setScrollLeft(x) {
      if (element.scrollLeft != x) {
        ignoreScrollEvents = true;
        element.scrollLeft = x;
      }
    } 
    
    ...
    
    function onScroll() {
      const ignore = ignoreScrollEvents;
      ignoreScrollEvents = false;
      
      if (ignore) {
        return false;
      }
    
      ...
    }
    

    But, depending on your needs, you may already be storing the scroll position somewhere; if so, just update and check that as your flag. Something like:

    element.scrollLeft = x;
    currentScrollLeft = x;
    
    ...
    
    function onScroll() {
      // retrieve element, etc... 
      if (element.scrollLeft == currentScrollLeft) {
        return false;
      }
    
      ...
    }