I've used onclick events in my website. But when I open it in google chromes' developer mode's mobile view, nothing happens on touch on the elements which work on click with mouse. So my question is:
Do I have to also add ontouch events along with onclick events, or onClick event work on touch on all touch-screen devices?
P.S: You can see all of my codes here: https://github.com/SycoScientistRecords/sycoscientistrecords.github.io/
Or at the live website: http://sycoscientistrecords.github.io
And no I haven't tested the website on real phone.
onclick works fine on touchscreens; I've used it several times and have never had any problem.
You could consider using onmousedown instead of onclick. Or use jQuery to detect taps.
I found this detailed writeup at MDN very helpful. In particular:
the browser may fire both touch events and mouse events in response to the same user input [emphasis mine]
and
the element's touch event handlers should call preventDefault() and no additional mouse events will be dispatched
So, your touchstart or touchend listener can call evt.preventDefault() and your mousedown / mouseup listeners won't fire because they come later in the chain.
In Angular, I was able to detect whether I'd clicked a button using my mouse or my laptop's touchscreen, by changing (click)="doSomething()" to (mouseup)="doSomething(false)" (touchend)="doSomething(true); $event.preventDefault()". The method is called with true for touch events and false for mouse events.
onclick may not work on touch devices, I had this issue and the event ontouchstart sorts it.
if you use ontouchstart and onclick watch that you don't trigger the event twice.
this is another post related
onClick not working on mobile (touch)
New browsers have a pointerType which determines if the onClick is made by a mouse or via a touch. If you just want make adjustments in user behavior based on the input, using pointerType is the safest way.
if you are using jQuery:
$(selector).click(e => {
if (e.pointerType === "mouse") {} // mouse event
else {} // touch event
});
if you are using vanilla JS:
element.addEventListener('click', e => {
if (e.pointerType === "mouse") {} // mouse event
else {} // touch event
});
If you are using React, the event is wrapped around a synthetic event. To access the pointerType, you have to use the nativeEvent of the react event. Here is what you need to consider (especially if you are using Typescript). If the event is triggered by a mouse, the native event is an instance of MouseEvent which does not have pointerType, so, first you need to check the type of native event which will also take care of the typing problems in TS
<div
onClick={e => {
if (e.nativeEvent instanceof PointerEvent && e.nativeEvent.pointerType === 'touch') {} // Touch Event
else {} // Mouse Event
}}
></div>
Pro tip: If you want to test the touch event in development, use Chrome following this. Note that Safari has a responsive mode which simulates the framework of iPhones and iPads. However, Safari always registers a mouse event even when you are in responsive design mode and have selected an iPhone or iPad.
Related
Browsers support touch events and might generate mouse events. Also, for a long touch the browser generates a ContextMenu event. However, in my industrial environment, I want all touch events to be handled like a click event. Is there a global setting to prevent the browser to generate context menu events? Or can I at least set the time when the browser will generate such an event?
My only solution I came up with so far is the subscribe to click and context menu events and call the same handler. However I would rather avoid this for every button in my application...
Any ideas?
There are several answers at Disabling the context menu on long taps on Android
But I think the most voted answer over there is not a good one.
Try and see if this work for you,
window.ontouchstart = function(event) {
event.preventDefault();
event.stopPropagation();
return false;
};
I would like for a button to react to 'touches' on a touch screen, and 'clicks' on a non-touch screen. In case of a touch screen, I only want the touchstart handler to direct my flow and prevent the system from further handling the click event.
For this, I added two event listeners to my button. One listens for touchstart events. Once a touchstart has been detected, it uses event.preventDefault() to cancel the click event.
The code below on a touchscreen in Chrome, Opera and Android browsers achieves the desired result:
- one alert saying "touch".
However, in Firefox both events are detected, in spite of the preventDefault() in the touchstart handler:
two alerts... first one says "touch", followed by a second alert saying "click".
lginButton.addEventListener('touchstart', function(event) {
event.preventDefault();
alert("touch");
}, false);
lginButton.addEventListener('click', function(event) {
alert("click");
}, false);
Why is this happening and how can I achieve the desired results in all browsers?
I am currently unable to test. But based on your feedback it appears that Firefox is in fact not following the spec on events found here. I was about to find 4-5 bug logs on Mozilla that discussed this very topic, and finally found one that resolved the issue here https://bugzilla.mozilla.org/show_bug.cgi?id=977226. Definitely check to make sure you have the current version of firefox. And if you do it may be worth opening a new bug with mozilla on this. In the meantime you can set up a conditional inside of your touchstart event handler that detects the event type and handles touch and mouse events differently.. And then further adding more conditionals within you click conditional to handle browser and OS version. which is super bad practice, but would keep you going until a patch was implemented.
I am curious about this one. Does creating a div imitating a button (with 'click' event binded to it) is user-friendly? I mean, does all mobile browsers accurately treat it and always fire event when div is clicked?
Does replacing such constructions with normal buttons increases responsivness on mobile devices?
Google describes this pretty well i think here.
So as described there, handling the click event adds a 300ms delay because it is waiting to see if it is a double-tap.
The technique involves a bit of JavaScript that allows the button to
respond to touchend events rather than click events. Touchend events
are fired with no delay so this is significantly faster than click
events, however there are a few problems to consider:
If the user tapped somewhere else on the screen and then invokes a
touchend on the button then we should not fire a click.
If the user touches down on the button and then drags the screen a bit and then
invokes a touchend on the button then we should not fire a click.
We want to highlight the button when the user touches down to give it a
pressed state.
We can solve the first two problems by monitoring touchstart and touchmove events as well.
We should only consider a touchend on the button if there was previously a touchstart on the button. Also if there exists a touchmove anywhere that goes past a
certain threshold from the touchstart then we should not handle the
touchend as a click.
We can solve the third problem by adding an onclick handler to the
button as well. Doing so will allow the browser to properly treat it
as a button, and our touchend handler will ensure that the button is
still fast. Also, the presence of an onclick handler serves as a good
fallback for browsers that don’t support touch events.
Another advice from experience would be to avoid anchors for buttons.
They recommend using Touchend instead of click.
I've got a Backbone app, and I'm using Modernizr.
On touch devices, I can't swipe the page to scroll it down, because touch events are triggering Backbone listeners and a series of complex events, rather than the usual page scroll.
This is my code:
events: function () {
if (this.modernizr.touch) {
return {
'touchstart .hover': 'onTouchStart'
};
} else {
return {
'mousemove .hover': 'onMouseMove'
};
}
}
// onTouchStart and onMouseMove both fire a listener
What event should I be using to distinguish swipe from click, so that swipe allows the user to move the page as normal? (I can't easily test on a touch device, just so you know this isn't a lazy question.)
Is your onTouchStart function calling event.preventDefault()? If so, that’ll stop the event triggering the native swipe-to-scroll behaviour. Removing that call should allow users to scroll normally.
This HTML5 Rocks article goes into quite a bit of detail about how touch events propagate/cascade.
Side note: The pattern you’ve used here makes a few dangerous assumptions IMO:
By only binding mouse events if Modernizr.touch is false, users with hybrid devices (touch-capable laptops etc) won’t be able to use the mouse/trackpad; why not just bind both events?
Some browsers/devices can’t fire touchstart or mousemove (keyboard users, Windows smartphones, etc) so won’t be able to use this functionality; if you bind to click events too as a fallback, you’d have them covered
I recently wrote an article about what I consider the “golden pattern” to cover all eventualities, if you’re interested.
Of course if the functionality those handlers provide is non-critical these things might not be a problem.
I'm trying to write a web application that can respond to both touch events and mouse events. Webview on android (and maybe other environments) trigger a mousedown event and a touchstart event when the phone is tapped. I'm running into a problem where the touchstart event triggers a page change, and the mousedown event is clicking a different button in the new page.
If its possible, the easy solution would be to force webview to not trigger mouse events alongside touch events (but only when an actual mouse is clicked).
I've read the answer here: How to bind 'touchstart' and 'click' events but not respond to both? but it doesn't cover this case.
Anyone know how I can solve this problem in a general way?