Stop button losing focus when contextmenu event fires - javascript

I've got a react application that has a need for a piece of content to play when a button is held down and then stop when the button is released.
I've implemented this by creating a helper to handle detecting a longpress, when onMouseDown or onTouchStart is fired then it plays, when onMouseUp, onMouseLeave or onTouchEnd fires it stops. This all works perfectly on desktop. The issues comes when we take a look at mobile, mobile treats a long press as a right click in the desktop and tries to launch a contextmenu or highlight an element/piece of text, to deal with this I've added the following css:
touch-action: none;
user-select: none;
-webkit-user-select: none;
-webkit-touch-callout: none;
and the following Javascript:
window.oncontextmenu = function (event) {
event.preventDefault();
event.stopPropagation();
return false;
};
This works as expected in the sense that the contextmenu doesn't display, however the button that is being held does lose focus, meaning that the content continues to play and the onMouseUp, onMouseLeave or onTouchEnd events never fire unless you tap somewhere on the button or screen again, I've tried solutions like reapplying the focus to the button during the onContextMenu event however that doesn't work either.

Mobile user agents do not consider a long touch as a right click when the target element is a button (because there are no mobile compatible actions on a button, other than just click). I suggest you to verify that the button you're talking about is an actual button.
const button = document.querySelector('button');
button.addEventListener('mousedown', function() { this.classList.add('red') });
button.addEventListener('touchstart', function() { this.classList.add('red') });
button.addEventListener('mouseup', function() { this.classList.remove('red') });
button.addEventListener('mouseleave', function() { this.classList.remove('red') });
button.addEventListener('touchend', function() { this.classList.remove('red') });
.red {
background-color: red;
}
This link does trigger a context menu on a long touch <button>This button doesn’t</button>
If that does not answer your question, please add the actual HTML code.

When using this on desktop clicking my mouse would fire the mousedown event, which is expected, when using this on mobile it was firing two events at the same time, meaning when it would fire touchend it would also fire mouseleave or mouseup, i'm unsure why this was happening but to resolve my issue I just conditionally added the event listeners, so for mobile I now only add event listeners for touchstart, touchend and touchcancel.

Related

event.stopPropogation() not working in IPAD/Tablet

I am using coveo Framework and i used facets inside a dropdown button i wrote a window.onclick function so that when clicked outside dropdown button the dropdown should be closed.
everything seems to be working fine but when i clicked facets checkbox the dropdown was closing and when i talked to coveo team they said the query was triggered when coveo checkbox was clicked thats the reason the dropdown was closing when clicked.
To fix this i used event.stopPropogation and that was working fine in desktop mode but when it comes to IPAD Mode this is not working any help
Here is my code
// Prevent event bubble up to window.
document.getElementById('dropdown').addEventListener('click', function(event) {
event.stopImmediatePropagation();
});
function close() {
document.getElementById('dropdown').classList.remove('show');
}
window.onclick = function(event) {
if (!navigator.userAgent.match(/Android|webOS|iPhone|iPod|Blackberry/i)) {
if ((!event.target.matches('.dropdown-backdrop')) && event.target.closest('#dropdown') === null) {
close();
}
}
};
I believe the issue is on a touch screen device, you actually get touch events possibly in addition to mouse events. I suspect if you attached another listener to touchstart that does the same thing as click you will see the same results on the tablet.
In theory you should see no click events on a tablet (a user cannot click without a mouse) but in practice the browser emulates click events. However, when those events are generated the browser may fire both touch events and mouse events in response to the same user input. If both events are fired you're successfully stopping the click event from propagating but not the touch event.
Update
You haven't given enough detail to fully give an example, but the change happens in the listeners you attach to your dropdown element.
// Note instead of using the same anonymous function twice,
// I've defined a function to stop propigation
function stopProp(e) {e.stopImmediatePropagation();}
document.getElementById('dropdown').addEventListener('click',stopProp);
document.getElementById('dropdown').addEventListener('touchstart',stopProp);

Phonegap touch not working: simulate click on mobile

I have the code:
wrapper.addEventListener("click", function (event) {
//do thing
});
However it doesn't fire in mobile.
I tried replacing click with touch but then nothing happens. I tried replacing click with touchstart and the activates, but it also triggers when I'm trying to drag on top of the element.
How do I grab a click event while ignoring a drag event?

createjs prevent hyperlink interaction

In my simple application canvas wrapped by hyperlink. Some objects, which are placed on canvas stage have special mouse interaction on click event. Is there any possible solutions to prevent hyperlink jumping by clicking on objects with my mouse click event listeners?
Normally you can just call preventDefault on the generated mouse event, and it will stop the link event from firing.
element.addEventListener("click", function(e) {
e.preventDefault();
}, false);
This is not possible using EaselJS because although you can access the nativeEvent on any EaselJS mouse event, EaselJS doesn't use the "click" event at all (and instead uses a combination of "mousedown" and "mouseup"). So preventing default on a click event will do nothing.
Doesn't work
// You would expect this to work.
myShape.on("click", function(e) {
e.nativeEvent.preventDefault(); // Nothing. This cancels a "mouseup" instead.
});
Workaround
However, you can work around this pretty easily. Set a flag on the clicked item (or wherever you would set it in your application) any time it is clicked.
myShape.addEventListener("click", function(event) {
myShape.clicked = true;
}, false);
Then, listen for the canvas click event yourself, check and check the flag. Make sure to reset it after. This is possible because "click" is always fired after "mouseup"
stage.canvas.addEventListener("click", function(event) {
if (myShape.clicked) { event.preventDefault(); }
myShape.clicked = false;
}, false);
Here is a quick fiddle showing it working. http://jsfiddle.net/buqkvb1u/
We are looking to see if this makes sense to handle in EaselJS. Thanks for your report!

Event listener does not register click event on certain types of elements

I'm making a Firefox extension to record user clicks on a website. I'm using eventListener to detect clicks on any elements on the website but for some reason clicks on input elements or dropdown options are not registered. Any idea on why this is? Here's the code for the extension:
alertClick : function(aEvent) {
document.addEventListener('click', function(e) {
window.alert("click");
}, false);
Moving to solution:
Instead of click try mouseup or mousedown. The reason is because click does not fire IF you mousedown then move your mouse too much and/or wait a long time and then do mouseup.

trying to stop multiple event triggers on android tablet

I'm making a website that will be displayed on a desktop/laptop and a tablet. The problem is that my touch events trigger both mouse and touch events, so the functions that use events like swipe are called twice. I've tried to solve the problem by detecting the device and then unbinding mouse events. But my approach has not stopped the mouse/touch functions from being triggered twice.
Here is my code:
//Device Detection
(function () {
var agent = navigator.userAgent.toLowerCase();
var isDevice = agent.match(/android/i);
if (isDevice == 'android') {
alert(isDevice);
$('*').unbind('mouseenter mouseleave mousedown mouseup mousemove');
}
})();
This function is placed at the end of my .js document. I tried to be cautious and unbinded every mouse event I could think of, but it has not worked. Please help.
(Note: this thread's approach has not been helpful either: Click event called twice on touchend in iPad)

Categories

Resources