On click event not firing on moving target - javascript

I am coding a javascript game, with a moving ball.
I want an alert message when the user manage to click on the moving ball.
It is working right now, but the event is not firing every times... It look likes the ball is moving too fast for the js engine to be able to notice that the ball was indeed clicked.
I am testing on Firefox 18, windows 7 on a 5 years old cpu...
Here are some bits of my code :
myBall = document.getElementById("myBall");
function move(){
myLeft += 20;
myBall.style.left = myLeft + "px";
}
myTimer = window.setInterval(move, 10);
...
myBall.addEventListener("click", function(){alert("win")});
Is there any way to set a click event listener on a small moving target, that will behave more accurately ? Would jQuery make any difference here ?
Thanks.

All right, to solve the problem you're having, you'll need to add event listener for mousedown instead of click.
It is because click requires mouse button to go both down and up, and – as #techfoobar noted – it must be done at the same place on the target element (if coords of mousedown and mouseup are not equal, the click event won't be fired). The ball simply moves too fast to meet the aforementioned condition, hence the problem.

Related

HTML5 Canvas key event blocks mouse event

I have this little code. It's the beginnig of a drawing app: https://jsfiddle.net/t2xycjcd/1/ (building on code by www.williammalone.com)
This is the key listener:
canvas.onkeypress = function (e) {
e.preventDefault();
var letter = String.fromCharCode(e.keyCode);
if (keyMap[letter]) {
settings[keyMap[letter].param] = keyMap[letter].value;
refreshToolStatusDisplay();
redraw();
}
}
This is the mouse listener (nothing fancy):
canvas.onmousedown = function(e)
{
console.log("mousedown");
clickX = offsetX(e, canvas);
...
I am getting crazy about mouse events not correctly firing when happening short time (or immediately) after a key event.
How to reproduce:
use the line tool to draw a line
press the "p" key to select "player" tool
now without pausing and without moving the mouse -> click
The mousedown event will not fire.
It will however if you either wait about one second before step three, or move the mouse or click one more time.
This is kind of catastrophic for my purpose.
I have tried various things but none worked:
Resetting the focus to the canvas element after the key event -> not the problem, the canvas still has the focus
Firing a custom mouse event after the key event through a MouseEvent.initMouseEvent() -> not working
Other crazy stuff not worth mentioning
This seems to be typical behaviour of canvas elements. This is a
similar but unrelated fiddle of a canvas element with a mouse listener: http://jsfiddle.net/4Lanc/ -> Same behaviour there: clicking shortly after a key press will prevent the click from happening.
Anybody have an idea?

Triggering mousemove on the mouse's current position

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/

Duplicate events in prototype

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.)

How does the triggering of mousemove work in Javascript?

I have an object that prints the mouse's x and y positions on every mousemove.
It's something like this:
$('#canvas').mousemove(function(e){
$('#output').prepend(e.pageX + ',' + e.pageY);
});
I've noticed that when you move over the object really fast it only prints out a few positions.
I'm not exactly unhappy that it does that (because it would be quite exhaustive to have it do something for all the hundreds of pixels you've crossed) but I am wondering how this works.
Is the mousemove event limited to a certain amount of triggers per second or what?
(Btw: this was tested on Chromium in Ubuntu Linux)
"Mice only report their position to the operating system n times per second, and I think n is usually less than 100"
You may want to look at this, as this may be browser dependent,
http://javascript.info/tutorial/mouse-events#mousemove-and-mouseover-frequency, but, if you look at this question, there is a suggestion on how to get better response.
How to set mousemove update speed?
i think it's synchronous. It's doesn't get triggered for every pixel in which you move your mouse, which means that the events are not queued up .
Say if you have some some code like this.
$('#canvas').mousemove(function(e){
//Some code which takes seconds to execute
//All subsequent events won't be dispatched while this event handler is executing.
});
Say if you move mouse while the mouse move event handlers execute. The mousemove handler won't be triggered.
Here is a example for handler which will take seconds to execute. --> http://jsfiddle.net/78Hf3/1/
And one that take only few time --> http://jsfiddle.net/78Hf3/2/

Detect if mouse is over an element when page loads with Javascript

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.

Categories

Resources