I am tracking the mousedown state and not only does Secondary mouse button click trigger the mousedown event while failing to deliver on a mouseup event, so does the situation of dragging on something selected (note this is different from dragging to select).
I am currently experiencing this on Safari 6 on a Mac and I'll report back if I see it on other platforms/systems.
Is there a way to intercept this so that my JS program can be not confused about what's going on? For the secondary button situation I simply check event.which === 3 in my handler and just don't mark my button as down, and that takes care of that, but I am using the left button to initiate drag on a selected bit of text as well..
I am not sure I understand what you want to do, but checking which button has been pressed may involve a bit more work other that checking the which property.
Have a look this quirksmode page. The rightclick section contains some code that may help you.
A very thorough explanation on mouse events is also available here. It can really help you deal with browser quirks.
The specific issue here is that mousedown is not triggered when dragging a selection.
The solution is to simply prevent selection where it may become problematic.
Related
My Vaadin web application uses custom buttons that extend from CssLayout.
Click listeners are added to the layout/button with addLayoutClickListener.
Often when the layout/button is clicked, no event is fired.
It seems that the event is only fired when the mouse is not moved at all between press and release. Traditional UI buttons allow mouse movement between press and release, as long as the pointer is still within the button area during release (the 'pressed and armed' state).
Do I absolutely have to use com.vaadin.ui.Button or com.vaadin.ui.NativeButton?
Can someone maybe provide some explanation for why the layout approach does not work reliably?
I was not able to customize the style of the default buttons within a reasonable amount of time (Valo Theme was too complicated for me)
Use button.setPrimaryStyleName("my-button") and you’ll have a blank slate to apply your own CSS.
So... I am working on an interaction design project and I want to create a sencha-style gesture scroll for content areas. The way I've done it so far, is to attach touchmove/start/end events to the content area, and it translateY's the contents. It works in on desktop with mousemove/up/down events, but it jumps around like crazy with touch. I'm not sure whats wrong.. here is a link to a prototype.
**requires webkit.
http://apps.omorphos.com/gesture-scroll
I think it is an issue with the event response, but I tried and haven't been able to nail it down. Any help is greatly appreciated!
So, I figured this out.
What I was doing was attaching the touch event to the list tag itself.. and, that works fine on desktop with mouse events; however, with touch, the target changes and touchend doesn't fire properly.
So, what I did, and what I believe sencha does, ... and I had originally implemented but went in a different direction... is have an absolutely positioned element with a transparent background color floating above the element that will be manipulated. All of the touch events will be captured by that DIV and then the elements below can be manipulated without losing the event data.
In the new version I used HammerJs ... more info: http://eightmedia.github.io/hammer.js/
but i'm pretty sure you could just use standard events; but the good thing about hammer js, is that it will translate touch events to mouse events for testing in the browser, this also means making the coordinates for touch the same as mouse, so you can access mouse event coords via
e.gesture.touches[0].pageX
e.gesture.touches[0].pageY
which let's you write less code.
Part 2:
Additionally... part of the issue is... how do you click on the content/components(e.g. links) below the screen.
How you do this... is you take the coords from the event handler and pass them through this native Javascript function...
var a = document.elementFromPoint(x, y);
this will return the dom element. and all you have to do is trigger the click/tap event.
Which would be great, except it will pick the element with the highest z-index.. so that is your screen obj(the one that is capturing all of the touch events). So, what you need to do, is hide the screen after a tap is registered, and then execute this function 200ms later, and then bring back the screen to capture whatever events.
You can do this with this function...
$(theScreen).on('tap', function(e){
screen.hide();
var hit = document.elementFromPoint(e.gesture.touches[0].pageX, e.gesture.touches[0].pageY);
$(hit)[0].tagName !=="A" || $(hit).trigger('click');
setTimeout(function(){screen.show()},300);
});
And, that is how I solved it!
My code is not super annotated, but you can find it at the link below:
Updated example:
http://apps.omorphos.com/gesture-scroll/v2/
I was trying to answer an issue with custom drop down, but challenged by an inconsistent behavior in Chrome and Firefox.
DEMO: http://jsfiddle.net/fyeht/ [Added scroll event for more clarity]
See below image, The list items can be navigated using arrow keys.
To Reproduce the issue:
Open console in Chrome (F12)
Click on an item in the list (you would notice some events getting logged in the console)
Use down arrow key to navigate to the next item in the list
Finally, the issue is noticed when you reach the last item in the view and hitting down arrow would scroll. Check the log to see 'scroll', 'mouse enter' and 'mouse move' [check the new demo]
The issue is after reaching the end of items in view, it scrolls. Even though the mouse is untouched, it triggers mouseenter and mousemove events in Chrome. In FF, on scroll it triggers just the mouseenter which make sense.
Question(s):
Why is mousemove triggered when mouse is untouched?
Is this just browser inconsistency? Could not find documentation on events triggered when scrolling? (never knew it did)
Submitted a bug report: https://code.google.com/p/chromium/issues/detail?id=241476
In your example, I see that both Chrome and FF are firing mouseenter DOM events whenever the mouse is left hovering over the <ul> and pressing the key down triggers the browser to scroll in order to bring the selected <li> into view.
However, only Chrome is additionally triggering mousemove events. One obvious difference already in the mouseenter event objects that the two throw is that for Chrome, MouseEvent.offsetX and MouseEvent.offsetY values are included, whereas in FF these properties are undefined. So, when that enter is triggered Chrome has already decided the mouse "has moved".
Since the MouseEvent.screenX and MouseEvent.screenY event context values do not change between scroll-triggered MouseEvent instances, one could perhaps distinguish between an "artificial" mouseenter / mousemove event and an "authentic" one by storing these values from prior events.
DOM Event Specification
The DOM Level 2 Event Specification for mousemove reads:
The mousemove event occurs when the pointing device is moved while it is over an element.
The Level 3 spec (working draft) is essentially the same:
A user agent must dispatch this event when a pointing device is moved while it is over an element.
Seems like it could down to whether one interprets "is moved" relatively or not.
Also, in the section of the Level 3 spec on mouse event order, it states that when a pointer is moved into an element, it triggers mouseover, mouseenter, and mousemove, in that order. Every case that is specified there always has those three together, so perhaps one might interpret it that if you are going to trigger the mouseenter event, you should also be triggering the mousemove event which corresponds to entering the element.
This is a nice demo.
In Chrome mouse movement for elements is definitely relative. In chrome I can get keydown and scroll events only if the mouse pointer is over the scroll bar. I can also get scroll only events if i use the wheel to scroll and leave the mouse over the scroll bar. It is and isn't very odd that scroll by dragging causes "mouse move", and "mouse over" events.
Not only are mouse move and mouse over events produced in profusion by the browser they are not a very good indication of a users intent. Infact these events are a useful entropy source.
To the degree that there are some minor differences this is in the context of how useful these "micro events" are individually. To work with them you must devise a way to filter them for user intention you want to link to higher level actions. Any reasonable method you choose to make sense of these events will probably detect these move - on scroll events as garbage. This is where your point is really worth noting and taking under consternation.
A first stage would be to Filter out events based on the elements and values of coordinates. It might help to create a state machine model. You might register and registered handlers in response to other events. You've identified this case where you'd want to change responsive state if or reaction criteria if a key element has a scroll bar. IF an element or it's parent has a vertical scroll bar throw out mouse moves with relatively high X values.
You might want to also ignore mouse overs if it's fired with a mouse move in that context. It starts to become impractical to handle each of these micro event one at a time even if you are changing state by registering or deregistering handlers. More information can be extracted by creating an event sequence fifo buffer.
Register event handlers to add a new event to the buffer. You might also want to collect information from timer events in this buffer to establish more context. You might create an object that keeps a fifo in an array. This would be like a queue but not in the sense of it being a place where the events are waiting to be processed. Instead your program is waiting to calculate patterns in the buffer and based on the patterns fire higher level events, accept or reject different types of events and extend, contract or save the contents of the buffer. You can then evaluate move events for changes in x and y and also create conditions given the patter of scroll mouse over and mouse move events you've demonstrated.
I really doubt there's a browser inconsistency here. You should create a mousemove event that prints out the x and y coordinate. You'll probably see that the mouse has indeed moved a little bit. If that's the case, try using the plugin hoverIntent to eliminate issues like this.
EDIT:
Using the up and down arrow keys, I'm now able to replicate the issue. Yeah, it sure looks like some kind of bug! I bet the mousemove coordinate delta is tiny. Maybe the cursor moves one or two pixels? I would say, to overcome this, add a check to the mousemove function that compares previous mousemove's x-y coordinates to the current mousemove's x-y coordinates. Determine if it's more than just a few pixels. If so, you know it's a real mousemove. If it's less, you can chalk that up as a chrome bug.
FURTHER EDIT:
It seems like you uncovered a bug where mousemove is being fired in chrome when it probably shouldn't be. There may be workarounds that you could figure out if you hack it enough. But the best solution might be just to avoid using mousemove in this situation. In general, mousemove is one of those expensive events that should be used only when you really need it.
This is not a bug. The mousemove is relative to element that the event is attached to. In your case, you see that your mouse is not moving because you took the browser window as the reference. But for that scrolling list, whenever the list is scrolled, the mouse pointing over some element of the list moved to over different element
Imagine that you as the Earth, a cup of coffee stand still on a table as the mouse, the scrollable list as the Sun : if you (window) don't move, the position of the cup of coffee (mouse) is at the same place for you; but for the Sun (list), it will see that the Earth and the cup of coffee are both moving.
I have a div, with an onMouseUp event set (in HTML).
Within that div are many elements, some of which contain icons for handles that I want to drag.
The icons have an onMouseDown event.
When I drop the mouse on an icon and release it, first the icon's onMouseDown event fires, then the div's onMouseUp event fires - exactly as I would expect.
However when I click down on the icon, drag it to another part of the div, and release, the mouseDown event is fired as you would expect, and the onmouseUp event is NOT fired.
I have two questions.
1) Why is this the behaviour?
2) What is the correct way to handle drag-drop in a browser independant way?
I am using firefox 3.6.16 on widows, but IE 8 behaves the same way.
I know this doesn't seem like it's a fair answer, but the best answer (in my opinion) is to use something like jQuery and use draggable. I've only worked with Dojo and jQuery but both have an easy to use drag/drop interface that is browser independent.
Here's a url explaining jQuery's.
http://jqueryui.com/demos/draggable/
I'm just wrestling with this today. There is a nice demo at http://www.brainjar.com/dhtml/drag/demo.html that uses raw Javascript (with all the browser checks that that implies). It looks like the key is to stop event propagation on the mousedown event.
I'm working with Dojo, and using dojo.stopEvent in the dragStart (that is, the function attached to mousedown) made the difference in my seeing the mouseup.
I'm trying to implement a drag and drop script and have hit the wall with one problem. When you take an item and start dragging it - the item is directly below your cursor and onmouseover event is very rarely fired on the items below. But i want other items to highlight when i drag something over them. One of the solutions would be not to drag anything at all - that way the mouse events would work, but that would look ugly. Has anyone ever done something like this and know how to overcome this problem?
If you're thinking about suggesting some JQuery plugin or something like that - please don't. I don't need a completed solution, this is educational.
IMO, in order to have the mouseover event to be fired up frequently would be binding the mouseover event to the parent element of all the affected elements, or perhaps to the document itself, since events get bubbled up, they are probably the only elements that can fire the mouseover events.
Then further, write a hit method in your mouseover event and actively check the position of your mouse cursor, see whether it's going under the target element's boundary. Tradeoff in usability and performance. You choose.
My 2cents.
Or perhaps, you can reverse engineer jQuery UI to see how they implement the drag element. Haven't check thou, but I think there should be a wiser way.