IE 6/7“未指定错误”是否有解决方法? 访问 offsetParent 时的错误

发布于 2024-07-10 14:34:15 字数 10717 浏览 8 评论 0原文

我在一个简单的 ASP.NET 概念验证应用程序中使用 jQuery UI 的可拖放库。 此页面使用 ASP.NET AJAX UpdatePanel 进行部分页面更新。 该页面允许用户将一个项目放入垃圾桶 div 中,这将调用一个回发,从数据库中删除一条记录,然后重新绑定该项目所在的列表(和其他控件)。 所有这些元素(可拖动项和垃圾桶 div)都位于 ASP.NET UpdatePanel 内。

以下是拖放初始化脚本:

    function initDragging()
    {
        $(".person").draggable({helper:'clone'});
        $("#trashcan").droppable({
            accept: '.person',
            tolerance: 'pointer',
            hoverClass: 'trashcan-hover',
            activeClass: 'trashcan-active',
            drop: onTrashCanned
        });
    }

    $(document).ready(function(){
        initDragging();

        var prm = Sys.WebForms.PageRequestManager.getInstance();
        prm.add_endRequest(function()
        {
            initDragging();
        });
    });

    function onTrashCanned(e,ui)
    {
        var id = $('input[id$=hidID]', ui.draggable).val();
        if (id != undefined)
        {
            $('#hidTrashcanID').val(id);
            __doPostBack('btnTrashcan','');
        }

    }

当页面回发时,部分更新 UpdatePanel 的内容,我重新绑定可拖动对象和可放置对象。 然后,当我用光标抓取可拖动对象时,我收到“htmlfile:未指定错误”。 例外。 我可以通过将 elem.offsetParent 替换为对我编写的此函数的调用来解决 jQuery 库中的此问题:

function IESafeOffsetParent(elem)
{
    try
    {
        return elem.offsetParent;
    }
    catch(e)
    {        
        return document.body;
    }
}

我还必须避免调用 elem.getBoundingClientRect(),因为它会引发相同的错误。 对于那些感兴趣的人,我只需在 维度插件

我的问题是:

  • 虽然这可行,但是否有更好的方法(更干净;更好的性能;无需修改 jQuery 库)来解决这个问题?
  • 如果没有,当我将来更新 jQuery 库时,管理保持更改同步的最佳方法是什么? 例如,我可以将库扩展到其他地方,而不仅仅是内联到从 jQuery 网站下载的文件中。

更新:

@some 它不是公开访问的,但我会看看 SO 是否会让我将相关代码发布到这个答案中。 只需创建一个 ASP.NET Web 应用程序(将其命名为 DragAndDrop)并创建这些文件。 不要忘记将 Complex.aspx 设置为您的起始页。 您还需要下载 jQuery UI 拖放插件 以及 jQuery 核心

Complex.aspx< /b>

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Complex.aspx.cs" Inherits="DragAndDrop.Complex" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
    <script src="jquery-1.2.6.min.js" type="text/javascript"></script>
    <script src="jquery-ui-personalized-1.5.3.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        function initDragging()
        {
            $(".person").draggable({helper:'clone'});
            $("#trashcan").droppable({
                accept: '.person',
                tolerance: 'pointer',
                hoverClass: 'trashcan-hover',
                activeClass: 'trashcan-active',
                drop: onTrashCanned
            });
        }

        $(document).ready(function(){
            initDragging();

            var prm = Sys.WebForms.PageRequestManager.getInstance();
            prm.add_endRequest(function()
            {
                initDragging();
            });
        });

        function onTrashCanned(e,ui)
        {
            var id = $('input[id$=hidID]', ui.draggable).val();
            if (id != undefined)
            {
                $('#hidTrashcanID').val(id);
                __doPostBack('btnTrashcan','');
            }

        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <div>
        <asp:UpdatePanel ID="updContent" runat="server" UpdateMode="Always">
    <ContentTemplate>
        <asp:LinkButton ID="btnTrashcan" Text="trashcan" runat="server" CommandName="trashcan" 
            onclick="btnTrashcan_Click" style="display:none;"></asp:LinkButton>
        <input type="hidden" id="hidTrashcanID" runat="server" />
        <asp:Button ID="Button1" runat="server" Text="Save" onclick="Button1_Click" />
        <table>
            <tr>
                <td style="width: 300px;">
                    <asp:DataList ID="lstAllPeople" runat="server" DataSourceID="odsAllPeople"
                        DataKeyField="ID">
                        <ItemTemplate>
                            <div class="person">
                                <asp:HiddenField ID="hidID" runat="server" Value='<%# Eval("ID") %>' />
                                Name:
                                <asp:Label ID="lblName" runat="server" Text='<%# Eval("Name") %>' />
                                <br />
                                <br />
                            </div>
                        </ItemTemplate>
                    </asp:DataList>
                    <asp:ObjectDataSource ID="odsAllPeople" runat="server" SelectMethod="SelectAllPeople" 
                        TypeName="DragAndDrop.Complex+DataAccess" 
                        onselecting="odsAllPeople_Selecting">
                        <SelectParameters>
                            <asp:Parameter Name="filter" Type="Object" />
                        </SelectParameters>
                    </asp:ObjectDataSource>
                </td>
                <td style="width: 300px;vertical-align:top;">
                    <div id="trashcan">
                        drop here to delete
                    </div>
                    <asp:DataList ID="lstPeopleToDelete" runat="server" 
                        DataSourceID="odsPeopleToDelete">
                        <ItemTemplate>
                            ID:
                            <asp:Label ID="IDLabel" runat="server" Text='<%# Eval("ID") %>' />
                            <br />
                            Name:
                            <asp:Label ID="NameLabel" runat="server" Text='<%# Eval("Name") %>' />
                            <br />
                            <br />
                        </ItemTemplate>
                    </asp:DataList>
                    <asp:ObjectDataSource ID="odsPeopleToDelete" runat="server" 
                        onselecting="odsPeopleToDelete_Selecting" SelectMethod="GetDeleteList" 
                        TypeName="DragAndDrop.Complex+DataAccess">
                        <SelectParameters>
                            <asp:Parameter Name="list" Type="Object" />
                        </SelectParameters>
                    </asp:ObjectDataSource>
                </td>
            </tr>
        </table>    
    </ContentTemplate>
    </asp:UpdatePanel>
    </div>
    </form>
</body>
</html>

Complex.aspx.cs

namespace DragAndDrop
{
    public partial class Complex : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }

        protected List<int> DeleteList
        {
            get
            {
                if (ViewState["dl"] == null)
                {
                    List<int> dl = new List<int>();
                    ViewState["dl"] = dl;

                    return dl;
                }
                else
                {
                    return (List<int>)ViewState["dl"];
                }
            }
        }

        public class DataAccess
        {
            public IEnumerable<Person> SelectAllPeople(IEnumerable<int> filter)
            {
                return Database.SelectAll().Where(p => !filter.Contains(p.ID));
            }

            public IEnumerable<Person> GetDeleteList(IEnumerable<int> list)
            {
                return Database.SelectAll().Where(p => list.Contains(p.ID));
            }
        }

        protected void odsAllPeople_Selecting(object sender, ObjectDataSourceSelectingEventArgs e)
        {
            e.InputParameters["filter"] = this.DeleteList;
        }

        protected void odsPeopleToDelete_Selecting(object sender, ObjectDataSourceSelectingEventArgs e)
        {
            e.InputParameters["list"] = this.DeleteList;
        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            foreach (int id in DeleteList)
            {
                Database.DeletePerson(id);
            }

            DeleteList.Clear();
            lstAllPeople.DataBind();
            lstPeopleToDelete.DataBind();
        }

        protected void btnTrashcan_Click(object sender, EventArgs e)
        {
            int id = int.Parse(hidTrashcanID.Value);
            DeleteList.Add(id);
            lstAllPeople.DataBind();
            lstPeopleToDelete.DataBind();
        }
    }
}

Database.cs

namespace DragAndDrop
{
    public static class Database
    {
        private static Dictionary<int, Person> _people = new Dictionary<int,Person>();
        static Database()
        {
            Person[] people = new Person[]
            {
                new Person("Chad")
                , new Person("Carrie")
                , new Person("Richard")
                , new Person("Ron")
            };
            foreach (Person p in people)
            {
                _people.Add(p.ID, p);
            }
        }

        public static IEnumerable<Person> SelectAll()
        {
            return _people.Values;
        }

        public static void DeletePerson(int id)
        {
            if (_people.ContainsKey(id))
            {
                _people.Remove(id);
            }
        }

        public static Person CreatePerson(string name)
        {
            Person p = new Person(name);
            _people.Add(p.ID, p);

            return p;
        }
    }

    public class Person
    {
        private static int _curID = 1;
        public int ID { get; set; }
        public string Name { get; set; }
        public Person()
        {
            ID = _curID++;
        }

        public Person(string name)
            : this()
        {
            Name = name;
        }
    }
}

I'm using jQuery UI's draggable and droppable libraries in a simple ASP.NET proof of concept application. This page uses the ASP.NET AJAX UpdatePanel to do partial page updates. The page allows a user to drop an item into a trashcan div, which will invoke a postback that deletes a record from the database, then rebinds the list (and other controls) that the item was drug from. All of these elements (the draggable items and the trashcan div) are inside an ASP.NET UpdatePanel.

Here is the dragging and dropping initialization script:

    function initDragging()
    {
        $(".person").draggable({helper:'clone'});
        $("#trashcan").droppable({
            accept: '.person',
            tolerance: 'pointer',
            hoverClass: 'trashcan-hover',
            activeClass: 'trashcan-active',
            drop: onTrashCanned
        });
    }

    $(document).ready(function(){
        initDragging();

        var prm = Sys.WebForms.PageRequestManager.getInstance();
        prm.add_endRequest(function()
        {
            initDragging();
        });
    });

    function onTrashCanned(e,ui)
    {
        var id = $('input[id$=hidID]', ui.draggable).val();
        if (id != undefined)
        {
            $('#hidTrashcanID').val(id);
            __doPostBack('btnTrashcan','');
        }

    }

When the page posts back, partially updating the UpdatePanel's content, I rebind the draggables and droppables. When I then grab a draggable with my cursor, I get an "htmlfile: Unspecified error." exception. I can resolve this problem in the jQuery library by replacing elem.offsetParent with calls to this function that I wrote:

function IESafeOffsetParent(elem)
{
    try
    {
        return elem.offsetParent;
    }
    catch(e)
    {        
        return document.body;
    }
}

I also have to avoid calls to elem.getBoundingClientRect() as it throws the same error. For those interested, I only had to make these changes in the jQuery.fn.offset function in the Dimensions Plugin.

My questions are:

  • Although this works, are there better ways (cleaner; better performance; without having to modify the jQuery library) to solve this problem?
  • If not, what's the best way to manage keeping my changes in sync when I update the jQuery libraries in the future? For, example can I extend the library somewhere other than just inline in the files that I download from the jQuery website.

Update:

@some It's not publicly accessible, but I will see if SO will let me post the relevant code into this answer. Just create an ASP.NET Web Application (name it DragAndDrop) and create these files. Don't forget to set Complex.aspx as your start page. You'll also need to download the jQuery UI drag and drop plug in as well as jQuery core

Complex.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Complex.aspx.cs" Inherits="DragAndDrop.Complex" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
    <script src="jquery-1.2.6.min.js" type="text/javascript"></script>
    <script src="jquery-ui-personalized-1.5.3.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        function initDragging()
        {
            $(".person").draggable({helper:'clone'});
            $("#trashcan").droppable({
                accept: '.person',
                tolerance: 'pointer',
                hoverClass: 'trashcan-hover',
                activeClass: 'trashcan-active',
                drop: onTrashCanned
            });
        }

        $(document).ready(function(){
            initDragging();

            var prm = Sys.WebForms.PageRequestManager.getInstance();
            prm.add_endRequest(function()
            {
                initDragging();
            });
        });

        function onTrashCanned(e,ui)
        {
            var id = $('input[id$=hidID]', ui.draggable).val();
            if (id != undefined)
            {
                $('#hidTrashcanID').val(id);
                __doPostBack('btnTrashcan','');
            }

        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <div>
        <asp:UpdatePanel ID="updContent" runat="server" UpdateMode="Always">
    <ContentTemplate>
        <asp:LinkButton ID="btnTrashcan" Text="trashcan" runat="server" CommandName="trashcan" 
            onclick="btnTrashcan_Click" style="display:none;"></asp:LinkButton>
        <input type="hidden" id="hidTrashcanID" runat="server" />
        <asp:Button ID="Button1" runat="server" Text="Save" onclick="Button1_Click" />
        <table>
            <tr>
                <td style="width: 300px;">
                    <asp:DataList ID="lstAllPeople" runat="server" DataSourceID="odsAllPeople"
                        DataKeyField="ID">
                        <ItemTemplate>
                            <div class="person">
                                <asp:HiddenField ID="hidID" runat="server" Value='<%# Eval("ID") %>' />
                                Name:
                                <asp:Label ID="lblName" runat="server" Text='<%# Eval("Name") %>' />
                                <br />
                                <br />
                            </div>
                        </ItemTemplate>
                    </asp:DataList>
                    <asp:ObjectDataSource ID="odsAllPeople" runat="server" SelectMethod="SelectAllPeople" 
                        TypeName="DragAndDrop.Complex+DataAccess" 
                        onselecting="odsAllPeople_Selecting">
                        <SelectParameters>
                            <asp:Parameter Name="filter" Type="Object" />
                        </SelectParameters>
                    </asp:ObjectDataSource>
                </td>
                <td style="width: 300px;vertical-align:top;">
                    <div id="trashcan">
                        drop here to delete
                    </div>
                    <asp:DataList ID="lstPeopleToDelete" runat="server" 
                        DataSourceID="odsPeopleToDelete">
                        <ItemTemplate>
                            ID:
                            <asp:Label ID="IDLabel" runat="server" Text='<%# Eval("ID") %>' />
                            <br />
                            Name:
                            <asp:Label ID="NameLabel" runat="server" Text='<%# Eval("Name") %>' />
                            <br />
                            <br />
                        </ItemTemplate>
                    </asp:DataList>
                    <asp:ObjectDataSource ID="odsPeopleToDelete" runat="server" 
                        onselecting="odsPeopleToDelete_Selecting" SelectMethod="GetDeleteList" 
                        TypeName="DragAndDrop.Complex+DataAccess">
                        <SelectParameters>
                            <asp:Parameter Name="list" Type="Object" />
                        </SelectParameters>
                    </asp:ObjectDataSource>
                </td>
            </tr>
        </table>    
    </ContentTemplate>
    </asp:UpdatePanel>
    </div>
    </form>
</body>
</html>

Complex.aspx.cs

namespace DragAndDrop
{
    public partial class Complex : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }

        protected List<int> DeleteList
        {
            get
            {
                if (ViewState["dl"] == null)
                {
                    List<int> dl = new List<int>();
                    ViewState["dl"] = dl;

                    return dl;
                }
                else
                {
                    return (List<int>)ViewState["dl"];
                }
            }
        }

        public class DataAccess
        {
            public IEnumerable<Person> SelectAllPeople(IEnumerable<int> filter)
            {
                return Database.SelectAll().Where(p => !filter.Contains(p.ID));
            }

            public IEnumerable<Person> GetDeleteList(IEnumerable<int> list)
            {
                return Database.SelectAll().Where(p => list.Contains(p.ID));
            }
        }

        protected void odsAllPeople_Selecting(object sender, ObjectDataSourceSelectingEventArgs e)
        {
            e.InputParameters["filter"] = this.DeleteList;
        }

        protected void odsPeopleToDelete_Selecting(object sender, ObjectDataSourceSelectingEventArgs e)
        {
            e.InputParameters["list"] = this.DeleteList;
        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            foreach (int id in DeleteList)
            {
                Database.DeletePerson(id);
            }

            DeleteList.Clear();
            lstAllPeople.DataBind();
            lstPeopleToDelete.DataBind();
        }

        protected void btnTrashcan_Click(object sender, EventArgs e)
        {
            int id = int.Parse(hidTrashcanID.Value);
            DeleteList.Add(id);
            lstAllPeople.DataBind();
            lstPeopleToDelete.DataBind();
        }
    }
}

Database.cs

namespace DragAndDrop
{
    public static class Database
    {
        private static Dictionary<int, Person> _people = new Dictionary<int,Person>();
        static Database()
        {
            Person[] people = new Person[]
            {
                new Person("Chad")
                , new Person("Carrie")
                , new Person("Richard")
                , new Person("Ron")
            };
            foreach (Person p in people)
            {
                _people.Add(p.ID, p);
            }
        }

        public static IEnumerable<Person> SelectAll()
        {
            return _people.Values;
        }

        public static void DeletePerson(int id)
        {
            if (_people.ContainsKey(id))
            {
                _people.Remove(id);
            }
        }

        public static Person CreatePerson(string name)
        {
            Person p = new Person(name);
            _people.Add(p.ID, p);

            return p;
        }
    }

    public class Person
    {
        private static int _curID = 1;
        public int ID { get; set; }
        public string Name { get; set; }
        public Person()
        {
            ID = _curID++;
        }

        public Person(string name)
            : this()
        {
            Name = name;
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

谈场末日恋爱 2024-07-17 14:34:15

@arilanto - 我在 jquery 脚本之后包含此脚本。 从性能角度来看,这不是最好的解决方案,但它是一个快速简单的解决方案。

function IESafeOffsetParent(elem)
{
    try
    {
       return elem.offsetParent;
    }
    catch(e)
    {        
      return document.body;
    }
}

// The Offset Method
// Originally By Brandon Aaron, part of the Dimension Plugin
// http://jquery.com/plugins/project/dimensions
jQuery.fn.offset = function() {
/// <summary>
///     Gets the current offset of the first matched element relative to the viewport.
/// </summary>
/// <returns type="Object">An object with two Integer properties, 'top' and 'left'.</returns>

var left = 0, top = 0, elem = this[0], results;

if ( elem ) with ( jQuery.browser ) {
    var parent     = elem.parentNode,
        offsetChild  = elem,
        offsetParent = IESafeOffsetParent(elem),
        doc       = elem.ownerDocument,
        safari2   = safari && parseInt(version) < 522 && !/adobeair/i.test(userAgent),
        css       = jQuery.curCSS,
        fixed       = css(elem, "position") == "fixed";

    // Use getBoundingClientRect if available
    if (false && elem.getBoundingClientRect) {
        var box = elem.getBoundingClientRect();

        // Add the document scroll offsets
        add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
            box.top  + Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));

        // IE adds the HTML element's border, by default it is medium which is 2px
        // IE 6 and 7 quirks mode the border width is overwritable by the following css html { border: 0; }
        // IE 7 standards mode, the border is always 2px
        // This border/offset is typically represented by the clientLeft and clientTop properties
        // However, in IE6 and 7 quirks mode the clientLeft and clientTop properties are not updated when overwriting it via CSS
        // Therefore this method will be off by 2px in IE while in quirksmode
        add( -doc.documentElement.clientLeft, -doc.documentElement.clientTop );

    // Otherwise loop through the offsetParents and parentNodes
    } else {

        // Initial element offsets
        add( elem.offsetLeft, elem.offsetTop );

        // Get parent offsets
        while ( offsetParent ) {
            // Add offsetParent offsets
            add( offsetParent.offsetLeft, offsetParent.offsetTop );

            // Mozilla and Safari > 2 does not include the border on offset parents
            // However Mozilla adds the border for table or table cells
            if ( mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2 )
                border( offsetParent );

            // Add the document scroll offsets if position is fixed on any offsetParent
            if ( !fixed && css(offsetParent, "position") == "fixed" )
                fixed = true;

            // Set offsetChild to previous offsetParent unless it is the body element
            offsetChild  = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent;
            // Get next offsetParent
            offsetParent = offsetParent.offsetParent;
        }

        // Get parent scroll offsets
        while ( parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) {
            // Remove parent scroll UNLESS that parent is inline or a table to work around Opera inline/table scrollLeft/Top bug
            if ( !/^inline|table.*$/i.test(css(parent, "display")) )
                // Subtract parent scroll offsets
                add( -parent.scrollLeft, -parent.scrollTop );

            // Mozilla does not add the border for a parent that has overflow != visible
            if ( mozilla && css(parent, "overflow") != "visible" )
                border( parent );

            // Get next parent
            parent = parent.parentNode;
        }

        // Safari <= 2 doubles body offsets with a fixed position element/offsetParent or absolutely positioned offsetChild
        // Mozilla doubles body offsets with a non-absolutely positioned offsetChild
        if ( (safari2 && (fixed || css(offsetChild, "position") == "absolute")) ||
            (mozilla && css(offsetChild, "position") != "absolute") )
                add( -doc.body.offsetLeft, -doc.body.offsetTop );

        // Add the document scroll offsets if position is fixed
        if ( fixed )
            add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
                Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
    }

    // Return an object with top and left properties
    results = { top: top, left: left };
}

function border(elem) {
    /// <summary>
    ///     This method is internal.
    /// </summary>
    /// <private />
    add( jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true) );
}

function add(l, t) {
    /// <summary>
    ///     This method is internal.
    /// </summary>
    /// <private />
    left += parseInt(l, 10) || 0;
    top += parseInt(t, 10) || 0;
}

return results;
};

@arilanto - I include this script after my jquery scripts. Performance wise, it's not the best solution, but it is a quick easy work around.

function IESafeOffsetParent(elem)
{
    try
    {
       return elem.offsetParent;
    }
    catch(e)
    {        
      return document.body;
    }
}

// The Offset Method
// Originally By Brandon Aaron, part of the Dimension Plugin
// http://jquery.com/plugins/project/dimensions
jQuery.fn.offset = function() {
/// <summary>
///     Gets the current offset of the first matched element relative to the viewport.
/// </summary>
/// <returns type="Object">An object with two Integer properties, 'top' and 'left'.</returns>

var left = 0, top = 0, elem = this[0], results;

if ( elem ) with ( jQuery.browser ) {
    var parent     = elem.parentNode,
        offsetChild  = elem,
        offsetParent = IESafeOffsetParent(elem),
        doc       = elem.ownerDocument,
        safari2   = safari && parseInt(version) < 522 && !/adobeair/i.test(userAgent),
        css       = jQuery.curCSS,
        fixed       = css(elem, "position") == "fixed";

    // Use getBoundingClientRect if available
    if (false && elem.getBoundingClientRect) {
        var box = elem.getBoundingClientRect();

        // Add the document scroll offsets
        add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
            box.top  + Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));

        // IE adds the HTML element's border, by default it is medium which is 2px
        // IE 6 and 7 quirks mode the border width is overwritable by the following css html { border: 0; }
        // IE 7 standards mode, the border is always 2px
        // This border/offset is typically represented by the clientLeft and clientTop properties
        // However, in IE6 and 7 quirks mode the clientLeft and clientTop properties are not updated when overwriting it via CSS
        // Therefore this method will be off by 2px in IE while in quirksmode
        add( -doc.documentElement.clientLeft, -doc.documentElement.clientTop );

    // Otherwise loop through the offsetParents and parentNodes
    } else {

        // Initial element offsets
        add( elem.offsetLeft, elem.offsetTop );

        // Get parent offsets
        while ( offsetParent ) {
            // Add offsetParent offsets
            add( offsetParent.offsetLeft, offsetParent.offsetTop );

            // Mozilla and Safari > 2 does not include the border on offset parents
            // However Mozilla adds the border for table or table cells
            if ( mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2 )
                border( offsetParent );

            // Add the document scroll offsets if position is fixed on any offsetParent
            if ( !fixed && css(offsetParent, "position") == "fixed" )
                fixed = true;

            // Set offsetChild to previous offsetParent unless it is the body element
            offsetChild  = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent;
            // Get next offsetParent
            offsetParent = offsetParent.offsetParent;
        }

        // Get parent scroll offsets
        while ( parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) {
            // Remove parent scroll UNLESS that parent is inline or a table to work around Opera inline/table scrollLeft/Top bug
            if ( !/^inline|table.*$/i.test(css(parent, "display")) )
                // Subtract parent scroll offsets
                add( -parent.scrollLeft, -parent.scrollTop );

            // Mozilla does not add the border for a parent that has overflow != visible
            if ( mozilla && css(parent, "overflow") != "visible" )
                border( parent );

            // Get next parent
            parent = parent.parentNode;
        }

        // Safari <= 2 doubles body offsets with a fixed position element/offsetParent or absolutely positioned offsetChild
        // Mozilla doubles body offsets with a non-absolutely positioned offsetChild
        if ( (safari2 && (fixed || css(offsetChild, "position") == "absolute")) ||
            (mozilla && css(offsetChild, "position") != "absolute") )
                add( -doc.body.offsetLeft, -doc.body.offsetTop );

        // Add the document scroll offsets if position is fixed
        if ( fixed )
            add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
                Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
    }

    // Return an object with top and left properties
    results = { top: top, left: left };
}

function border(elem) {
    /// <summary>
    ///     This method is internal.
    /// </summary>
    /// <private />
    add( jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true) );
}

function add(l, t) {
    /// <summary>
    ///     This method is internal.
    /// </summary>
    /// <private />
    left += parseInt(l, 10) || 0;
    top += parseInt(t, 10) || 0;
}

return results;
};
指尖凝香 2024-07-17 14:34:15

如果您想修复 jQuery 版本 1.4.2 的缩小/压缩的 .js 文件,请将:替换

var d=b.getBoundingClientRect(),

var d = null; 
try { d = b.getBoundingClientRect(); }
catch(e) { d = { top : b.offsetTop, left : b.offsetLeft } ; }

(请注意,现在右大括号后面没有逗号)

If you would like to fix the minified/compressed .js file for jQuery version 1.4.2, replace:

var d=b.getBoundingClientRect(),

with

var d = null; 
try { d = b.getBoundingClientRect(); }
catch(e) { d = { top : b.offsetTop, left : b.offsetLeft } ; }

(note that there is no comma after the closing brace now)

贱贱哒 2024-07-17 14:34:15

我尝试了以下解决方法来解决拖放时的 getBoundingClientRect() 未指定错误,并且效果很好。

在 jquery.1.4.2.js(即基本 jquery 文件,其中错误被准确抛出)中

替换 js 文件中的 elem.getBoundingClientRect() 函数调用

//抛出未指定错误的行

var box = elem.getBoundingClientRect(),

与此..


var 框 = null;
尝试
{
box = elem.getBoundingClientRect();
}
捕获(e)
{
box = { 顶部: elem.offsetTop, 左侧: elem.offsetLeft } ;
}

这解决了问题,即使通过更新面板回发后,拖放也能正常工作

问候

Raghu

i tried the following workaround for the getBoundingClientRect() unspecified error whilst drag n drop, and it works fine.

in the jquery.1.4.2.js (i.e base jquery file, where the error is thrown exactly)

replace the elem.getBoundingClientRect() function call in js file

//the line which throws the unspecified error

var box = elem.getBoundingClientRect(),

with this..


var box = null;
try
{
box = elem.getBoundingClientRect();
}
catch(e)
{
box = { top : elem.offsetTop, left : elem.offsetLeft } ;
}

This solves the issue and drag n drop will work quitely even after post back through update panel

Regards

Raghu

月棠 2024-07-17 14:34:15

我的版本是:

  1. 添加功能:

    function getOffsetSum(elem) { 
          var 顶部 = 0,左侧 = 0 
          而(元素){ 
              顶部 = 顶部 + parseInt(elem.offsetTop) 
              左 = 左 + parseInt(elem.offsetLeft) 
              尝试 { 
                  elem = elem.offsetParent 
              } 
              抓住(e){ 
                  返回 { 顶部:顶部,左侧:左侧 } 
              } 
          } 
          返回 { 顶部:顶部,左侧:左侧 } 
      }; 
      
  2. 替换

    var box = this[0].getBoundingClientRect() 
      

    var box = getOffsetSum(this[0]) 
      

PS:jquery-1.3.2。

My version is:

  1. Add function:

    function getOffsetSum(elem) {
        var top = 0, left = 0
        while (elem) {
            top = top + parseInt(elem.offsetTop)
            left = left + parseInt(elem.offsetLeft)
            try {
                elem = elem.offsetParent
            }
            catch (e) {
                return { top: top, left: left }
            }
        }
        return { top: top, left: left }
    };
    
  2. replace

    var box  = this[0].getBoundingClientRect()
    

    with

    var box = getOffsetSum(this[0])
    

PS: jquery-1.3.2.

好听的两个字的网名 2024-07-17 14:34:15

@Raghu

感谢这段代码! 我在 IE 中遇到了同样的问题,这解决了它。

var box = null; 
try { 
    box = elem.getBoundingClientRect(); 
} catch(e) { 
    box = { 
        top : elem.offsetTop, 
        left : elem.offsetLeft 
    }; 
}

@Raghu

Thanks for this bit of code! I was having the same problem in IE and this fixed it.

var box = null; 
try { 
    box = elem.getBoundingClientRect(); 
} catch(e) { 
    box = { 
        top : elem.offsetTop, 
        left : elem.offsetLeft 
    }; 
}
‖放下 2024-07-17 14:34:15

这不仅仅是一个 jQuery 错误。 我在 IE8 上使用 ExtJS 4.0.2a 时遇到了这个问题。 如果 DOM 中的元素已被替换,IE 似乎总是会偶然发现 element.getBoundingClientRect()。 你的 try/catch hack 几乎是解决这个问题的唯一方法。 我想实际的解决方案是最终放弃 IE < 9 支持。

相关 ExtJS v4.0.2a 源代码(第 11861-11869 行):

...
if(el != bd){
    hasAbsolute = fly(el).isStyle("position", "absolute");

    if (el.getBoundingClientRect) {
        b = el.getBoundingClientRect();
        scroll = fly(document).getScroll();
        ret = [Math.round(b.left + scroll.left), Math.round(b.top + scroll.top)];
    } else {
...

使用 try/catch 修复:

...
if(el != bd){
    hasAbsolute = fly(el).isStyle("position", "absolute");

    if (el.getBoundingClientRect) {
        try {
            b = el.getBoundingClientRect();
            scroll = fly(document).getScroll();
            ret = [Math.round(b.left + scroll.left), Math.round(b.top + scroll.top)];
        } catch(e) {
            ret = [0,0];
        }
    } else {
...

This isn't just a jQuery error. I encountered it using ExtJS 4.0.2a on IE8. It seems that IE will almost always stumble on element.getBoundingClientRect() if the element has been replaced in the DOM. Your try/catch hack is pretty much the only way to get around this. I guess the actual solution would be to eventually drop IE < 9 support.

Relevent ExtJS v4.0.2a Source Code (lines 11861-11869):

...
if(el != bd){
    hasAbsolute = fly(el).isStyle("position", "absolute");

    if (el.getBoundingClientRect) {
        b = el.getBoundingClientRect();
        scroll = fly(document).getScroll();
        ret = [Math.round(b.left + scroll.left), Math.round(b.top + scroll.top)];
    } else {
...

With a try/catch fix:

...
if(el != bd){
    hasAbsolute = fly(el).isStyle("position", "absolute");

    if (el.getBoundingClientRect) {
        try {
            b = el.getBoundingClientRect();
            scroll = fly(document).getScroll();
            ret = [Math.round(b.left + scroll.left), Math.round(b.top + scroll.top)];
        } catch(e) {
            ret = [0,0];
        }
    } else {
...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文