How to simulate long press with react js? - javascript

I want to trigger long press event with click event. is there any way to that in react js?
something close to this, is the jQuery trigger() function. but i want something like trigger("longPress") or open up right click menu with left click in react. both mentioned (long press trigger / open up right click menu) are ideal for me

you can do this hack by get hold time
https://stackblitz.com/edit/react-d1txdm
export default function App() {
let triggerTime;
return (
<div>
<h1>Try on Google Chrome Desktop</h1>
<p>Open the console log to see how the event gets triggered.</p>
<p>The event should not get triggered if there is a long click.</p>
<img
src="https://via.placeholder.com/200.png/09f/fff"
onClick={(e) => {
if (triggerTime > 1000) return;
else console.log('normal click');
}}
onMouseDown={() => {
triggerTime = new Date().getTime();
}}
onMouseUp={() => {
let thisMoment = new Date().getTime();
triggerTime = thisMoment - triggerTime;
}}
/>
</div>
);
}

What about something like this:
const myComponent = () => {
let clickHoldTimer = null;
const handleMouseDown = () => {
clickHoldTimer = setTimeout(() => {
//Action to be performed after holding down mouse
}, 1000); //Change 1000 to number of milliseconds required for mouse hold
}
const handleMouseUp = () => {
clearTimeout(clickHoldTimer);
}
return (
<div onMouseDown={handleMouseDown} onMouseUp={handleMouseUp} />
)
}

Related

Close button popup doesn't work (JAVASCRIPT)

i'm trying to create a custom pupop in javascript, this is my first time with this.
I have a problem with the close button, the "x" target correctly the div to close, but doesn't remove the "active" class at click.
https://demomadeingenesi.it/demo-cedolino/
HTML CODE
<div class="spot spot-2">
<div class="pin"></div>
<div class="contenuto-spot flex flex-col gap-3">
<img class="chiudi-popup" src="img/chiudi.svg" />
[---CONTENT---]
</div>
</div>
</div>
JAVASCRIPT CODE
const tooltips = function () {
const spots = document.querySelectorAll(".spot");
spots.forEach((spot) => {
const contenuto = spot.querySelector(".contenuto-spot");
const pin = spot.querySelector(".pin");
spot.addEventListener("click", () => {
let curActive = document.querySelector(".spot.active");
let contActive = document.querySelector(".contenuto-spot.show");
const chiudiPopup = document.querySelector(".chiudi-popup");
spot.classList.add("active");
contenuto.classList.add("show");
if (curActive && curActive !== spot) {
curActive.classList.toggle("active");
contActive.classList.toggle("show");
}
chiudiPopup.addEventListener("click", () => {
spot.classList.remove("active");
contenuto.classList.remove("show");
});
});
});
const chiudiPopup = document.querySelector(".chiudi-popup");
chiudiPopup.addEventListener("click", () => {
spot.classList.remove("active");
contenuto.classList.remove("show");
});
What the code above does is adding an click listener, but it's inside another click listener, so all it's doing is adding an click listener on the first .chiudi-popup that removes .active and .show from the last spot element.
It's hard to see if this is correct, because you haven't given us enough to reproduce the problem, but I moved the code above outside the spot.addEventListener("click", () => { and instead of searching the whole document with const chiudiPopup = document.querySelector(".chiudi-popup"); the code nows only targets the .chuidi-popup element within the spot: const chiudiPopup = spot.querySelector(".chiudi-popup");
const tooltips = function() {
const spots = document.querySelectorAll(".spot");
spots.forEach((spot) => {
const contenuto = spot.querySelector(".contenuto-spot");
const pin = spot.querySelector(".pin");
spot.addEventListener("click", () => {
let curActive = document.querySelector(".spot.active");
let contActive = document.querySelector(".contenuto-spot.show");
spot.classList.add("active");
contenuto.classList.add("show");
if (curActive && curActive !== spot) {
curActive.classList.toggle("active");
contActive.classList.toggle("show");
}
});
// MOVED FROM THE CLICK LISTENER
const chiudiPopup = spot.querySelector(".chiudi-popup");
chiudiPopup.addEventListener("click", () => {
spot.classList.remove("active");
contenuto.classList.remove("show");
});
});
EDIT: I missed that you have the img.chiudi-popup inside your container, which will trigger both event listeners. I would honestly just simplify the code and always hide the container when clicking on it again. You can still have the img.chiudi-popup (close image) to make it easier for the users to understand that they can click on it.
const tooltips = function() {
const spots = document.querySelectorAll(".spot");
spots.forEach((spot) => {
const contenuto = spot.querySelector(".contenuto-spot");
const pin = spot.querySelector(".pin");
spot.addEventListener("click", () => {
let curActive = document.querySelector(".spot.active");
let contActive = document.querySelector(".contenuto-spot.show");
if (curActive !== spot) {
spot.classList.add("active");
contenuto.classList.add("show");
}
if (curActive) {
curActive.classList.remove("active");
contActive.classList.remove("show");
}
});

Event repeating multiple times during click

A small development problem, first, I declare a div to represent an icon to enter my inventory.
<<if setup.tagValue("map") !== 'MainMenu'>>
<div id="generalMenu">
<div id="Inventory"></div>
</div>
<</if>>
Now the real code, to activate this.
$(document).on(':passageend', () => {
window.inventoryIcons()
})
window.inventoryIcons = () => {
const _local = passage()
const _icon = $('#Inventory')
if (['BattleAPI'].includes(_local)) {
_icon
.removeClass()
.addClass("disabled")
}
else {
_icon.addClass("genMenuHover")
_icon.ariaClick(() => {
window.playerEquipIcon()
window.setInvIcons()
window.playerInventoryHover()
Engine.play('Inventory')
console.log(_icon)
})
}
}
This is having a mysterious effect, where each execution returns more and more events to the click.

React-Leaflet: How to listen to LayersControl.Overlay checkbox click events?

I'm dynamically rendering some overlay controls and wanting to bind a click event listener to the checkbox of each control. However there does not currently seem to be a way to provide a React ref to LayersControl or an onClick handler to LayersControl.Overlay. Is there a better approach to achieving this functionality?
Example:
<LayersControl>
{overlays.map(el => (
<LayersControl.Overlay
checked={el.checked}
key={el.id}
name={el.label}
>
<GeoJsonLayer {...el} />
</LayersControl.Overlay>
))}
</LayersControl>
Use a ref to get the map instance and following listen to a baselayerchange event. Then using the name of your layer or the url you can implement the behavior you want.
const mapRef = useRef();
useEffect(() => {
const map = mapRef.current.leafletElement;
map.on("baselayerchange", e => {
//do whatever
console.log(e.name);
switch (e.name) {
case "OpenStreetMap.Mapnik":
flyToParis(map);
break;
case "OpenStreetMap.BlackAndWhite":
console.log("do something else");
break;
default:
return;
}
});
}, []);
const flyToParis = map => {
console.log(map);
map.panTo([48.864716, 2.349014]);
};
Demo

Activating and Deactivation EventListener JS vanilla

I am creating a game with two players. these players are 0,1
var activePlayer = [0,1]
Depending who is active I would like to make available the event listener which activates the controlers of each player, only when the player is active.
I try the following but of course, is not working.
function controlGame(){
do{
document.querySelector('.btn-roll-0').addEventListener('click', play,);
document.querySelector('.btn-hold-0').addEventListener('click',hold);
}while(activePlayer === 0)
do{
document.querySelector('.btn-hold-1').addEventListener('click',hold);
document.querySelector('.btn-roll-1').addEventListener('click', play,);
}while(activePlayer === 1)
}
Ignore the scaffold code that completes the demo, and look at the event listeners.
We only activate if the active player is correct.
// This is just for the demo ignore
const play = (player) => {
let newNum = Date.now();
setOut(`Role ${newNum} for Player ${player}`);
};
// This is just for the demo ignore
const hold = (player) => {
setOut(`hold for ${player}`);
};
// This is just for the demo ignore
const setOut = (msg) => {
document.querySelector('#out').innerText = msg;
};
let isActivePlayer = false;
// Here we add event listeners that toggle based on active player.
document.addEventListener('DOMContentLoaded', () => {
document.querySelector('.btn-roll-0').addEventListener('click', (event) => {
if (!isActivePlayer) play(0);
});
document.querySelector('.btn-hold-0').addEventListener('click', (event) => {
if (!isActivePlayer) hold(0);
});
document.querySelector('.btn-roll-1').addEventListener('click', (event) => {
if (isActivePlayer) play(1);
});
document.querySelector('.btn-hold-1').addEventListener('click', (event) => {
if (isActivePlayer) hold(1);
});
document.querySelector('.btn-switch-plyr').addEventListener('click', (event) => {
isActivePlayer = !isActivePlayer;
});
});
<button class="btn-roll-0">Player 1 Roll</button>
<button class="btn-hold-0">Player 1 Hold</button>
<button class="btn-roll-1">Player 2 Roll</button>
<button class="btn-hold-1">Player 2 Hold</button>
<button class="btn-switch-plyr">Switch Player</button>
<div id="out">
<div>

Javascript mouseDown - cannot read currentTarget of undefined

I have a composent with which I would allow maintaining click in order to call multiple function by push-holding. My action dispatch a simple function to Redux reducers.
The objective of my component is to allow people decrease quantity of their order by maintaining a mouse's click. So that it, to allowing visitors have a more fluent user experience.
When I trigger the function my console returns me :
Cannot read property 'currentTarget' of undefined
When I click alone one time it is great. But when I mouseDown it fails with the above message.
Here my reactComponent.js:
import React, {Component} from 'react'
import style from "./OrderRibbon.css";
import equal from 'deep-equal';
export default class OrderRibbon extends Component {
t;
start = 100;
decreaseQuantity = (e) => {
e.preventDefault();
this.props.decreaseOrder(this.props.id)
}
addOrder= (e) => {
e.preventDefault();
this.props.addOrder(this.props.id)
}
orderPushing = (e) => {
e.preventDefault();
this.orderRepeat(e);
}
orderRepeat = (e) => {
if( e.currentTarget.attributes.name.value ){
console.log("EVENT NAME IN ORDER REAPEAT: ", e.currentTarget.attributes.name.value)
}else{
console.log("EVENT NAME IN ORDER REAPEAT: ", e.target.attributes.name.value)
}
if(e.currentTarget.attributes.name.value === "addOrder"){
this.addOrder
}else{
this.decreaseQuantity
}
this.t = setTimeout(this.orderRepeat, this.start);
this.start = this.start / 2;
}
// STOP Calling function
onMouseUp = () => {
clearTimeout(this.t);
this.start = 100;
}
render(){
return (
<div className={style.order_ribbon_layout} >
<div className={`${style.title} ${style.details_element}`} >
{this.props.title}
<div className={style.quantity} >
<div className= {style.quantity_icon}></div>
<span className= {style.quantity_number} > {this.props.quantity} </span>
</div>
</div>
<div className={style.price} >
{this.props.price * this.props.quantity}
</div>
<div className={style.quantity} >
<div
onMouseUp={this.onMouseUp}
onMouseDown={this.orderPushing}
name="decreaseQuantity"
onClick={this.decreaseQuantity}
className={ `${style.cardButton}`}
id={style.decreaseQuantity}></div>
<div
onMouseUp={this.onMouseUp}
onMouseDown={this.orderPushing}
name="addOrder"
onClick={this.addOrder}
className={ `${style.addButon}`}
// ${style.details_element}
id={style.addArticle}></div>
</div>
</div>
)
}
}
I wcan't figure out what is going wrong, if any body have an hint, would be great.
You have event binding issue. You can define like this:
orderPushing = () => (e) => {
e.preventDefault();
this.orderRepeat(e);
}
Or, keeping the same as you currently have, you may use inline event binding like this:
onMouseDown={(e) => this.orderPushing(e)}

Categories

Resources