CoderGuruXYZ
CoderGuruXYZ

Reputation: 73

Touchscreen Press & Hold

I want the user to be able to touch and hold a button, and after a certain period of time, a function is called.

E.g. the button text starts as black, turns orange after 0.2s of pressing, and then green after 0.5s of pressing. If it is green, a function, myFunction(), is triggered.

I have made a start on it, more help would be appreciated. Thanks :)

var btn = document.getElementById("pressBtn");

var pressedTime = 0;
var elaspedHoldTime;

btn.onmousedown = function() {
  if (pressedTime != 0) {
    pressedTime = performance.now();
  } else {
    elaspedHoldTime = performance.now() - pressedTime;
  }

  if (elaspedHoldTime > 200) {
    btn.style.color = "orange";
  }

  if (elaspedHoldTime > 1000) {
    btn.style.color = "green";
  }
};

btn.addEventListener("mouseup", function() {
  elaspedHoldTime = performance.now() - pressedTime;

  btn.style.color = "black";

  if (elaspedHoldTime > 500) {
    console.log("Call Function Here");
  }

  pressedTime = 0;
  elaspedHoldTime = 0;
});
<button id="btn">Button Text</button>

(It also has a bug for some reason)

Upvotes: 1

Views: 2619

Answers (3)

xhxe
xhxe

Reputation: 1487

UPDATED

for not fully functioanlity I edited the code and also changed the logic

I come up with variable timerValue which increases in every 0.1s when mouse is pressed and when that timerValue reaches 2, button changes color to orange and on 5 changes on red and prints triggered as well

and on mouseup which will be called after user picks up finger from mouse, timerValue backs to 0 and resets also button class

interval is variable where are I store setInterval function and on mouse release I clear it

I included also paragpraph tag where is shown the timer to understand how it works

const btn = document.querySelector(".btn")
const timer = document.querySelector("p") //can be deleted

let timerValue = 0
let interval;

const mousePress = () => {
  interval = setInterval(() => {
    timerValue++
    timer.innerHTML = timerValue //can be deleted
    
    if(timerValue === 2) btn.classList.toggle("orange")
    if(timerValue === 5) {
      btn.classList.toggle("red")
      console.log("triggered")
    }
  }, 100)
}

const mouseRelease = () => {
  clearInterval(interval)
  timerValue = 0
  timer.innerHTML = timerValue //can be deleted
  btn.className = "btn"
}

btn.addEventListener("mousedown", mousePress)
btn.addEventListener("mouseup", mouseRelease)
.btn.orange{
  color: orange;
}
.btn.red{
  color: red;
}
<button class="btn">Click</button>
<p></p>

Upvotes: 3

Christopher
Christopher

Reputation: 3667

mousedown, mouseup, touchstart, touchend triggers just once when the key is pressed.

To check, if the user is still holding it, you can check for a truly variable inside a setTimeout() function-call, stop the timeout on release or use a setInterval()-function-call that only runs when it's pressed.

For example:

let pressed = false;
button.addEventListener("mousedown", () => {
  pressed = true;
  setTimeout(() => {
    if (pressed) { ... }
  }, 200);
});
button.addEventListener("mouseup", () => { pressed = false; });
let timer = null;
button.addEventListener("mousedown", () => {
  pressed = true;
  timer = setTimeout(() => { ... }, 200);
});
button.addEventListener("mouseup", () => { clearTimeout(timer) });

As there is already an answer with setTimeout(), here is another solution with setInterval().

let vars = {
    interval: null, // used to store the interval id
    start: 0, // changes to Date.now() on every start.
    // used to avoid myFunction be called more than once per "hold"
    myFunctionCalled: false 
  }, myFunction = () => console.log("Yes...?");

button.addEventListener("mousedown", (event) => {
  // avoid start w/ rightclick
  if (event.which == 1) {
    vars.start = Date.now();
    vars.myFunctionCalled = false;
    vars.interval = setInterval(() => {
      let dur = Date.now() - vars.start;
      if (dur > 1000) {
        button.style.color = "green";
        if (!vars.myFunctionCalled) {
          vars.myFunctionCalled = true;
          myFunction();
        }
      } else if (dur > 500) {
        button.style.color = "orange";
      } else if (dur > 100) {
        button.style.color = "red";
      }
    }, 10);
  }
});

// using window, so the user can move the mouse
window.addEventListener("mouseup", (event) => {
  // checking again for the mouse key, to avoid disabling it on rightlick
  if (vars.interval && event.which == 1) {
    // stop the interval and reset the color to default
    clearInterval(vars.interval);
    button.style.color = "";
    vars.interval = null;
  }
})
<button id="button">Hold me</button>

Upvotes: 2

Parking Master
Parking Master

Reputation: 626

If you're making it for a touchscreen, you need to use TouchEvents:

ontouchstart -> when a target is being pressed by a finger
ontouchmove -> the active finger moves off the target
ontouchcancel -> when the the target has lost focus of a touch event
ontouchend -> lifting the finger off of the target

MouseEvents are reserved for mouse / trackpad-controlled devices, such as Computers.

TouchEvents are reserved for touch-screen devices, such as tablets and phones.

Also read this answer for code.

Upvotes: 1

Related Questions