d3 drag fires event even when dx and dy is 0 - javascript

when i try to create a new d3.drag() function and bind it afterwards to my selection the "drag" event fires even when i didn't move the mouse (dx and dy = 0) on click.
I wan't to call a click handler when there was no "drag".
var drag = d3.drag()
.on('start', dragStart)
.on('drag', dragging)
.on('end', dragEnd);
viewPort.on('click', function () {
clicked = true;
})
.call(drag);
I expect that clicked = true and "drag" doesn't fire when i don't move the mouse on click. Now clicked is true but "drag" is also fired.

Elabourating on my comment a little more: a mousedown event will fire the dragstart event in d3.js, so you can't really prevent the callback from being invoked. That, by definition, means that dragstart always fires before the click event is registered, and that's why you cannot prevent dragstart from firing in the event handler invoked bu click. The chain of event that happens when you click and release an element:
The mousedown event is fired: this triggers dragstart event in d3.js
The mouseup event is fired: this triggers the dragend event in d3.js
The click event is fired
click fires after both the mousedown and mouseup events have fired, in that order.
Source: see MDN docs on mouse-related events
This also means that the dragstart event will always fire, even when there is no cursor/pointer/mouse movement, because at that point in time, the browser has no idea whether any movement has detected, when the mousedown event is triggered.
What you can do, however, is to set up some kind of guard clause that simply does not allow further execution of logic in the callback should the dx and dy of the event register as zero.

Related

How to manage asynchronous mouse events in Javascript

I have JavaScript code where:
When the user presses the left mouse button, a mousedown event is fired, which triggers a call to function OnMouseDown.
When the user releases the left mouse button, a mouseup event is fired, which triggers a call to function OnMouseUp.
The two events are fired asynchronously.
For example, the mouseup event can be fired immediately after the mousedown event is fired (short mouse click), before the OnMouseDown ends. (Figure1)
I want to process the events sequentially, where the function OnMouseUp will only start after OnMouseDown ends.
I can achieve this by preventing the mouseup event from firing until after OnMouseDown ends (by calling removeEventListener('mouseup', OnMouseUp) when OnMouseDown begins) (Figure2)
But then I may lose a mouseup event altogether (Figure3)
Figure3 - mouseup event is lost
I am looking for a way to insure that
a mouseup event after a mousedown event is not lost, and
the OnMouseUp function begins after OnMouseDown ends.
How can I achieve this?
The following code example demonstrates the problem:
function sleep1 () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("Finished sleeping");
}, 2000);
});
}
// The mousedown event is fired when a pointing device button (usually a mouse button) is pressed on an element.
document.addEventListener('mousedown', async function(e) {
console.log('BEG OnMouseDown');
let retval = await sleep1();
console.log('retval: ', retval);
console.log('END OnMouseDown');
});
// The mouseup event is fired when a pointing device button (usually a mouse button) is released over an element.
document.addEventListener('mouseup', function(e) {
console.log('BEG OnMouseUp');
console.log('END OnMouseUp');
});
Clicking on the left mouse button and releasing results in the following printout, which shows that the function OnMouseUp ends before the function OnMouseDown ends, which fits figure1.
BEG OnMouseDown
BEG OnMouseUp
END OnMouseUp
Inside OnMouseDown: Finished sleeping
END OnMouseDown
You can try async await,
Define an async function then use await keyword on the mouswdown event, it will not fire the next event untill the the async function is done
What i'm understanding is that you want to record events in the sequence they have fired.
Please check this solution:
// The mousedown event is fired when a pointing device button (usually a mouse button) is pressed on an element.
var ismousedown = false;
document.addEventListener('mousedown', function(e) {
e.preventDefault();
ismousedown = true;
console.log('BEG OnMouseDown');
});
// The mouseup event is fired when a pointing device button (usually a mouse button) is released over an element.
document.addEventListener('mouseup', function(e) {
e.preventDefault();
if(ismousedown){
ismousedown = false;
console.log('BEG OnMouseUp');
}
});
Is this what you're looking for? There is something else i have missed?
I solved the problem by:
implementing a sleep based on here
introducing a flag onMouseDownStillProcessing that is set to false/true at the beginning/end of OnMouseDown, respectively.
waiting in the beginnning of OnMouseUp for onMouseDownStillProcessing to become true.

How is possible to get cursor position and cursor events outside and cross origin iframe?

I am working on a video player. This player is used inside an iframe on the client's page, so it is cross-origin. When the user clicks on seekbar and drags the cursor out of iframe, I can't identify the mouseup event, so it keeps selected. I notice that youtube player can do it, and can identify cursor events outside iframe. How can i do it using javascript?
One thing to consider is that the mouseup event only fires if the pointer is directly over the element with the eventListener. It doesn't keep track of what element the mousedown event fired on, it only knows about the state of the mouse at the time of the mouseup.
The mouseup event is fired at an Element when a button on a pointing
device (such as a mouse or trackpad) is released while the pointer is
located inside it.
https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseup_event
Therefore you need some other method of tracking if your user has initiated the drag on your seekbar playhead.
A possible solution is to use a boolean variable. Then to listen to mouseup on document and check the value of that variable.
let scrubbingTimeline = false;
document.querySelector('button').addEventListener('mousedown', ()=> {
console.log('Mouse down')
scrubbingTimeline = true
})
document.addEventListener('mouseup', ()=> {
if(scrubbingTimeline === true) {
console.log('Mouse has been released')
scrubbingTimeline = false
}
})
Another possible solution would be to initiate the mouseup listener only once the mousedown callback has fired. Then to stop listening after one event. Like this:
function mouseUpHandler() {
console.log("Mouse Lifted")
document.removeEventListener('mouseup', mouseUpHandler)
}
document.querySelector('button').addEventListener('mousedown', ()=> {
console.log('Down')
document.addEventListener('mouseup', mouseUpHandler)
})
Important: This code is for the inner document. I.E. the one that will be the iframe.

How can i simulate drag event using mouse events(mousedown, mousemove events) in JavaScript

How can i simulate drag event using mouse events(mousedown, mousemove events) in JavaScript. i want to create drag event programatically, triggering mouse events.
The DragEvent interface is a DOM event that represents a drag and drop interaction.
This interface inherits properties from MouseEvent and Event
(You can read more here).
whereas mouseEvents is fired when a pointing device (usually a mouse) is moved over the element that has the listener attached.
You can read more here
// add mousedown handler
document.addEventListener('mousedown', handleMousedown);
function handleMousedown() {
// on mousedown add listeners
document.addEventListener('mouseup', handleMouseup);
document.addEventListener('mousemove', handleMousemove);
}
function handleMousemove(event) {
// let's make some magic
}
function handleMouseup() {
// on mouseup remove listeners
document.removeEventListener('mouseup', handleMouseup);
document.removeEventListener('mousemove', handleMousemove);
}
jsfiddle example

How to prevent click event for mouseup event

There is a rect on mousedown mouseup click event . but when I click the rect mouseup Event dosen`t trigger https://jsfiddle.net/f0vbc94s/
there is my code:
var rect=d3.select(".text").append("rect")
.attr("width",1000).attr("height",1000)
.style("fill","#00ff00");
rect.on("click",function(){
d3.event.preventDefault
d3.select(this).style("fill","#000000")
})
.on("mousedown",function(){
d3.select(this).style("fill","#ff0000")
}).on("mouseup",function(){
d3.event.preventDefault;
d3.select(this).style("fill","#00ff00")
})
Your click event is overwriting the mouseup event. When you click
and hold the mouse at down position, mousedown event fires and
changed the color. When you release the mouse, mouseup event fired,
changed the color and then click event fired immediately and changed
the color. So you couldn't recognise it.
If you comment the click event, you can see the mouseup event fired.
Try this,
var rect=d3.select(".text").append("rect")
.attr("width",1000).attr("height",1000)
.style("fill","#00ff00");
//rect.on("click",function(){
//d3.event.preventDefault
//d3.select(this).style("fill","#000000")
//})
rect.on("mousedown",function(){
d3.select(this).style("fill","#ff0000")
}).on("mouseup",function(){
d3.event.preventDefault;
d3.select(this).style("fill","#00ff00")
})

Losing MouseUp event if releasing not over the same element

I have got a problem with a slider. When i grab the handler, i change the .src of the image, just to change its color. However, i want it to change back to the original color when i release the mouse button. I have tried two things.
1) Changing it back on the handler mouseup event: this works only if i release the button over the handler, so this is not a solution.
2)Changin it back on the window mouseup event: the event is not firing properly. If i click and release on any place of the window, the event fires normaly, but if i click in the handler, move the cursor to any other point of the window, and then release the button, the event will not fire.
Btw, im using the prototype js framework.
Solutions? Thanks
Here is the code. I load the handler function when the document is ready.
function handler()
{
var handler = $('handler');
Event.observe(window, "mouseup", function(){
alert('salta'); //to see when mouseup fires
if(handler.src=='http://localhost/moodle/blocks/videoavatar/eggface/trunk/gripper_o.png'){ //orange
handler.src='http://localhost/moodle/blocks/videoavatar/eggface/trunk/gripper.png';} //grey
});
Event.observe(handler,'mousedown',function(){handler.src='http://localhost/moodle/blocks/videoavatar/eggface/trunk/gripper_o.png';}); //orange
}
You should be attaching the mouseup handler to the document object.
How about onmouseout event?
Here is the code. I load the handler function when the document is ready.
function handler()
{
var handler = $('handler');
Event.observe(window, "mouseup", function(){
alert('salta'); //to see when mouseup fires
if(handler.src=='http://localhost/moodle/blocks/videoavatar/eggface/trunk/gripper_o.png'){ //orange
handler.src='http://localhost/moodle/blocks/videoavatar/eggface/trunk/gripper.png';} //grey
});
Event.observe(handler,'mousedown',function(){handler.src='http://localhost/moodle/blocks/videoavatar/eggface/trunk/gripper_o.png';}); //orange
}

Categories

Resources