Wrong values from JS-Accessed DOM
I encountered a problem while tring to realize a kind of bar containing elements, that are able to slide in and out.
In order to check weather the mouse is inside one of the icons or the custom tooltip that pops up when lasting the cursor over one of them i calculated the absolute position of the elements kind like this:
(element.offsetParent) ? element.offsetTop+abstop(element.offsetParent) : element.offsetTop;
This works fine for 80 - 90 % of all icons. But some of them dont get the right position because the element.offsetTop-access gives me a value alternating to the one in the HTML-inspector of Chrome.
How can you explain this? Any fixes?
Thanks in advance! Max
You asked for code - so you'll get it! Dont say i didnt warned you.
<%
ArrayList<String[]> alArticlesToShow = logic.getArticlesToShow();
if(alArticlesToShow.size() > 1)
{
%>
<div style="padding-bottom:5px; padding-top:3px;">
<%@ include file="/include/new/rahmenBlauOben.jsp" %>
<div class="<%= FarbenVerlauf.blau.getRahmen() %>" style="padding-bottom:0px; padding-top:0px; height:43px">
<%
long time = System.currentTimeMillis();
String sCellWidth = "102px";
int iCellWidth = 102;
int iCurrentPos = logic.getNewArticleIndex();
// Offset berechnen
int iOffsetFactor = iCurrentPos - 4;
// if(iOffsetFactor < 0) iOffsetFactor = 0;
int iOffset = iOffsetFactor * iCellWidth;
int iFloaterSize = iCellWidth * alArticlesToShow.size();
int iTooltipSizeX = 400;
int iTooltipSizeY = 300;
String von_datum = null;
String bis_datum = null;
String von_zeit = null;
String bis_zeit = null;
if(logic.isTimeData("von_datum")) von_datum = logic.getTimeData("von_datum");
if(logic.isTimeData("bis_datum")) bis_datum = logic.getTimeData("bis_datum");
if(logic.isTimeData("von_zeit")) von_zeit = logic.getTimeData("von_zeit");
if(logic.isTimeData("bis_zeit")) bis_zeit = logic.getTimeData("bis_zeit");
String searchStationID = logic.getStationID();
%>
<script type="text/javascript">
//<!--
var iCellWidth = <%= iCellWidth %>;
var iFloatingSpeed = 2;
var fOffset = <%= iOffset %>.0;
var iOffsetFactor = <%= iOffsetFactor %>;
var iLoaded = <%= alArticlesToShow.size() %>
var iTooltipDelay = 1000
var iCellSizeX = 75;
var iCellSizeY = 40;
var iTooltipSizeX = <%= iTooltipSizeX %>;
var iTooltipSizeY = <%= iTooltipSizeY %>;
var iTooltipMoveFactor = 2;
var iTooltipScaleFactor = 4;
var iTooltipFadeFactor = 2;
var iShadowOffset = 30;
// Preisberechnung
var von_datum = '<%= von_datum %>';
var bis_datum = '<%= bis_datum %>';
var von_zeit = '<%= von_zeit %>';
var bis_zeit = '<%= bis_zeit %>';
var stationID = '<%= searchStationID %>';
//-->
</script>
<div style="float:left; width:20px; height:40px;">
<img src="/images/new/barButtonLinks.png" style="cursor:pointer" onclick="slideLeft()" />
</div>
<div style="overflow:hidden; width:95%; float:left; padding-left:5px;">
<div style="position:relative; width:<%= iFloaterSize %>px; margin-left:<%= -iOffset %>px;" id="main_floater">
<%
for(String[] article : alArticlesToShow)
{
if(alArticlesToShow.indexOf(article) == iCurrentPos)
{
%>
<%-- Der aktuell auf der Detailseite angezeigte Artikel --%>
<div style="float:left; width:<%= sCellWidth %>;">
<div style="border:2px solid #109EE3; width:75px; height:40px; margin-left:auto; margin-right:auto;">
<div style="margin-left:auto; margin-right:auto; width:40px; height:30px; padding-top:5px;" title="<%= article[2] %>">
<img src="<%= article[1] %>" />
</div>
</div>
</div>
<%
}
else
{
%>
<%-- Alle anderen Artikel --%>
<div style="float:left; width:<%= sCellWidth %>;">
<div onclick="location='<%= article[3] %>';"
onmouseover="mouseInElement('<%= article[0] %>_<%= article[4] %>');"
id="bar_<%= article[0] %>_<%= article[4] %>"
title="<%= article[2] %>"
style="border:1px solid #B3B3B3; cursor:pointer; width:75px; height:40px; margin-left:auto; margin-right:auto;">
<a href="<%= article[3] %>" style="height:40px;" onmouseover="mouseInElement('<%= article[0] %>_<%= article[4] %>');" >
<div onmouseover="mouseInElement('<%= article[0] %>_<%= article[4] %>');" style="margin-left:auto; margin-right:auto; width:40px; height:30px; padding-top:5px;">
<img src="<%= article[1] %>" onmouseover="mouseInElement('<%= article[0] %>_<%= article[4] %>');" />
</div>
</a>
</div>
</div>
<%
}
}
%>
</div>
</div>
<div style="float:right; width:20px; height:40px;">
<img src="/images/new/barButtonLinks.png" class="flippedImageH" style="cursor:pointer" onclick="slideRight()"/>
</div>
</div>
<%@ include file="/include/new/rahmenBlauUnten.jsp" %>
</div>
<div class="tooltip" id="tooltip">
<%@ include file="/include/new/detailpage/tooltipBlauOben.jsp" %>
<div class="tooltipMidBorders" style="height:<%= iTooltipSizeY -50 %>px; background-color:white;">
<div id="tooltipContent">
</div>
</div>
<%@ include file="/include/new/detailpage/tooltipBlauUnten.jsp" %>
</div>
<div class="tooltip_shadow" id="tooltip_shadow">
</div>
<% System.out.println("Zeit in ms: " + (System.currentTimeMillis() - time) + " : ArticleBar"); %>
<%
}
%>
This is the jsp-include that displays the bar. Sorry for the german comments, i didnt change them. Hope youll understand it either.
Now here comes the JS-File:
var fTime = 0.05;
var fOffsetAim = 0;
var iElementXPos = 0;
var iElementYPos = 0;
var mouseOverID = "";
var lockedElementID = "";
// Tooltip Bounds
var fTooltipPosX = 0.0;
var fTooltipPosXAim = 0.0;
var fTooltipPosY = 0.0;
var fTooltipPosYAim = 0.0;
var fTooltipSizeX = 0.0;
var fTooltipSizeXAim = 0.0;
var fTooltipSizeY = 0.0;
var fTooltipSizeYAim = 0.0;
var fTooltipOpacity = 0.0;
var fTooltipOpacityAim = 0.0;
var sTooltipDisplay = 'hidden';
var bTooltipVisible = false;
var XPosDone = false;
var YPosDone = false;
var XSizeDone = false;
var YSizeDone = false;
var OpacityDone = false;
var iLevelOfDetail = -1;
var sTooltipData = "";
function slideLeft()
{
iOffsetFactor--;
if(iOffsetFactor < -4)
iOffsetFactor = -4;
fOffsetAim = iOffsetFactor * iCellWidth;
move();
}
function slideRight()
{
iOffsetFactor++;
if(iOffsetFactor >= iLoaded - 5)
iOffsetFactor = iLoaded - 5;
fOffsetAim = iOffsetFactor * iCellWidth;
move();
}
function move()
{
var fDist = fOffsetAim - fOffset;
fOffset += fDist * fTime * iFloatingSpeed;
setOffset();
if(Math.abs(fDist) < 1)
{
fOffset = fOffsetAim;
}
else
{
window.setTimeout("move()", fTime);
}
}
function setOffset()
{
var floater = document.getElementById('main_floater');
floater.style.marginLeft = "" + -fOffset + "px" ;
}
function mouseInElement(articleID)
{
if(articleID != mouseOverID)
{
mouseOverID = articleID;
var element = document.getElementById("bar_" + articleID);
element.style.border = "2px solid #B0B0B0";
var rect = element.getBoundingClientRect();
iElementXPos = rect.left;
iElementYPos = rect.top;
var foo = 'stillMouseOver(\'' + articleID + '\')';
window.setTimeout(foo, iTooltipDelay)
}
}
function mouseOutElement(articleID)
{
iElementXPos = 0;
iElementYPos = 0;
var element = document.getElementById("bar_" + articleID);
element.style.border = "1px solid #B3B3B3";
mouseOverID = "";
window.setTimeout('stillMouseOut(\'' + articleID + '\')', iTooltipDelay)
}
function checkMouseOut()
{
if(mouseOverID.length != 0 || lockedElementID.length != 0)
{
if(isOut() && isOutTooltip())
{
if(mouseOverID.length != 0)
mouseOutElement(mouseOverID);
else if(lockedElementID.length != 0)
mouseOutElement(lockedElementID);
}
}
}
function isOut()
{
if(g_iMousePosX < iElementXPos - 5)
return true;
if(iElementXPos + iCellSizeX + 5 < g_iMousePosX)
return true;
if(g_iMousePosY < iElementYPos - 5)
return true;
if(iElementYPos + iCellSizeY + 5 < g_iMousePosY)
return true;
return false;
}
function isOutTooltip()
{
if(g_iMousePosX < fTooltipPosX - 5)
return true;
if(fTooltipPosX + fTooltipSizeX + 5 < g_iMousePosX)
return true;
if(g_iMousePosY < fTooltipPosY - 5)
return true;
if(fTooltipPosY + fTooltipSizeY + 40 < g_iMousePosY)
return true;
return false;
}
function getXPos(element)
{
return (element.offsetParent) ? element.offsetTop+abstop(element.offsetParent) : element.offsetTop;
/*
var x = element.offsetLeft;
if (!element.offsetParent) return x;
else return (x + getXPos(element.offsetParent));
*/
}
function getYPos (element)
{
return (element.offsetParent) ? element.offsetLeft+abstop(element.offsetParent) : element.offsetLeft;
/*
var y = element.offsetTop;
if (!element.offsetParent) return y;
else return (y + getYPos(element.offsetParent));
*/
}
function stillMouseOver(articleID)
{
if(articleID == mouseOverID)
{
if(bTooltipVisible)
{
if(LOD() < 4)
fTooltipPosXAim = iElementXPos + iCellSizeX/2 - iTooltipSizeX/2;
else
fTooltipPosX = fTooltipPosXAim = iElementXPos + iCellSizeX/2 - iTooltipSizeX/2;
XPosDone = false;
lockedElementID = articleID;
getArticleData(lockedElementID);
moveTooltip();
}
else
{
openTooltip(articleID);
}
}
}
function stillMouseOut(articleID)
{
if(bTooltipVisible)
{
if(isOut() && isOutTooltip())
{
closeTooltip();
}
}
}
function openTooltip(articleID)
{
lockedElementID = mouseOverID;
getArticleData(lockedElementID);
bTooltipVisible = true;
var tooltip = document.getElementById('tooltip');
var tooltip_shadow = document.getElementById('tooltip_shadow');
tooltip.style.display = 'block';
if(LOD() < 2)
tooltip_shadow.style.display = 'block';
fTooltipPosX = fTooltipPosXAim = iElementXPos + iCellSizeX/2 - iTooltipSizeX/2; // Set X-Position
if(LOD() < 4) // with animation
{
fTooltipPosY = iElementYPos + iCellSizeY + 50; // Y-Position
fTooltipPosYAim = iElementYPos + iCellSizeY + 10; // Y-Position Aim
fTooltipSizeX = fTooltipSizeXAim = iTooltipSizeX; // X-Size
fTooltipSizeY = 0; // Y-Size
fTooltipSizeYAim = iTooltipSizeY; // Y-Size Aim
}
else // without animation
{
fTooltipPosY = fTooltipPosYAim = iElementYPos + iCellSizeY + 10; // Set Y-Pos Hard
fTooltipSizeX = fTooltipSizeXAim = iTooltipSizeX; // X-Size
fTooltipSizeY = fTooltipSizeYAim = iTooltipSizeY; // Set Y-Size Hard
}
if(LOD() < 3) // with fading
{
fTooltipOpacity = 0; // Set Opacity
fTooltipOpacityAim = 1.0;
}
else
{
fTooltipOpacity = fTooltipOpacityAim = 1.0;
}
setAnimationDone(false);
moveTooltip(); // start animation or just set the values
}
function closeTooltip()
{
lockedElementID = "";
bTooltipVisible = false;
if(LOD() == 4)
{
tooltip.style.display = 'none';
}
else
{
if(LOD() < 4)
{
fTooltipSizeYAim = fTooltipSizeY / 2;
fTooltipPosYAim = fTooltipPosY + 50;
}
if(LOD() < 3)
{
fTooltipOpacityAim = 0.0;
}
moveTooltip();
}
}
function moveTooltip()
{
var tooltip = document.getElementById('tooltip');
var tooltip_shadow = document.getElementById('tooltip_shadow');
if(!XPosDone)
{
var XPosDist = fTooltipPosXAim - fTooltipPosX;
if(Math.abs(XPosDist) > 1)
{
fTooltipPosX += XPosDist * fTime * iTooltipMoveFactor;
}
else
{
fTooltipPosX = fTooltipPosXAim;
XPosDone = true;
}
tooltip.style.left = fTooltipPosX + "px";
tooltip_shadow.style.left = (fTooltipPosX - iShadowOffset) + "px";
}
if(!YPosDone)
{
var YPosDist = fTooltipPosYAim - fTooltipPosY;
if(Math.abs(YPosDist) > 1)
{
fTooltipPosY += YPosDist * fTime * iTooltipMoveFactor;
}
else
{
fTooltipPosY = fTooltipPosYAim;
YPosDone = true;
}
tooltip.style.top = fTooltipPosY + "px";
tooltip_shadow.style.top = (fTooltipPosY + iShadowOffset) + "px";
}
if(!XSizeDone)
{
var XSizeDist = fTooltipSizeXAim - fTooltipSizeX;
if(Math.abs(XSizeDist) > 1)
{
fTooltipSizeX += XSizeDist * fTime * iTooltipScaleFactor;
}
else
{
fTooltipSizeX = fTooltipSizeXAim;
XSizeDone = true;
}
tooltip.style.width = fTooltipSizeX + "px";
tooltip_shadow.style.width = fTooltipSizeX + "px";
}
if(!YSizeDone)
{
var YSizeDist = fTooltipSizeYAim - fTooltipSizeY;
if(Math.abs(YSizeDist) > 1)
{
fTooltipSizeY += YSizeDist * fTime * iTooltipScaleFactor;
}
else
{
fTooltipSizeY = fTooltipSizeYAim;
YSizeDone = true;
}
tooltip.style.height = fTooltipSizeY + "px";
tooltip_shadow.style.height = (fTooltipSizeY - 20) + "px";
}
if(!OpacityDone)
{
var OpacityDist = fTooltipOpacityAim - fTooltipOpacity;
if(Math.abs(OpacityDist) > 0.01)
{
fTooltipOpacity += OpacityDist * fTime * iTooltipFadeFactor;
}
else
{
fTooltipOpacity = fTooltipOpacityAim;
OpacityDone = true;
}
tooltip.style.opacity = fTooltipOpacity;
tooltip_shadow.style.opacity = fTooltipOpacity * 0.25;
}
if(XPosDone && YPosDone && XSizeDone && YSizeDone && OpacityDone)
{
// animation done -> no callback
if(bTooltipVisible)
{
setTooltipContent(sTooltipData);
}
else
{
tooltip.style.display = 'none';
tooltip_shadow.style.display = 'none';
removeTooltipContent();
}
开发者_开发百科 setAnimationDone(false);
}
else
{
window.setTimeout('moveTooltip()', fTime);
}
}
function setAnimationDone(bAnimation)
{
XPosDone = bAnimation;
YPosDone = bAnimation;
XSizeDone = bAnimation;
YSizeDone = bAnimation;
OpacityDone = bAnimation;
}
function getArticleData(articleID)
{
$.post("/ajax_getData",
{id:2, articleID:articleID, von_datum:von_datum, von_zeit:von_zeit, bis_datum:bis_datum, bis_zeit:bis_zeit, stationid:stationID},
function (data)
{
sTooltipData = data;
});
}
function setTooltipContent(data)
{
var aData = data.split('|||');
var sPicturePath = aData[0];
var sArticleDescription = aData[1];
var sArticleID = aData[2];
var sPrice = aData[3];
var sArticleName = aData[4];
var aPrice = sPrice.split('_');
sPrice = aPrice[0];
var sTimePeriode = aPrice[1];
if(sTimePeriode == "")
{
sTimePeriode = von_datum + " - " + bis_datum;
}
var htmlCode = '<div style="width:' + (fTooltipSizeX - 25) + 'px; height:' + (fTooltipSizeY-50) + 'px; margin-left:10px; margin-right:10px;">' +
'<div style="height:' + (fTooltipSizeY-50)/3 + 'px;">' +
'<div style="width:' + (fTooltipSizeX-25) /2 + 'px; height:' + (fTooltipSizeY-50)/3 + 'px; float:left">' +
'<div style="width:105px; height:70px; margin-left:auto; margin-right:auto;">' +
'<img src="' + sPicturePath + '">' +
'</div>' +
'</div>' +
'<div style="width:' + (fTooltipSizeX-25) /2 + 'px; height:' + (fTooltipSizeY-50)/3 + 'px; float:left">' +
'<b>PREIS</b><br>' +
sPrice +
'</div>' +
'</div>' +
'<div style="height:' + (fTooltipSizeY-50)*2/3 + 'px;">' +
'<b>' +
sArticleName +
'</b>' +
'<br><br>' +
'<div style="overflow-y:scroll; width:100%; height:65%; border:1px solid black;">' +
'<p style="width:98%; word-wrap:break-word; padding-left:3px; padding-right:3px;">' + sArticleDescription + '</p>' +
'</div>' +
'</div>' +
'</div>';
var content = document.getElementById('tooltipContent');
content.innerHTML = htmlCode;
}
function removeTooltipContent()
{
var content = document.getElementById('tooltipContent');
content.innerHTML = "";
}
function LOD()
{
/**
* LevelOfDetail:
* 1: all animations, fade-effects and Shadows
* 2: animations and fade-effects
* 3: animations
* 4: just the tooltip
*/
if(iLevelOfDetail == -1)
{
var version = $.browser.version;
version = version.substring(0, version.indexOf('.'), version.indexOf('.') + 1);
version = isNaN(version) ? 1 : version * 1;
if($.browser.safari)
{
iLevelOfDetail = 1;
}
else if($.browser.msie)
{
if($.browser.version >= 8) iLevelOfDetail = 1;
else if($.browser.version >= 7) iLevelOfDetail = 2;
else if($.browser.version >= 6) iLevelOfDetail = 3;
}
else if($.browser.mozilla)
{
if($.browser.version >= 4) iLevelOfDetail = 1;
else if($.browser.version >= 2) iLevelOfDetail = 2;
}
else if($.browser.opera)
{
iLevelOfDetail = 1;
}
else
{
iLevelOfDetail = 4;
}
}
return iLevelOfDetail;
}
The relevant part might be in the JS in mouseInElement(articleID); The position of the Icon is calculated incorrectly!
Again thank you very much for your help!
offsetTop
has lots of issues, particularly when scrolling is involved. Maybe try getBoundingClientRect() instead?
精彩评论