How to detect Pull to refresh

Viewed 18270

There are many "pull to refresh" plugins. I have already tested 5 of them. But none of them running fast (especially on old smartphones).

What is the best (buttery UX performance and responsiveness) way to check for pull to refresh?

PS: I don't need any animation. I just want to recognize if a user "pull to refresh"

6 Answers

What about this?

var lastScrollPosition = 0;
window.onscroll = function(event)
{
  if((document.body.scrollTop >= 0) && (lastScrollPosition < 0))
  {
    alert("refresh");
  }
  lastScrollPosition = document.body.scrollTop;
}

If your browser doesn't scroll negative, then you could replace line 4 with something like this: if((document.body.scrollTop == 0) && (lastScrollPosition > 0))

Alternatively for android devices, you could swap out lastScrollPosition for "ontouchmove" or other gesture events.

I know this answer has been answered by a lot many people but it may help someone.

It's based on Mr. Pryamid's answer. but his answer does not work touch screen. that only works with mouse.

this answer works well on touch screen and desktop. i have tested in chrome in desktop and chrome in android

<!DOCTYPE html>
<html>
  <head>
    <style>
      * {
        margin: 0;
        padding: 0;
      }

      html,
      body {
        width: 100%;
        height: 100%;
      }

      .pull-to-refresh-container {
        width: 100%;
        height: 100%;
        background-color: yellow;
        position: relative;
      }

      .pull-to-refresh-content-container {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background-color: white;
        margin: 0px;
        text-align: center;
      }
    </style>
  </head>
  <body>
    <div class="pull-to-refresh-container">
      <div class="pull-to-refresh-loader-container">
        loading ...
      </div>
      <div class="pull-to-refresh-content-container">
        here lies the content
      </div>
    </div>

    <script>
      var mouseY = 0
      var startMouseY = 0
      var container = document.querySelector(
        ".pull-to-refresh-content-container"
      )

      container.onmousedown = (ev) => {
        mouseY = ev.pageY
        startMouseY = mouseY

        container.onmousemove = (e) => {
          if (e.pageY > mouseY) {
            var d = e.pageY - startMouseY

            console.log("d: " + d)
            container.style.marginTop = d / 4 + "px"
            if (d >= 300) {
              // alert("load more content");
            }
          } else {
            container.onmousemove = null
          }
        }
      }

      container.onmouseup = (ev) => {
        container.style.marginTop = "0px"
        container.onmousemove = null
      }

      container.onmouseleave = (ev) => {
        container.style.marginTop = "0px"
        container.onmousemove = null
      }
      container.ontouchstart = (ev) => {
        mouseY = ev.touches[0].pageY
        startMouseY = mouseY

        container.ontouchmove = (e) => {
          if (e.touches[0].pageY > mouseY) {
            var d = e.touches[0].pageY - startMouseY

            console.log("d: " + d)
            container.style.marginTop = d / 4 + "px"
            if (d >= 300) {
              // alert("load more content");
            }
          } else {
            container.onmousemove = null
          }
        }
      }

      container.ontouchcancel = (ev) => {
        container.style.marginTop = "0px"
        container.onmousemove = null
      }

      container.ontouchend = (ev) => {
        container.style.marginTop = "0px"
        container.onmousemove = null
      }
    </script>
  </body>
</html>

Here is how I did it with Stimulus and Turbolinks:

See video in action: https://imgur.com/a/qkzbhZS

import { Controller } from "stimulus"
import Turbolinks from "turbolinks"

export default class extends Controller {
  static targets = ["logo", "refresh"]

  touchstart(event) {
    this.startPageY = event.changedTouches[0].pageY
  }

  touchmove(event) {
    if (this.willRefresh) {
      return
    }

    const scrollTop = document.documentElement.scrollTop
    const dy = event.changedTouches[0].pageY - this.startPageY

    if (scrollTop === 0 && dy > 0) {
      this.logoTarget.classList.add("hidden")
      this.refreshTarget.classList.remove("hidden")

      if (dy > 360) {
        this.willRefresh = true
        this.refreshTarget.classList.add("animate-spin")
        this.refreshTarget.style.transform = ""
      } else {
        this.refreshTarget.classList.remove("animate-spin")
        this.refreshTarget.style.transform = `rotate(${dy}deg)`
      }
    } else {
      this.logoTarget.classList.remove("hidden")
      this.refreshTarget.classList.add("hidden")
      this.refreshTarget.classList.remove("animate-spin")
      this.refreshTarget.style.transform = ""
    }
  }

  touchend(event) {
    if (this.willRefresh) {
      Turbolinks.visit(window.location.toString(), { action: 'replace' })
    } else {
      this.logoTarget.classList.remove("hidden")
      this.refreshTarget.classList.add("hidden")
      this.refreshTarget.classList.remove("animate-spin")
      this.refreshTarget.style.transform = ""
    }
  }
}
  body(class="max-w-md mx-auto" data-controller="pull-to-refresh" data-action="touchstart@window->pull-to-refresh#touchstart touchmove@window->pull-to-refresh#touchmove touchend@window->pull-to-refresh#touchend")
        = image_tag "logo.png", class: "w-8 h-8 mr-2", "data-pull-to-refresh-target": "logo"
        = image_tag "refresh.png", class: "w-8 h-8 mr-2 hidden", "data-pull-to-refresh-target": "refresh"

One simple way:

$(document.body).pullToRefresh(function() {
         setTimeout(function() {
            $(document.body).pullToRefreshDone();
         }, 2000);
      });

Related