whats is the difference between a "target" a "relatedTarget" and a "fromelement" in terms of a mootools mouse event?
for example in the following code why is target not being used and why is there a || involved?
'mouseenter':function(e){
var reltar = e.relatedTarget || e.fromElement;
}
Basically,
The target is the element the event is dispatching on. i.e.
$('el').addEvent('mouseenter',function(event){
console.log(event.target) //target refers to the 'el' element.
}
The relatedTarget is the element the mouse came from in case of mouseover/enter.
fromelement is the MS way to implement what relatedTarget does. Therefore,
var reltar = e.relatedTarget || e.fromElement;
is a cross-browser way to detect what element the mouse came from.
W3C says that event.relatedTarget is the element where mouse comes from in a mouseover event, or the element that the mouse goes to in a mouseout event.
However, IE uses two separate properties for those two cases: event.fromElement is the element the mouse comes from in a mouseover event, while event.toElement is the element the mouse goes to in a mouseout event.
You can find more details and some examples on the following page by Peter-Paul Koch (very good content there):
http://www.quirksmode.org/js/events_mouse.html
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
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.
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/
As JQuery document says, I have converted many lines mouseover to mouseenter because it does not fire more than once.
http://api.jquery.com/mouseover/
mouseover fires when the pointer moves into the child element as well
mouseenter fires only when the pointer moves into the bound element.
Even hover event works as mouseenter and mouseleave, not as mouseover and mouseout.
It makes me wonder why there is mouseover event if mouseenter can do it all.
For me, mouseover gets fired unpredictably when you move mouse around on an element. It seems really dependent on the depth of child elements.
Is there a good use-case of mouseover and mouseout, which needs to fire multiple times?
That I know of, there is no use case for mouseover/mouseout at all. The only reason they exist is because these events are triggered by browsers because they are in the standard DOM event list. mouseenter and mouseleave are not standard events, but they are jQuery-specific constructs.
I suppose a use case would be if you wanted the event to trigger when moving the mouse over and out of the children of the element that the events are bound to. I can't think of anything specific, but at least this functionality is available. If only mouseenter/mouseleave existed, you wouldn't have a choice in the matter.
From http://code.jquery.com/jquery-1.9.1.js:
jQuery.each({
mouseenter: "mouseover",
mouseleave: "mouseout"
}, function( orig, fix ) {
/* content snipped */
Speculation: the reason why the creators of jQuery created the mouseenter and mouseleave non-standard events is because their behavior works as you would expect the mouseover/mouseout events to work (i.e. without regard for descendants).
Because the event contains coordinates of cursor.
So if you need to track mouse coordinates under the target, you have to use 'mouseover'
I have a div which onmouseover, displays a panel and onmouseout makes it disappear. JavaScript code is as follows:
function ShowPanel() {
document.getElementById("thePanel").style.display = "inline";
}
function HidePanel() {
document.getElementById("thePanel").style.display = "none";
}
The code works in Firefox and IE perfectly. The problem is Chrome. It works until the mouse is on the textbox in the panel. When the mouse goes on the textbox the onmouseout event is called even though the textbox is part of the panel and should remain open.
What you need is the behavior of the onmouseenter event instead of onmouseover and onmouseleave instead of onmouseout. The problem is that those events work only in IE (they actually got those ones right). You either need to simulate that behavior taking into account all of the differences in the event handling in different browsers, or just use a good JavaScript library that would take care of that for you. For example jQuery has .mouseenter() and .mouseleave() that are simulated on browser that don't support those events natively, and even a nice shortcut .hover() to set both at the same time.
I wouldn't recommend doing it manually unless you really know all of the quirks and inconsistencies of event models in different browsers (and you don't since you asked this question) but if you want to see how jQuery is doing it then see events.js and search for mouseenter and mouseleave.
In Chrome as you've found the mouseout event is fired whenever you move from the parent element (on which the handler is registered) and child elements contained within it.
The simple fix is to use jQuery, which will simulate mouseleave events (which don't suffer that problem) on browsers that don't support it.
Alternatively, in your mouseout handler, look at the toElement property of the event, and traverse its parent list and see if your original parent is in that list. Only process your action if it was not in the list.
document.getElementById('outer').addEventListener('mouseout', function(ev) {
var el = ev.toElement;
while (el && el !== document.body) {
if (el === this) {
console.log('mouseout ignored');
return; // enclosed - don't do anything
}
el = el.parentNode;
}
console.log('mouseout');
}, false);
demo at http://jsfiddle.net/raybellis/s4EQT/