HTML5 Canvas key event blocks mouse event - javascript

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?

Related

Getting mouse coordinates in SDK first-time right-click

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

Propagate click event to underlaying element [duplicate]

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/

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/

JavaScript mouseUp event ignored when mouse is released during drag

I have a <div> element that is created in my script and appended to another <div>. I have:
coverElm.onmousedown = mouseDownEventHandeler;
document.onmouseup = mouseUpEventHandeler;
document.onmousemove = mouseMoveEventHandeler;
I have the functions defined and work great and keep track of if the mouse is down with a boolean mouseDown.
The Problem - When the mouse is pressed down and is released the document.onmouseup is never handled. I think its because its doing a drag of whatever is in the <div> witch is just a few words of text. I have this issue without text too.
So what I'm looking for is a way to prevent this odd dragging behavior, or way for onmousedrag to see if the mouse is pressed down of not - NOT USING THE MOUSE UP AND MOUSE DOWN METHODS
Here are my functions:
function mouseUpEventHandeler(e) {
mouseDown = false;
}
function mouseDownEventHandeler(e) {
mouseDown = true;
}
function mouseMoveEventHandeler(e) {
if (mouseDown) {
coverElm.innerHTML ="<p>Mouse down and dragging</p>";
}
}
90% of the time, this is because the dragged element is in front of the element with the mouseup event listener, so the parent element underneath never gets the event.
Usually, this can be fixed by using addEventListener as opposed to the inline form of the event. Another way to fix this is to give the dragged element an eventListener for when the mouse is released. Also, you can have a div that is put in front of all other elements whenever an element starts to drag (via the zIndex property).
Edit: I whipped up some proof-of-concept code:
http://jsfiddle.net/2BkEM/5/
$j(divID).bind('dragstart', function (event) { event.preventDefault() });
Thanks all

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