Estoy usando las bibliotecas arrastrables y droppable de jQuery UI en una simple aplicación de prueba de concepto de ASP.NET. Esta página utiliza ASP.NET AJAX UpdatePanel para realizar actualizaciones de página parciales. La página permite a un usuario colocar un elemento en un div de basura, que invocará una devolución de datos que borrará un registro de la base de datos, y luego volverá a vincular la lista (y otros controles) de los que el artículo era droga. Todos estos elementos (los elementos que se pueden arrastrar y el div de trashcan) están dentro de un UpdatePanel de ASP.NET.Existe una solución para IE 6/7 error "Error no especificado" al acceder a offsetParent
Aquí está el script de inicialización de arrastrar y soltar:
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','');
}
}
cuando la página de nuevo, la actualización parcialmente el contenido del UpdatePanel, que volver a vincular el draggables y droppables. Cuando agarro un arrastrable con mi cursor, aparece un "htmlfile: error no especificado". excepción. Puedo resolver este problema en la biblioteca jQuery reemplazando elem.offsetParent
con llamadas a esta función que escribí:
function IESafeOffsetParent(elem)
{
try
{
return elem.offsetParent;
}
catch(e)
{
return document.body;
}
}
también tengo que evitar las llamadas a elem.getBoundingClientRect(), ya que arroja el mismo error. Para aquellos interesados, solo tuve que hacer estos cambios en la función jQuery.fn.offset
en el Dimensions Plugin.
Mis preguntas son:
- Aunque esto funciona, hay mejores maneras (más limpia; un mejor rendimiento, sin tener que modificar la biblioteca jQuery) para resolver este problema?
- De no ser así, ¿cuál es la mejor forma de administrar la sincronización de mis cambios cuando actualizo las bibliotecas jQuery en el futuro? Por ejemplo, ¿puedo extender la biblioteca en algún lugar que no sea solo en línea en los archivos que descargo del sitio web de jQuery?
Actualización:
@some No es públicamente accesible, pero voy a ver si también lo hará me deja publicar el código en cuestión en esta respuesta. Simplemente cree una aplicación web ASP.NET (llámela DragAndDrop) y cree estos archivos. No olvides configurar Complex.aspx como página de inicio. También tendrá que descargar el jQuery UI drag and drop plug in, así como 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;
}
}
}
Podría dar un enlace a una página de prueba con la cantidad mínima? – some