Suppose we have a <div> with a mousemove handler bound to it. If the mouse pointer enters and moves around this div, the event is triggered.
However, I am dealing with a rich web application where <div>s move around the screen, appear and disappear... So it may happen that a <div> appears under the mouse pointer. In this case, mousemove is not triggered. However, I need it to be. (Note that replacing mousemove with mouseover does not change this behavior.)
Specifically, the <div> has to be highlighted and I deem it as a UI flaw to require the user to do a slight mouse move in order to trigger the highlighting.
Is it possible to trigger the mousemove event programatically? And I do not mean
document.getElementById('mydiv').onmousemove();
because onmousemove is parametrised by the event object, which I do not have.
Is it possible to make browser behave as if onmousemove was triggered on the current mouse's position (although in fact the mouse didn't move)?
You could modify your mousemove to keep a state variable with the current mouse coordinates, and use that information to perform a collision detection that you call both on mouse move, and on moving a div.
A little example of what that might look like
You actually can create a mousemove event object to pass in, using something like this:
window.onload = function () {
document.getElementById("test").onmousemove = function(e) { console.log(e); };
document.getElementById("test").onclick = function(e) {
var e = document.createEvent('MouseEvents');
e.initMouseEvent('mousemove',true,true,document.defaultView,<detail>,<screenX>,<screenY>,<mouseX>,<mouseY>,false,false,false,false,<button>,null);
this.onmousemove(e);
};
};
Of course, here I'm firing it on a click, but you can do it on whatever event you want, such as when your div becomes visible, check to see if the mouse is within it. You just need to make sure your parameters are right, and you need to track the mouse position on your own. Also, there's some differences in IE, I think. Here's my source: http://chamnapchhorn.blogspot.com/2008/06/artificial-mouse-events-in-javascript.html. He added a little extra code to account for it.
Here's a fiddle to play around with. http://jsfiddle.net/grimertop90/LxT7V/1/
Related
For an SDK add-on, I am trying to detect, on right-click, the closest page anchor (as described here).
Since JavaScript apparently has no way to query the mouse coordinates without first creating a mouse event listener, and since I don't want an expensive mouseover listener running all of the time on every single page! (and polling to rebuild a mouse listener is ugly and not fully accurate anyways), I was hoping I could get the mouse coordinates from a click event. Unfortunately, although self.on('click' does fire:
This event is without an event object from which mouse coordinates could be obtained
Adding a normal window.addEventListener('click',... listener doesn't actually get fired in the SDK content script with the first menu selection for some reason (it does fire subsequently, however).
Here is my workaround, but I want to fire on the current exact coordinates, not the coordinates of the node:
var x, y;
window.addEventListener('click', function (e) {
if (e.button === 2) {
x = e.clientX;
y = e.clientY;
}
}, true);
self.on('click', function (node) {
if (!x) { // Since this is not showing the first time, we fire on the node (which is specifically an element, not a text node), though we really want the real clientX and clientY where the mouse is, not this simulation based on where the element is
node.dispatchEvent(new MouseEvent('click', {
button: 2
}));
}
// Use document.caretPositionFromPoint with x and y to determine location of text
Is there any other way to get the actual mouse coordinates?
You can actually query the mouse coordinates without a mouse listener.
This page has a bunch of examples: https://developer.mozilla.org/en-US/docs/Mozilla/js-ctypes/Standard_OS_Libraries
It has to be done on per OS basis though as it uses JS-Ctypes. If you're worried about performance don't fear at all. You can use the code asynchronously via ChromeWorkers
I want to display an image under the mouse (a finger to simulate a touch screen) when a mousedown event occurs and hide it when the mouseup event occurs, but when I do this, the image I display blocks the subsequent mouse events ("click" in particular) on elements under this image. I'm using jQuery, by the way.
I'm sure this is something to do with event bubbling or propagating or somewhat, but I couldn't figure it out. Any pointers please?
Check out this answer to on this post:
https://stackoverflow.com/a/4839672/589909
It seems to do what I understand what you want to achieve using a pure cross browser CSS approach.
pointer-events:none;
touch-action:none;
Billy Moon, your code was almost working. You just have to use hide and show instead of css :
$('#finger').click(function(e){
evt = e || window.event;
// make finger disappear
$('#finger').hide(0);
// get element at point of click
starter = document.elementFromPoint(evt.clientX, evt.clientY);
// send click to element at finger point
$(starter).click();
// bring back the finger
$('#finger').show(0);
});
This is untested - but is based on a working script of mine, so should be along the right lines. Basically, you have to make the layer that is in the way disappear for a moment, so you can use the elementFromPoint method and then make it come back.
$('.selector').click(function(e){
evt = e || window.event;
// make finger disappear
$('.finger').css({display:'none'});
// get element at point of click
starter = document.elementFromPoint(evt.clientX, evt.clientY);
// send click to element at finger point
$(starter).click();
// bring back the finger
$('.finger').css({display:''});
});
You can do this
$(document).bind('mousedown mouseup', function() {
$('.finger').toggle();
});
Check working example at http://jsfiddle.net/2cSj4/2/
I have a setup where I have a grid of elements and when I rollover each element a popup appears like an advanced tooltip. I first check if the popup needs to follow the moused over elements mouse position, if so I use a mousemove event. I first stopObserving in case there was one set before, then I start observing. Do I really need to do this or is prototype smart enough to not to add duplicate events on the same element.
show:function(param){
if(this.isFollow){
$(param.target).stopObserving('mousemove', this.onMouseMove);
$(param.target).observe('mousemove', this.onMouseMove);
}
},
//param.target is the element that is being rolled over. I pass this in to my show method to then find its x and y position.
onMouseMove:function(event){
var xPos = Event.pointerX(event);
var yPos = Event.pointerY(event);
_self._popup.setStyle({left: xPos + 10 + "px", top:yPos + 10 + "px"});
}
Second question. When I move my mouse across the elements really fast my popup that is following the mouse sometimes lags and the mouse goes over the popup obstructing the mouseover event on the element below it.
I presume this is the nature of the mousemove as its not rendering fast enough. Should I be using setTimeout or something like that instead of mousemove, to prevent this lag.
1) No, Prototype won't set the same event handler twice. It'll only happen if you declare your handler function in-line (i.e. element.observe('click', function(){…})) since the handler will be sent a newly created function each time, and never the exact same instance of a function.
But in your case, where you're referring to the onMouseMove function, Prototype will check whether that particular function is already registered for that particular event, on that particular element. And if it is, it won't be registered again.
2) You can't avoid the lag on fast mouse movements, no. The browser won't send the mousemove events fast enough. You could use a timer, but I'd probably try registering a single mousemove handler for the parent element of all the grid-elements (or maybe even document itself), and use the X/Y coordinates to figure out which grid-element to show the tooltip for. Then you don't have to bother with setting event handlers for each element. I.e. if the grid was a standard table, I'd listen for events on the <table> element itself, rather than on each and every <td>. Especially if you still want to implement a timer, I should think, it'd be easier to deal with everything in one place (otherwise, a timer might accidentally execute on some element you've already moused out of, and your tooltip will flicker back and forth or something. If you only want 1 tooltip at a time, it's easier to manage it in 1 place.)
I have a link which has mousedown and mouseup handlers to animate some objects on page.
When dragged (drag and drop) link fires mousedown event but it doesn't fire mouseup when released. is there a workaround for this problem?
Here is a example, if you click link normally it works but when you drag the link mouse up doesn't happen:
http://jsfiddle.net/hL3mg/1/
Handling drags
Something crucial nobody mentions here is that there actually is an event to register the end of a drag, which as explained by the other answers is what's happening here. The event is called dragend, so you can simply do
$("a").on("dragend",function(){
console.log("Drag End");
});
To register the end of the drag. The disadvantage of this is that you will still see a drag interface (in other words: the browser will show some UI to notify the user he's draggin).
Registering mouse up's
Note from 2020: This isn't a good answer, but I am not familiar anymore with jQuery, so can't update it well. I would guess that event.preventDefault() on the dragstart might or might not be relevant.
There is however also a way to register the sought after mouse ups, simply cancel the drag behaviour by returning false in the click event listener, and then register the mouseup on the document.
$("a").mousedown(function(){
console.log("Mouse Down");
return false;
});
$(document).mouseup(function(){
console.log("Mouse Up");
});
The only remark that I do feel like I have to make is that in a stand alone jsfiddle this worked perfectly, in my own code it did not, so I am listening for both the mouseup and the dragend just to be sure.
What I did to solve this is associate an "mouseOut" event to every link and check if any link has been pressed. If it did, the mouseOut would fix the positioning of the link. Here's the code:
var mouse_button = false;
$('a')
.mousedown(function(){
$(this).css('top', '+=2');
mouse_button = true;
})
.mouseup(function(){
$(this).css('top', '-=2');
mouse_button = false;
})
.mouseout(function(){
if (mouse_button) {
$(this).css('top', '-=2');
mouse_button = false;
}
});
It seems that the mouseup event won't be fired because your mouse has left the link when you release the left button.
From http://www.quirksmode.org/js/events_mouse.html :
Suppose the user depresses the mouse
button on a link, then moves his mouse
off the link and then releases the
mouse button. Now the link only
registers a mousedown event.
Maybe you can do this to walkaround:
register mousedown event for a link
register mouseup event for the whole document
when the link fire mousedown event , then the document fire mouseup event, you can think that link is firing mouseup event
What you described is by conscious design.
It has always been the intent that if you mouse down on a link, a button, whatever and change your mind before you've mouse up, you can move the cursor off the link or button and then release the mouse button and the action - the link, button, whatever - will not occur.
It is by design that the mouse up is not sent to the object which received the mouse down if the cursor is moved off the item before mouse up.
This is a user interface design consideration. This is why you should program such that it takes a click to initiate just about any action - not just a mouse down.
I grant you that there may be times where you want to take action on a mouse down, such as in dragging, but it is the exception and when done properly, the mouse up will be seen - except in some versions of IE when the mouse up will be lost if you drag the cursor off the page - to the top, left or right.
If you want to move things around and be able to see the mouse up, it is far better to use divisions or such than things like links.
Links are intended to be just that: link to something. Yes, you can code JavaScript to be executed when the link is clicked - href="javascript:someFunction();" or you can code onclick to execute something or even mouse up over down out. However, the link is intended to do something not to be dragged around.
Use a division or a span and move it around.
Bob
If you look closely at what the browser does, it "drags" the DOM object, in my case a link, upon release the mouseup event does not fire for the DOM object (underneath the mouse, when dragged) or the document (it doesn't seem to bubble).
adding draggable="false" attr helps ...
link
however, there is still an issue of the user highlighting/selecting something with their cursor and dragging the selected element(s).
Using the mouseout event also helps.
If you need to handle dragging in jQuery why not use Draggable?
I have an image that I want to have trigger certain behaviors when the mouse is over, I have a mouseover and mouseout method, but if you happen to have your mouse over the image when the page loads, the mouseover method never fires until you leave the image and come back over it.
Is there a way to detect if the mouse is over an element on the fly without the mouse having to be off of the element and then come over the element to trigger the JS mouseover event? Like is there a document.getElementById("blah").mouseIsOver() type function in Javascript?
I believe this is possible without any action from the user. When your page loads, bind the mouseover event to your image and hide your image (i.e. using CSS display:none). Use setTimeout() to show it again in a few milliseconds (10 should be enough). The even should be fired.
If you don't want to cause the 'flick' effect on your image, you may try using some temporary element instead, attaching event to it, and delegating the event onto your image.
I have no idea if this is cross-browser solution, but it worked from my Firefox 3.0 console ;)
You could use the mousemove event. That would trigger anytime the user moves a mouse; so the only instance of the trigger not firing would be if the user does not move the mouse at all, which should be rare.
The only problem with this is that the event would fire anytime the mouse would move over your image, so you would get a LOT of those events while over the component. What you would probably need to do is implement some sort of flag within your method when the event fires. You turn on the flag when the event first fires, and you turn it off when you leave the component.
This is less than ideal, but I think this will probably satisfy your problem scenario. The following is some quick pseudo code on what that solution might look like, I think it should work.
<img src="blah.png" onmousemove="JavaScript:triggerOn(event)" onmouseout="JavaScript:triggerOff(event)"/>
...
<script type='text/javascript'>
var TriggerActive = false;
function triggerOn(e){
e = e||window.e;
if( !TriggerActive){
TriggerActive = true;
// Do something
} else {
// Trigger already fired, ignore this event.
}
}
function triggerOff(e){
e = e||window.e;
if(TriggerActive)
TriggerActive = false;
}
</script>
You can find some great mouse event information including browser compatibility notes here.
Use document.querySelectpor and onload/onready events.
var a = document.querySelector('#a:hover');
if (a) {
// Mouse cursor is above a
}
else {
// Mouse cursor is outside a
}
There is no way to get the mouse coordinates aside from listening for mouse events, namely mousemove, mouseover etc. However, these events are very sensitive in the sense that moving the cursor by just one pixel is enough to trigger them, so having the cursor hover over your image while perfectly still should be somewhat unusual.