With "draggable" domNoes, the 'drag' event doesn't seem to contain any mouse information at all (like offsetX and offsetY) like it does in chrome. How can I get this information while dragging?
I've tried setting a 'mousemove' event handler on the document, but it seems like that isn't fired when something is being dragged. Same seems to be true in chrome. What a drag..
I'm using Firefox 30.
drag events are used on the elements that are being dragged. dragover can be used on other elements that stay stationary such that something is dragged over them. If you ask for clientX or clientY on drag events, you will get zeros. If you drag that element over an element with dragover, and ask that event for coordinates, you will get x and y relative to the dragover listening element.
Easiest example to see it in action is to apply dragover to the document object, then drag something over it and print the x and y.
Update
Sorry for the delayed response, I've been very busy. If you have the mousemove event attached to the actual document rather than the element, then it should still fire. For example:
document.addEventListener("mousemove", moveHandler, true);
Notice that I set the boolean at the end to "true"; this means that the event fires in the capture phase. It should update the coordinates in your mouse move function as you're needing. As for getting the element being dragged, you can get that element reference from event.target in the drag handler, like this:
function dragHandler(e) {
var el = e.target; //this is the element being dragged
}
You can use this to ascertain the offset of the element that you're dragging:
var rectObject = element.getBoundingClientRect();
var top_offset = rectObject.top;
var left_offset = rectObject.left;
If you need mouse coordinates, you'll need to attach a mousemove event listener to the DOM and store the coordinates in a global variable so that you can access them in the drag listener.
Related
I can get mouse motion events in javascript using a simple function:
myElement.onmousemove(function(event){
// ...
});
but I think those events only fire when the cursor is hovering over the element. I know I can also do this for document and get all mouse motion events:
document.onmousemove(function(event){...});
However, this event doesn't have the "scope" of belonging to the div or button or whatever, and won't have an offset relative to the element I'm working with.
My workaround is to save a variable pointing at the focused div and reference it when getting all motion events, but I'd much rather get motion events and the onmousemove function set for the element itself. Is there a way for that element to continue receiving mouse move events even if the cursor leaves the boundary of the element?
In case it matters I can use jQuery but I would prefer a native solution.
no, it is not possible to get a mousemove event when the movement is outside of the attached element. As you stated correctly, you can track the movement on the document. When using that together with mouseenter and mouseleave events, you can set/unset a variable to indicate if the movements are happening on the element or not.
e.g.
var myElement = document.getElementById("special");
var isOverMyElement = false;
document.addEventListener('mousemove', function(e){
if (isOverMyElement){
console.log("mouse is within myelement at details", e);
}
})
myElement.addEventListener('mousenter', function(e){
isOverMyElement = true;
})
myElement.addEventListener('mousenter', function(e){
isOverMyElement = false;
})
If you are targeting older browsers, use jQuery as it normalizes mouseenter/leave over browsers. If you are targeting modern browsers, there is no need for jQuery
I have an Ember.js application with a view where I use mouse events (down, move and up) to allow the user to resize elements by clicking and dragging while holding.
Works like a charm - until the mouse pointer leaves the boundaries of the view. Then I don't have any indication what's going on with the mouse.
To understand what I want to achieve think of the edit view in Paint - you click and drag to create a rectangle. If you pass the view's top the rectangle's height stops changing but the width changes according to the mouse current location.
I'd like to keep getting updates of the mouse moves even if the target is now another view. How can I achieve it in a clean way - without modifying the rest of the views?
Ideally, what I'd like to do is run a code in mouseLeave that modifies the way Ember's global event listener delegates events - so that they'll be passed to my view even when it's not the target. Of course - I'll need to clear this when the mouse button is released.
Then typically you have to register the event handlers on document instead, and filter out the target to match your view.
Example using jQuery:
var mouseDown = false;
$(document).on("mousedown", function(e){
// If we target the view element, we can start capture events
var $target = $(e.target);
if ($target.closest("#yourViewElement").length !== 0 || $target.is("#yourViewElement")) {
mouseDown = true;
}
});
$(document).on("mouseup", function(e){
mouseDown = false;
});
$(document).on("mousemove", function(e){
// We initially clicked on the view, so we listen for the changes now
if (mouseDown) {
// Parse events here, e.pageX / e.pageY etc.
}
});
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
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/
As the touchend event is bind to the element where the touchstart is fired, how can I get the element at the position where the finger leaves, when this is outside of the element where the event was binded to.
You could use the document.elementFromPoint method, passing it the coordinates of the event:
$('#element').on("touchend",function(event){
var endTarget = document.elementFromPoint(
event.originalEvent.touches[0].pageX,
event.originalEvent.touches[0].pageY
);
});
EDIT:
Found some good article about getting elements at specific coordinates.
http://www.zehnet.de/2010/11/19/document-elementfrompoint-a-jquery-solution/