Multiple onmouseout events in IE when returning false to the onDrag event.

T

Tom

Hi,

In the following code I have reproduced a problem in IE that is
extremely annoying for my application.

<html>
<head>
<script type="text/javascript">


function mouseover(id){
document.getElementById("debugmessages").innerHTML += "MouseOver
"+id+"<br>\n"
}

function mouseout(id){
document.getElementById("debugmessages").innerHTML += "MouseOut
"+id+"<br>\n"
}
</script>
</head>
<body>
<img onDrag="return false" onmouseover="mouseover('1')"
onmouseout="mouseout('1')"
style="position:absolute;left:10;top:10;height:50;width:50;" src="">
<img onDrag="return false" onmouseover="mouseover('2')"
onmouseout="mouseout('2')"
style="position:absolute;left:60;top:10;height:50;width:50;" src="">

<div style="position:absolute;top:70;">
<div
onclick="document.getElementById('debugmessages').innerHTML=''">Clear
Messages</div>
<div id="debugmessages"></div>
</div>
</body>
</html>

To reproduce the problem, move the cursor to as fas as you can to the
right within the leftmost image placeholder. Then hold down the left
mouse button and move the mouse to the right image placeholder (I did
not load actual images as its not needed to demonstrate the problem).
Looking at the events listed below the placeholders, you can see that
cell 1 is getting an extra onmouseover event AFTER the onmouseout event
has been handled. Additionally, when this behaviour is displayed, cell
2 does not get an onmouseover event.

I think this is something to do with when the onDrag event is being
fired. If you repeat the above but depress the left mouse button while
the mouse is in the middle of the image and then move to the other
image, all is OK. The problem only seems to occur if the distance moved
with the button down, before leaving the cell, is less than the
distance that is needed for onDrag events to be fired. So in the above
example, the onDrag event is fired (and is handled, possibly
incorrectly, by me) after the cursor has left the cell - I believe this
to be causing confusion somewhere.

Any ideas?

Thanks,

Tom...
 
R

RobG

Tom said:
Hi,

In the following code I have reproduced a problem in IE that is
extremely annoying for my application.

<html>
<head>
<script type="text/javascript">


function mouseover(id){
document.getElementById("debugmessages").innerHTML += "MouseOver
"+id+"<br>\n"

Manually wrap your code at about 70 characters - allowing auto wrapping
nearly always introduces errors.

document.getElementById("debugmessages").innerHTML +=
"MouseOver " + id + "<br>\n";

Terminating statements with a semi-colon is not strictly always
necessary, but good practice anyway.

}

function mouseout(id){
document.getElementById("debugmessages").innerHTML += "MouseOut
"+id+"<br>\n"
}
</script>
</head>
<body>
<img onDrag="return false" onmouseover="mouseover('1')"
onmouseout="mouseout('1')"
style="position:absolute;left:10;top:10;height:50;width:50;" src="">

CSS lengths must have a unit - say 'px' for this example:

style="position:absolute;left:10px;top:10px;height:50px;width:50px;"


Leaving off the units causes unpredictable results - browsers may try to
error correct in quirks mode by guessing - in strict mode they won't,
the lengths are ignored.


[...]
To reproduce the problem, move the cursor to as fas as you can to the
right within the leftmost image placeholder. Then hold down the left
mouse button and move the mouse to the right image placeholder (I did
not load actual images as its not needed to demonstrate the problem).
Looking at the events listed below the placeholders, you can see that
cell 1 is getting an extra onmouseover event AFTER the onmouseout event
has been handled. Additionally, when this behaviour is displayed, cell
2 does not get an onmouseover event.

I think this is something to do with when the onDrag event is being
fired. If you repeat the above but depress the left mouse button while
the mouse is in the middle of the image and then move to the other
image, all is OK. The problem only seems to occur if the distance moved
with the button down, before leaving the cell, is less than the
distance that is needed for onDrag events to be fired. So in the above
example, the onDrag event is fired (and is handled, possibly
incorrectly, by me) after the cursor has left the cell - I believe this
to be causing confusion somewhere.

Any ideas?

I don't think there is a solution. The ondrag handler you have doesn't
seem to do anything useful.

You could start messing with ondragstart/end/drop but you'd likely end
up chasing your tail - and handling multiple browser issues. If it's
causing you a specific problem, then post that and a solution may emerge.
 
T

Thomas 'PointedEars' Lahn

RobG said:
document.getElementById("debugmessages").innerHTML +=
"MouseOver " + id + "<br>\n";

One should never combine getElement* and innerHTML without proper
feature test. They are part of different object models.


PointedEars
 
T

Tom

I'm sorry the code was wrapping, my bad. The rest of the stuff was just
typo's and makes no difference to the effect I am seeing. I knocked
that test case up quickly just to demonstrate the problem I was having
in my main app. Its easier to just see the code that is causing
problems rather than having to trawl through my whole app :)

So here it is again, manually wrapped, semicolon'ed and px'ed. Still
the same behaviour is present in IE. I am not concerned with the other
browsers for the moment as they do not demonstrate this problem.

<html>
<head>
<script type="text/javascript">

function mouseover(id){
document.getElementById("debugmessages").innerHTML +=
"MouseOver"+id+"<br>\n";
}

function mouseout(id){
document.getElementById("debugmessages").innerHTML +=
"MouseOut"+id+"<br>\n";
}

</script>
</head>
<body>
<img onDrag="return false" onmouseover="mouseover('1')"
onmouseout="mouseout('1')"
style="position:absolute;left:10px;top:10px;
height:50px;width:50px;" src="">
<img onDrag="return false" onmouseover="mouseover('2')"
onmouseout="mouseout('2')"
style="position:absolute;left:60px;top:10px;
height:50px;width:50px;" src="">

<div style="position:absolute;top:70;">
<div onclick="document.getElementById('debugmessages').
innerHTML=''">
Clear Messages
</div>
<div id="debugmessages">
</div>
</div>
</body>
</html>

You mention my onDrag handler doesn't do much. This was the method I
had seen elsewhere to stop IE displaying the "no-drop" icon when you
try to drag something. If you know of a better way to do this then I am
all ears but this is all I could find. I tried doing the same with
ondragstart but this made no difference.

This is my specific problem and I am posting it :)

Thanks for your feedback

Tom...
 
R

RobG

Tom said:
I'm sorry the code was wrapping, my bad. The rest of the stuff was just
typo's and makes no difference to the effect I am seeing. I knocked
that test case up quickly just to demonstrate the problem I was having
in my main app. Its easier to just see the code that is causing
problems rather than having to trawl through my whole app :)

Thanks, your test case is fine for displaying the effect.

I can't believe I've found a fix... but first you must suffer the
explaination and there is a caveat (of course).

When you drag out of an element, IE fires the mouseover of the element
you are leaving not the one you are entering. You can check by
comparing the id of the element that fires the event to window.event -
the mouseover is actually fired by the mouseover'd element, but IE
fires the onmouseover handler of the wrong element.

That is a straight out bug.

Here's a fix. Handle the mouseover/out event with a function. Pass
'this' to the function and compare it to window.event.srcElement. A
bit of feature detection will stop W3C event model browsers from
barfing on windw.event.

If the elements don't match, use window.event.srcElement instead of the
element passed by this (or maybe just always use it?). You need this
on both mouseover and mouseout events.

Don't decide to replace passing 'this' with srcElement - keep passing
this and manage IE's silly behaviour. It will be fixed eventually
(maybe?) and then you are back to normal.

And the caveat... if the event has bubbled up from some other element,
this 'fix' will attempt to fire the mouseover/out of the lower element
(that is, the one referenced by window.event.srcElement), not the one
with the onmouseover event.

In this case you're safe 'cos an img element can't have anything nested
inside it.

What I can't understand is why this hasn't been raised and fixed
before. Is this a new issue, or has no one discovered in the last 5
years that IE fires the wrong event in this circumstance?



Anyone????




[...]
height:50px;width:50px;" src="">

<div style="position:absolute;top:70;">
---------------------------------------^

Hey, still a missing px! ;-)


[...]
You mention my onDrag handler doesn't do much. This was the method I
had seen elsewhere to stop IE displaying the "no-drop" icon when you
try to drag something.

OK, but I meant in regard to preventing the aberrant behaviour.

If you know of a better way to do this then I am
all ears but this is all I could find.

The answer is don't to it at all. Why only prevent it on two images?
Modifying the standard interface makes you responsible for any
subsequent issues - and after all, you don't want users trying to drag
the images anyway.

If you don't prevent the "no-drop" icon at least when (if?) the strange
behaviour is detected you can piously claim "But the icon is saying
don't do that...". :)

You can use ondrag="return false;" on the body element to apply is
document-wide, but I'm not recommending it.
I tried doing the same with
ondragstart but this made no difference.

This is my specific problem and I am posting it :)

What I meant was what is the functionality that you are trying to
deliver with the mouseover/out stuff. There may be another way of
doing it that isn't affected by the same issue.


Here's a 'fixed' (?) example:


<script type="text/javascript">

function mouseover(el){
if (window.event) {
el = window.event.srcElement;
}
document.getElementById("xx").innerHTML +=
'<br>Over ' + el.id;
}

function mouseout(el){
if (window.event) {
el = window.event.srcElement;
}
document.getElementById("xx").innerHTML +=
'<br><b>Out</b> ' + el.id;
}

</script>

<img id="img_1" onDrag="return false"
onmouseover="mouseover(this)"
onmouseout="mouseout(this)"
style="position:absolute;left:10px;top:10px;
height:50px;width:50px;" src="a.jpg">
<img id="img_2" onDrag="return false"
onmouseover="mouseover(this)"
onmouseout="mouseout(this)"
style="position:absolute;left:60px;top:10px;
height:50px;width:50px;" src="a.jpg">

<div style="position:absolute;top:70px;">
<div onclick="document.getElementById('xx').
innerHTML=''">
Clear Messages
</div>
<div id="xx">
</div>
</div>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,740
Latest member
JudsonFrie

Latest Threads

Top