Есть ли обходной путь для ошибки Unspecified Error IE 6/7 при доступе к offsetParent?

Я использую перетаскиваемые и сбрасываемые библиотеки jQuery UI в простом ASP.NET-приложении для проверки концепции. Эта страница использует ASP.NET AJAX UpdatePanel для частичного обновления страницы. Страница позволяет пользователю поместить элемент в корзину для мусора, которая вызовет обратную передачу, которая удалит запись из базы данных, а затем повторно свяжет список (и другие элементы управления), из которого этот элемент был наркотиком. Все эти элементы (перетаскиваемые элементы и элемент корзины) находятся внутри панели обновления ASP.NET.

Вот перетаскивающий скрипт инициализации:

    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: Unspecified error». исключение. Я могу решить эту проблему в библиотеке jQuery, заменивelem.offsetParent с вызовами этой функции, которую я написал:

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;
        }
    }
}

Ответы на вопрос(6)

Ваш ответ на вопрос