I am using the following code to make the browser follow a link on mouse down instead of on mouse up (like a normal click).
$('#links a').each(function(){
$(this).mousedown(function(){
window.location.href=$(this).attr('href');
});
});
First of all, is this good practice? GMail does this and it gives the effect that the page is loading faster than it actually is.
Also, is there a better way of doing this? I haven't tested this in all browsers yet, so I'm not sure if it works in older browsers.
The mousedown function is not supported by Internet Explorer version 5.5 or earlier. jQuery normalizes the browser-specific behavior of the event capture into the mousedown function.
As to good practice or not, I don't see a tangible performance benefit from handling mouse click events in this way. So, unless you have a specific reason for doing so, I would stay with standard conventions.
The only thing that should happen on mouse down is any necessary effects to show the user the mouse button is indeed down.
The reason you don't execute anything until mouse up goes back to at least the Apple Human Interface Guidelines for the original Macintosh: This gives the user the option of "canceling" their click by moving the mouse off the button before letting go.
Doing things on mouse down will give the user the sense that your program is pulling the rug, er, dialog box out from under them.
Related
I've looked everywhere for how to capture touch pad input for laptops but I can't seem to find anything for Chrome extensions/JavaScript.
Question: how can I capture the number of fingers down (not clicked, just down and potentially moving as you would with a mouse), their corresponding x,y coordinates, and their corresponding up events, for a touch pad on a laptop?
Clarifications:
I'm not interested in detecting touch screen events. Just touch pad
events.
Can assume the touch pad lives on 3 year old or newer lap tops.
I can't find it by now, but I somewhere read about this topic. But the synopsis is simple: it's a draft/in development but no browser supports it by now.
Here is the W3C draft: https://w3c.github.io/pointerevents/
I think it is not possible to do this using JavaScript only. Let's take it this way:
Consider the following situation:
I am using a Macbook pro 13in Retina Display, with multi touch and multi gesture touchpad.
Now Suppose if I have gesture settings in my Operating System that if I tap two fingers, register it as a normal Left Click, and when I tap a single finger, register it as a right click.
Now imagine we are capturing both the events, click and dblclick, now tell me which event will get fired when I will do a single tap with one finger. It will be a dblclick, and when I will do a tap with two fingers it will be click event fired.
Another Case: Imagine i have inverted scrolling turned on in my computer, now when I will scroll upwards my page will scroll downwards. And this is something which chrome/ firefox is not controlling.
Conclusion:
There can be varied number of such settings across varied types of operating system, across varied number of devices such as trackpads, trackballs, touchpads, mouse, magic mouse etc. This gives me a feel that there is a layer between the external hardware and the browser detecting the firing events and this layer is provided by the operating system. Its operating system which manipulate the events according to the user defined/preset settings.
There can be devices which intent to provide and fire multiple events like touch device, on touch they fire multiple events. But that is not the case with all the devices. So it doesn't matter if you are clicking from mouse or from the trackball or from the touchpad or from the touch screen you will get one common event that is a click, there is definitely a possibility that some more events are fired but they are dependent on the type of device and not on the settings you have done in your Operating System.
One way you can capture is the event is by establishing some sort of connectivity between your browser web page and operating system as suggested by #AlvaroSanz.
to develop such kind of extension, you need to write chrome native client with Windows Touch Input to make it happen.
I know that you´re asking for a solution for Chrome extensions/JavaScript but I´ve been searching and getting nothing, so I finished with a possible solution combining VB and JavaScript.
There is VB api for Synaptics (https://autohotkey.com/board/topic/65849-controlling-synaptics-touchpad-using-com-api/) and you can call javascript from VB (http://www.codeproject.com/Articles/35373/VB-NET-C-and-JavaScript-communication#cjfv), it's a long way, but it's a way.
Making a nice quick-responding website is relatively difficult because of the conflicts between touchstart, tap and the 300ms delayed click.
Ofcourse vclick should fix these issues, but also they seem to have problems fixing it completely. From the documentation:
Warning: Use vclick with caution
Use vclick with caution on touch devices. Webkit based browsers
synthesize mousedown, mouseup, and click events roughly 300ms after
the touchend event is dispatched. The target of the synthesized mouse
events are calculated at the time they are dispatched and are based on
the location of the touch events and, in some cases, the
implementation specific heuristics which leads to different target
calculations on different devices and even different OS versions for
the same device. This means the target element within the original
touch events could be different from the target element within the
synthesized mouse events.
We recommend using click instead of vclick anytime the action being
triggered has the possibility of changing the content underneath the
point that was touched on screen. This includes page transitions and
other behaviors such as collapse/expand that could result in the
screen shifting or content being completely replaced.
Now I'm thinking about doing something simpler. Whenever a touchstart event is being triggered I know this is a touch device for sure. I just disable all click events, and start listening to touchstart (or tap) events only. Ignoring the 300ms delayed click events.
Of course there are devices with a mouse and touch, but people using these at the same time seem like a minority to me.
Is this a good idea, or am I missing something in my thinking?
First of… what makes you say that people that use both touch and mouse input are a minority?
The 300ms click delay has been gone a while now on Android when using <meta name="viewport" content="width=device-width">. Unfortunately it can't be removed on iOS because it's a scroll gesture on unzoomable pages that almost nobody seems to be aware of.
I'd say that the best approach is still to support both mouse as well as touch input, despite the 300ms delay on iOS devices. It's dangerous to assume a user will exclusively use touch input when they use it once.
Imagine a user happily using a mouse to navigate. They see something interesting that they want to look at a bit closer so they use a touch gesture to zoom in and all of a sudden mouse clicks don't work anymore. That sounds broken to me.
I just remembered an interesting discussion about detecting a mouse user. Maybe it'll help you see things a bit differently.
Yes, in my honest opinion it is smart way to go. This has proven to be quite a hard problem and when you still combine it to the compatibility problems caused by some really crappy mobile devices which don't follow standards even that bit, it quickly becomes a battle that you can't win. We have adopted a solution close to this, with realization of fact that there might arise problems with poor devices. But after all, you can't satisfy the needs of everybody and the distribution of usage tends to favor those devices (nowadays) that follow the standards.
Also note that you don't need to wait for first touchstart to happen. Instead you can do this trick after DOM is ready and bind the events accordingly.
var isTouchDevice = 'ontouchstart' in document.documentElement;
which is copied from KevBurnsJr's answer.
Also as you most probably already know, you can bind to all kind of events and then check when entering the callback of which type the event actually is with
event.type
Good luck!
It would be a bad idea to disable all click events on the basis of a single touchstart as you suggest. While using both pointers or touch at the same time isn't a common use case. Preventing dual use of mouse/pens and touch isn't a forward compatible approach.
And when you say: "Ignoring the 300ms delayed click events."
I think you make a false assumption on click. You'd still have to synthesize clicks one way or another. touchstart alone isn't a click action. An assumed click happens on touchend, not touchstart. Here is the principle behind detecting clicks early on mobile: https://developers.google.com/mobile/articles/fast_buttons
If you are looking for fastclicks you may want to look into the fastclick script or other fastclick ones on github instead of vclicks.
To avoid issues with people using both touchscreen and mouse with pleasant reactivity I suggest this in JQuery, it works good enough for me:
$elem.on('click touchstart', function(e){
var $self = $(this);
if(e.type == 'touchstart'){
$self.mouseenter(); //fire events you still need
e.preventDefault();
}
/* your code */
});
From my experience it's better than keep the delay on click event and some hazardous comportment through devices, but there's inconvenient too.
On the iPad I tested, it avoids the situation where hover event is triggered on first tap then click event on second tap, but also it seems that the click event fire when you tap near the border of your element and not the touchstart, have to keep it in mind.
Also, it seems not working well with 'tap' event, certainly because it's not well treated yet by JQuery.
I'm developing a web game application with a, HTML5 canvas that has to react to "click" events (in the general meaning).
On a mobile platform (or touch-capable), that means reacting to onTouchDown, on a desktop/laptop platform (with a mouse or pad), that means reacting to onMouseDown.
Problem is, if I handle both events, then sometimes the same "click" will result in both events getting fired, so I get a double signaling.
What would be the best way to handle that?
Currently, upon the first touch event I receive, I turn off mouse events, but that may be a bit heavy handed if the platform supports both touch & mouse clicks (f.i. an Android tablet with attached keyboard/pad/mouse)
Measuring the delay between touch & click to ignore a click after a touch doesn't work too well, as there are circumstances where user may touch/click at a high frequency, so a too long delay leads to dropped double taps/clicks, and a too short delay lets through the occasional double signaling slipping through.
I've looked at user-agent detection, but that seems quite fragile (many user agents out there), and doesn't solve the cases where the platform has both touch & mouse/pad.
Maybe a combination of your suggestion:
Measuring the delay between touch & click to ignore a click after a touch doesn't work too well, as there are circumstances where user may touch/click at a high frequency, so a too long delay leads to dropped double taps/clicks, and a too short delay lets through the occasional double signaling slipping through
And detecting the x,y coordinates of the tap would decrease the false positives. So if both events (tap & click) happening in sequence got the same coordinates they are handled as the same.
Or maybe let the user switch (through some sort of options screen) if he wants to use mouse or touch for his device if both is supported. Display a warning message for example saying you're on a touch device so we enabled touch events, if you're using a mouse please see options or something like that.
Most users would be happy with the auto-choice and everybody unhappy can change it.
One major barrier to creating immersive experiences in the browser (using WebGL and similar) is the set of limitations placed on mouse control.
For instance a first person shooter control scheme essentially requires the program to grab the mouse and re-center it so as to allow infinite movement in any direction for the cursor. This is a no-no because it would give the web programmer too much control. Hopefully one day we will see a plugin that allows a site to request permission to move the mouse to allow this behavior.
However I think there are some ways to improve things without going that far. I am wondering if it's possible to allow access to the mouse position once the mouse moves off of the window (focus is still on window)?
I was playing this game using Google Chrome: http://www.chromeexperiments.com/detail/x-wing/?f=
and my biggest issue was that to get to a corner, I have to carefully keep my mouse on the corner of the browser window. If I push it off the window my ship would stay where the mouse's last window position was, which is not exactly in the corner. And I would crash into the wall.
To make this better, the browser should be able to receive mouse updates when the mouse is outside of the window. In the context of this type of game if the mouse leaves the window it should continue to send updated positions to the browser.
Is there any provision for this?
To answer your question, no, you can't get mouse events from outside the window (including its position).
There is the Mouse Lock API, which is designed specifically for the case you describe. It locks the cursor to the current window. Support is virtually non-existent right now, but one day..!
A hint :
function thumb_mouse_down(e) {
e.target.setCapture();
return false;
}
function doc_mouse_up(e) {
e.target.releaseCapture();
}
setCapture() does the trick. A working example is here.
That really seems like a far bigger security issue than allowing the developer to reposition the cursor. The answer is no, there's no such thing. And there probably won't ever be one. Sorry!
Update: I was, of course, talking about the capturing outside the window that would be a problem. It's very likely that there will ever be an API that locks the mouse, maybe after asking the user's permission. As nickf pointed out, they're already working on it -https://www.w3.org/TR/pointerlock/
Original defunct link - http://dvcs.w3.org/hg/webevents/raw-file/default/mouse-lock.html
I have coded a jquery script where there is a small grid on screen and using drag and drop users can place tiles on the grid (snaps in place). Currently if you hover over a tile it fades in the option to rotate, but I would much prefer it if you could right click to rotate (making it more natural). I understand blocking right click completely is often frowned upon so was wondering if it was possible just within a particular element, then capturing that event, doing something in JS and disabling the context menu? - that works in every browser.
On a side note, currently I am using jQuery for effects and custom javascript for drag and drop, is it worth looking at a jQuery plugin for drag and drop?
Many thanks,
For capturing the right click, you can use this jquery:
$('#gridID').bind('contextmenu', function(e) {
// do stuff here instead of normal context menu
return false;
});
This works in chrome, firefox, and safari. Haven't tested IE. Works in IE too. Only caveat is it doesn't work in Opera apparently. So if you can live with that...
I'm not a fan of using the right mouse button on web pages. However, if you really want to do it, you could trap the right mouse button as described here. You could block the right mouse button (in other words return false in your event handler) conditionally if the mouse is over your grid cells.
Regarding your bonus question: jquery ui has drag & drop functionality. It's probably easier to use that than rolling your own.
"is it worth looking at a jQuery plugin for drag and drop?"
Only if you don't intend your application to be used on the iPhone O.S with safari, i.e. including iPad, see Safari Web Content Guide: Handling Events