开发者

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?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜