Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent refresh for overflowing children while !window.scrollY #125

Open
robinpoort opened this issue Jun 8, 2023 · 2 comments
Open

Prevent refresh for overflowing children while !window.scrollY #125

robinpoort opened this issue Jun 8, 2023 · 2 comments

Comments

@robinpoort
Copy link

robinpoort commented Jun 8, 2023

Bug report

Pull to Refresh will 'pull' when scrolling back inside an overflowing element while !window.scrollY. This is problematic when you have any overflowing containers (with overflow: auto for example) in the default viewport (when the user hasn't scrolled inside the body element). See my solution below.

Current behavior:
When you scroll inside an overflowing container while !window.scrollY pull to refresh will do it's thing.

Expected behavior:
Check the current scrollTop of an element (and it's parents) to be smaller than 0 before running PTR

Browsers affected:
All

My solution

Since this is quite an old repo I don't expect a fix soon. I thought I'd post my solution here if other people run into the same issue.

    // Pull to refresh
    // ---------------
    let shouldRefresh = true;
    document.body.addEventListener('touchstart', (ev) => {
      let el = ev.target;
      while (el.parentNode && el !== document.body) {
        if (el.scrollTop > 0) {
          shouldRefresh = false;
        }
        el = el.parentNode;
      }
    });

    document.body.addEventListener('touchend', (e) => {
      shouldRefresh = true;
    });

    PullToRefresh.init({
      shouldPullToRefresh: () => !window.scrollY && shouldRefresh
    });

What is happening here is that I use shouldPullToRefresh to also check if shouldRefresh is true. shouldRefresh is false whenever the following happens: on touchstart, if the target element, or it's parent (as long as this parent is not the body element) has any scrollTop that is larger than 0. On touchend; shouldRefresh is set back to false for the next round. It would be even better to check for the PTR mainElement; but in my case I don't need that..

The code above will make sure you can scroll inside overflowing containers when !window.scrollY., but if the scrollTop of the target element (or one of it's parents) is 0; PTR will do it's thing.

Hope this helps anybody running into the same problem.

@qcasey
Copy link

qcasey commented Jan 25, 2024

Thank you for this!

I'm also checking against a few elements I don't want to take over, like shadcn/ui drawer:

        while (el.parentNode && el !== document.body) {
            if (el.scrollTop > 0) {
                shouldRefresh = false;
            }

            // Check if element has role=dialog
            if (el.getAttribute('role') === 'dialog') {
                shouldRefresh = false;
                break;
            }

            el = el.parentNode as HTMLElement;
        }

@robinpoort
Copy link
Author

Hi @qcasey

Glad the code could help you! And great example on how to add other exceptions as well :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants