JQuery偏移返回IE7中元素“旧”的位置

时间:2011-12-21 18:08:16

标签: jquery internet-explorer-7 css-position

好的,这里发生了一个奇怪的错误,到目前为止谷歌还未能解决任何问题。

当使用IE7(实际上是IE8兼容性)时,JQuery偏移函数不返回元素的当前偏移量。这是一个非常快速的测试页面来演示这个问题:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>

    <script src="Scripts/jquery-1.7.1.js" type="text/javascript"></script>

    <style type="text/css">
        div#Content
        {
            height: 400px;
            overflow: auto;
            border: solid 1px black;
            padding: 2px;
        }
        div.Spacer
        {
            height: 300px;
            border: dotted 1px black;
            background: #ddd;
        }
        div.Wrapper
        {
            padding: 5px;
        }
        div#MoveMe
        {
            position: absolute;
            z-index: 5;
            display: none;
            background-color: Blue;
        }
    </style>
</head>
<body>

    <script type="text/javascript">
        function SetPosition() {
            var divContent = $("div#Content");
            var divMoveMe = $("div#MoveMe");
            var Textbox = $("input#textbox");

            var divMoveMeOffset1 = divMoveMe.offset();

            divMoveMe.css({ "top": "0px", "left": "0px" });
            divMoveMe.height(0);
            divMoveMe.width(0);

            var divMoveMeOffset = divMoveMe.offset();
            var TextboxOffset = Textbox.offset();
            var ContentScrollTop = divContent.scrollTop();
            var ContentScrollLeft = divContent.scrollLeft();
            var divLeft = ((TextboxOffset.left - divMoveMeOffset.left)) + Textbox.outerWidth();
            var divTop = (TextboxOffset.top - divMoveMeOffset.top);
            divMoveMe.css({ "top": divTop + "px", "left": divLeft + "px" });
            divMoveMe.height(Textbox.outerHeight());
            divMoveMe.width(Textbox.outerWidth());

            var divMoveMeOffset2 = divMoveMe.offset();
        }

        $(document).ready(function() {
            $("div#MoveMe").show();
            SetPosition();
            $("div#Content").scroll(SetPosition);
            $(window).scroll(SetPosition);
            $(window).resize(SetPosition);
        });
    </script>

    <div id="Content">
        <div id="Spacer1" class="Spacer">
        </div>
        <div class="Wrapper">
            <input id="textbox" />
            <div id="MoveMe">
            </div>
        </div>
        <div id="Spacer2" class="Spacer">
        </div>
    </div>
    <div id="Spacer3" class="Spacer">
    </div>
</body>
</html>

在IE 8和firefox中,蓝色div正确定位在文本框附近,并通过滚动等保持此相对位置。但是当我回到IE7时,它没有正确保持位置。

尽管我已经知道偏移函数总是在调用SetPosition函数时返回div的位置值,但它们看不到设置顶部和左侧css属性应该产生的更改。我通过添加一些额外的偏移方法调用并对三个结果进行监视来验证这一点。即使在呼叫之间改变了顶部和左侧,所有三个都报告相同的偏移数字 有没有人知道在更改css属性后进行偏移更新的方法?还是另一种方法?

我应该注意到,这是进入Web控件,Wrapper div之外的任何标记或相关样式都不能被修改为有效的解决方案,实际上我需要能够修改它们而不会破坏它行为。

UPDATE:在更多地玩这个时我发现只有在滚动事件期间调用函数时才会出现问题,文档就绪期间的调用正常工作。

2 个答案:

答案 0 :(得分:1)

好的,我弄清楚发生了什么,如果不是确切原因,我能够想出一个解决方案。

在IE 7中,如果从content div的scroll事件中调用my方法,则jquery position和offset方法将始终在事件的上下文中返回相同的值。即使元素被多次重新定位,这些方法似乎也会返回它在事件开始时保持的位置的值。如果通过其他方式(例如文档就绪事件)调用该方法,则一切似乎都能正常工作,并且位置计算对元素的更改位置很敏感。我还应该注意,使用标准javascript回退并计算位置具有相同的行为。

我提出的解决方法是将我的定位方法分成两部分,第一部分将我的div的位置归零,第二部分设置新的位置。然后我在第一个方法中使用setTimeout来调用第二个方法。这使我脱离事件上下文,以便我的位置计算能够正确地找到div的零点。

var t;
function SetPosition() {
    var divMoveMe = $("div#MoveMe");
    if (t) {
        clearTimeout(t);
    }

    divMoveMe.css({ "top": "0px", "left": "0px" });
    divMoveMe.height(0);
    divMoveMe.width(0);

    t = setTimeout(function() { SetPosition2(); }, 0);
}
function SetPosition2() {
    var divMoveMe = $("div#MoveMe");
    var Textbox = $("input#textbox");

    var divMoveMeOffset = divMoveMe.offset();
    var TextboxOffset = Textbox.offset();
    var divLeft = ((TextboxOffset.left - divMoveMeOffset.left)) + Textbox.outerWidth();
    var divTop = (TextboxOffset.top - divMoveMeOffset.top);
    divMoveMe.css({ "top": divTop + "px", "left": divLeft + "px" });
    divMoveMe.height(Textbox.outerHeight());
    divMoveMe.width(Textbox.outerWidth());
}

编辑:此版本的代码也正常工作。似乎关键是在执行位置计算之前突破事件上下文。

var t;
function SetPosition() {
    if (t) {
        clearTimeout(t);
    }
    t = setTimeout(function() { SetPosition2(); }, 0);
}
function SetPosition2() {
    var divContent = $("div#Content");
    var divMoveMe = $("div#MoveMe");
    var Textbox = $("input#textbox");

    divMoveMe.css({ "top": "0px", "left": "0px" });
    divMoveMe.height(0);
    divMoveMe.width(0);

    var divMoveMeOffset = divMoveMe.offset();
    var TextboxOffset = Textbox.offset();
    var divLeft = ((TextboxOffset.left - divMoveMeOffset.left)) + Textbox.outerWidth();
    var divTop = (TextboxOffset.top - divMoveMeOffset.top);
    divMoveMe.css({ "top": divTop + "px", "left": divLeft + "px" });
    divMoveMe.height(Textbox.outerHeight());
    divMoveMe.width(Textbox.outerWidth());
}

答案 1 :(得分:0)

回答您的问题

jQuerys Offset不会返回到浏览器窗口的距离,而是返回到文档的顶部。

您的方法应该是从$(window).scrollTop()

中减去$(div).offset().top

其他建议

接下来我认为这些行代码不正确......不完全确定。

$("div#Content").scroll(SetPosition);
$(window).scroll(SetPosition);
$(window).resize(SetPosition);

如果SetPosition(),则应为SetPosition。但是如果没有返回值,SetPosition不能用作参数?!

顺便说一句,您可以使用:

divMoveMe.css(...).scroll(...).resize(...);

绝对:

divMoveMe.css({ "top": divTop + "px", "left": divLeft + "px" });
divMoveMe.height(Textbox.outerHeight());
divMoveMe.width(Textbox.outerWidth());