Forum Moderators: open
In any case, I have an image that I want to track using JavaScript. Different parts of the image trigger different actions in the resultant submit (my implementation is a clickable map).
Firefox works GREAT! IE, on the other hand, really dislikes the code. The Mac version gives results that are about ten pixels off, but the Windows version goes bonkers. It seems to be an issue with getting an accurate measurement of the top, left corner of the <img, and then normalizing it for the mouse coordinates.
I have done a great deal of research on this, and have seen numerous examples, but I have yet to find one that actually works in this instance.
As you may be aware, a clickable map requires pinpoint accuracy. I can't afford the "slop" that IE introduces.
Does anyone have any suggestions?
Here is the code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Test</title>
</head>
<body>
<div id="encloser" style="width:100%; text-align:center">
<div id="centerer" style="width:150px;margin-left:auto;margin-right:auto">
This works just ducky in Mozilla/Firefox, but goes pear-shaped in IE.
<img src="target.gif" id="target_image" width="100" height="100" alt="target" />
<form id="reporter" method="get" action="#">
<div id="righter" style="text-align:right">
<br />
Image Offset X: <input type="text" id="x_offset" size="4" />
<br />
Image Offset Y: <input type="text" id="y_offset" size="4" />
<br />
Global X: <input type="text" id="x_pos_global" size="4" />
<br />
Global Y: <input type="text" id="y_pos_global" size="4" />
<br />
Local X: <input type="text" id="x_pos_local" size="4" />
<br />
Local Y: <input type="text" id="y_pos_local" size="4" />
<br />
</div>
</form>
</div>
</div>
<script type="text/javascript">
// <![CDATA[
var IE = document.all? true : false;
if (!IE) document.captureEvents(Event.MOUSEMOVE);
document.onmousemove = getMouseXY;function getMouseXY(e) {
var tempX = 0;
var tempY = 0;
var offset_x = findObjPosX ( document.getElementById ( 'target_image' ) );
var offset_y = findObjPosY ( document.getElementById ( 'target_image' ) );
if(!e ) {
if( window.event ) {
//DOM
e = window.event;
} else {
//TOTAL FAILURE, WE HAVE NO WAY OF REFERENCING THE EVENT
return;
}
}
if( typeof( e.pageX ) == 'number' ) {
//NS 4, NS 6+, Mozilla 0.9+
tempX = e.pageX;
tempY = e.pageY;
} else {
if( typeof( e.clientX ) == 'number' ) {
//IE, Opera, NS 6+, Mozilla 0.9+
//except that NS 6+ and Mozilla 0.9+ did pageX ...
tempX = e.clientX;
tempY = e.clientY;
if(!( ( window.navigator.userAgent.indexOf( 'Opera' ) + 1 ) ¦¦
( window.ScriptEngine && ScriptEngine().indexOf( 'InScript' ) + 1 ) ¦¦
window.navigator.vendor == 'KDE' ) ) {
if( document.body && ( document.body.scrollLeft ¦¦ document.body.scrollTop ) ) {
//IE 4, 5 & 6 (in non-standards compliant mode)
tempX += document.body.scrollLeft;
tempY += document.body.scrollTop;
} else if( document.documentElement &&
( document.documentElement.scrollLeft ¦¦ document.documentElement.scrollTop ) ) {
//IE 6 (in standards compliant mode)
tempX += document.documentElement.scrollLeft;
tempY += document.documentElement.scrollTop;
}
}
} else {
//TOTAL FAILURE, WE HAVE NO WAY OF OBTAINING THE
//MOUSE COORDINATES
return;
}
}
document.getElementById ( 'x_offset' ).value = offset_x;
document.getElementById ( 'y_offset' ).value = offset_y;
document.getElementById ( 'x_pos_global' ).value = tempX;
document.getElementById ( 'y_pos_global' ).value = tempY;
document.getElementById ( 'x_pos_local' ).value = ( tempX - offset_x );
document.getElementById ( 'y_pos_local' ).value = ( tempY - offset_y );
return true;
}
function findObjPosX(obj) {
var curleft = 0;
if (obj.offsetParent) {
while (obj.offsetParent) {
curleft += obj.offsetLeft
obj = obj.offsetParent;
}
}
else if (obj.x)
curleft += obj.x;
return curleft;
}
function findObjPosY(obj) {
var curtop = 0;
if (obj.offsetParent) {
while (obj.offsetParent) {
curtop += obj.offsetTop
obj = obj.offsetParent;
}
}
else if (obj.y)
curtop += obj.y;
return curtop;
}
// ]]>
</script>
</body>
</html>
Nothing is happening?
I did solve the problem with Flash, but I hate to rely on a plugin.
This seems to be a chronic issue. I keep hearing that there's no real answer, or people breathlessly announce that they have solved it, but it doesn't work.
I will keep looking at it.
Thanks for the bump.
How about using an imagemap, in which each section triggers a different server side piece of code?
I'll give that some thought, and see if server-side can buy me anything. We will still have the problem of accurate cursor position reporting, which can't be taken away from the client, and is the true problem. It seems to me that there is no real advantage to server-side. Client-side Javascript will work just as well.
The problem is that it is a continuous data source. There are no (or thousands) of separate combinations. This is an X-Y grid of longitude and latitude coordinates. There's no way that can be done with a map. It's a fairly basic set of linear calculations. The problem is getting the offset and cursor position to agree with each other.
I don't even need to get the accurate cursor position, as long as it is accurate in relation to the image.
It seems that I should have applied occam's razor to this problem. I took out all that crap that was in the cursor measurement, and let the DOM do its work.
This works:
function getMouseXY(e) {
if(!e ) {
if( window.event ) {
//DOM
e = window.event;
} else {
//TOTAL FAILURE, WE HAVE NO WAY OF REFERENCING THE EVENT
return;
}
}
var tempX = 0;
var tempY = 0;if( typeof( e.offsetX ) == 'number' ) {
var offset_x = e.offsetX;
var offset_y = e.offsetY;
} else if( typeof( e.clientX ) == 'number' ) {
var offset_x = e.clientX;
var offset_y = e.clientY;
}
document.getElementById ( 'x_offset' ).value = offset_x;
document.getElementById ( 'y_offset' ).value = offset_y;
return true;
}
It probably won't work in real old versions of NS, but I can't help that.