65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 JQuery 进行带持久化的拖放

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.41/5 (24投票s)

2008 年 3 月 5 日

CPOL

7分钟阅读

viewsIcon

267532

downloadIcon

6351

如何创建拖放功能将用户添加到房间

引言

您是否曾经在网站上看到过拖放操作?它可能允许您将产品拖放到购物车中。我们大多数人都体验过,并且对这项功能印象深刻。在本文中,我们将重点介绍如何创建类似的拖放功能,将用户添加到房间。

为什么选择 JQuery?

为什么确实要选择 JQuery?市面上有许多免费的拖放库。例如,可以使用 Microsoft ASP.NET Ajax。不幸的是,Microsoft Ajax 库对开发者来说并不友好,也就是说,它非常复杂。所以,如果您正在寻找一些令人头疼的体验,请务必深入研究 Microsoft Ajax。但是,如果您对简单而强大的方法感兴趣,那么 JQuery 就是您的朋友。

有些人可能会想,“为什么不直接编写普通的 JavaScript 呢?” 当然可以,但这同样是一个非常复杂且耗时的过程。如果您只想使用 JavaScript,请参阅文章“浏览器兼容的拖放购物车”。

下载 JQuery 和 UI API

在实现任何功能之前,我们需要下载 JQuery 库和 JQuery 拖放 UI API。请查看以下链接进行下载:

  1. JQuery 库
  2. JQuery 拖放 UI API

场景

这个场景与购物车略有不同。在此应用程序中,我们将把用户拖放到一个房间。一旦用户被添加到房间,就会向数据库写入一条记录。我们也可以从房间中删除用户。在这种情况下,数据库中的记录也会被删除。请查看 GIF,链接为“使用 JQuery 实现带持久化的拖放”。

数据库

有一个名为 tblRoomSessions 的表,它将保存有关用户和房间的信息。下面显示了 tblRoomSessions 表的图示。

gridviewguy_jquerydd1.JPG

表脚本包含在下载文件中。

填充学生列表

有多种方法可以填充学生 DataList 控件。您可以使用简单的 DataSet 容器,将其填充来自 tblRoomSession 的数据,然后将其分配给 DataList 控件。我使用了不同的方法,但这实际上并不影响如何填充 DataList

学生 DataList 控件 ASPX 代码

DataList 控件的 ASPX 代码非常直接。请查看下面的代码:

<asp:DataList ID="dlRooms" EnableViewState="false" runat="server" RepeatColumns="3"
            RepeatDirection="Horizontal">
    <ItemTemplate>

    <div id="div1" class="block">

    <div style="text-align:center; font-size:18px; border:solid 1px">

        <%# Container.ItemIndex + 1 %></div><li id="username" runat="server">
    <%# Eval("UserName") %></li><li id="roomId" runat="server" style="visibility:hidden">

    <%# Eval("RoomID") %></li><li>
    <%# Eval("Subject") %></li><li>
    <%# Eval("Description") %></li></div></ItemTemplate></asp:DataList>

DataList 被填充后,它看起来会像下面的截图:

gridviewguy_jqimage1.JPG

数字表示学生请求房间的顺序。这意味着学号为 1 的学生比学号为 2 的学生先请求房间。这些数字是使用以下语句生成的:

<%# Container.ItemIndex + 1 %>

您还会注意到,ID 为 roomId<LI> 被标记为 hidden。您无需在每个 <LI> 中嵌入 roomId,因为您在到达此页面之前就知道 roomId。包含所有 <LI><DIV> 元素具有一个名为 block 的类。让我们在下一节中看看所有的样式。

CSS 样式

此应用程序使用了多种 CSS 样式。让我们看其中一些。

.block {
   border: 2px solid #0090DF;
   background-color: #68BFEF;
   width: 200px;
   height: 200px;
   margin: 10px;
   overflow:auto;
   padding:1em 1em 1em 1em;
   z-index:9999;
   cursor:move;
}

block 样式用于所有可拖动的项。

.roomItem {
   border: 2px solid #0090DF;
   background-color: yellow;
}

roomItem 样式用于添加到房间的项。

.drop {
 background-color: #e9b96e;
 border: 3px double #c17d11;
   width: 300px;
   height: 300px;
   margin: 10px;
   overflow:auto;
   position:absolute;
  top: 5px;
  right: 10%;
  padding: 1em 0 0 0;
}

drop 样式用于放置区域 <DIV> 元素,在本例中是房间。

使用 JQuery 使项可拖放

我将首先发布完整的代码,然后分段解释代码。

$(document).ready(function(){

    $(".block").draggable({helper:'clone'});

    $(".drop").droppable({
 accept: ".block",
 activeClass: 'droppable-active',
 hoverClass: 'droppable-hover',
 drop: function(ev, ui) {

 $(ui.draggable).addClass("roomItem");

 var lid = ($(ui.draggable).children("li:first"));

 // gets the username
 var username = ($(ui.draggable).children("li:first").text()).replace(/[\n\r\t]/g,'');
 var roomId = $(ui.draggable).children("li:eq(1)").text();

 var removeLink = document.createElement("a");
 removeLink.innerHTML = "remove";
 removeLink.href = "#";
 removeLink.onclick = function()
 {
      $("#drop1").children().remove("#"+lid[0].id);
      $(this).remove();
      // removes the class
      $(ui.draggable).removeClass("roomItem");
      // adds the new class
      $(ui.draggable).addClass("block");

      // remove the user session from the database
      VirtualTutoringRoomWebApps.VirtualRoomService.removeUserFromRoom(
          username,Number(roomId));
 }

 $(this).append($(ui.draggable).clone().children("li:first").addClass("roomItem"));
 $(this).append(removeLink);

 // add user to the room
 VirtualTutoringRoomWebApps.VirtualRoomService.addUserToRoom(username,Number(roomId));

 }
});

  });

看起来很复杂!别担心;并不难理解。让我们从 document.ready 函数开始,该函数在 DOM(文档对象模型)准备好并加载后触发。

要使元素可拖动,您只需要使用 JQuery UI API 提供的 draggable 函数。该函数可以接受不同的参数,但我们使用了类的名称,在本例中是 .block。这意味着“使所有类为 .block 的元素可拖动”。draggable 函数还接受 helper。Helper 用于对可拖动项执行操作。我们正在使用 clone helper,它将为我们的可拖动项创建一个 clone

$(".block").draggable({helper:'clone'});

创建放置区域也使用了相同的技术。当项被放到放置区域内时,一个名为 roomItem 的类会被添加到该项。这会给该项应用黄色背景,表明该项已被放入放置区域。然后,我们使用以下代码从可拖动的 <DIV> 元素内的 <LI> 项中提取 usernameroomId

// gets the username
 var username = ($(ui.draggable).children("li:first").text()).replace(/[\n\r\t]/g,'');
 var roomId = $(ui.draggable).children("li:eq(1)").text();

创建了一个新的超链接元素,用于从放置区域中删除项。基本上,remove 链接用于将用户从房间中移除。

var removeLink = document.createElement("a");
 removeLink.innerHTML = "remove";
 removeLink.href = "#";
 removeLink.onclick = function()
 {
      $("#drop1").children().remove("#"+lid[0].id);
      $(this).remove();
      // removes the class
      $(ui.draggable).removeClass("roomItem");
      // adds the new class
      $(ui.draggable).addClass("block");

      // remove the user session from the database
      VirtualTutoringRoomWebApps.VirtualRoomService.removeUserFromRoom(
          username,Number(roomId));
 }

当项从放置区域移除时,它会返回到其原始类,即 block。服务器端 removeUserFromRoom 方法被触发,该方法将项从数据库中移除。我们将在本文稍后介绍此方法。当我们拖放项到放置区域时,我们将第一个 <LI> 元素附加到放置区域。在本例中,这是用户的 username

$(this).append($(ui.draggable).clone().children("li:first").addClass("roomItem"));
 $(this).append(removeLink);

 // add user to the room
 VirtualTutoringRoomWebApps.VirtualRoomService.addUserToRoom(username,Number(roomId));

请查看下面的截图,显示了添加到放置区域的项。

gridviewguy_jqimage2.JPG

最后,addUserToRoom 方法被触发,并将用户添加到房间。

Ajax 方法

我使用了 Microsoft ASP.NET Ajax 来创建到 Web 服务方法的异步调用。让我们看看这些方法:

[WebMethod]
        public bool removeUserFromRoom(string username, int roomId)
        {
            MethodInvoker.Invoke<SQLDataAccess>("RemoveUserFromRoom", new object[]
            {
                username.Trim(), roomId
            });

            return false;
        }

        [WebMethod]
        public bool addUserToRoom(string username, int roomId)
        {
            try
            {
                MethodInvoker.Invoke<SQLDataAccess>(
                    typeof(tblRoomSession), "AddAndPersistAll",
                    new object[]
                    {
                        new tblRoomSession()
                        {
                            Guid = Guid.NewGuid().ToString(), RoomID = roomId,
                            StudentUserName = username.Trim(),
                            TutorUserName = User.Identity.Name, IsSessionStarted = true,
                            SessionStartDate = DateTime.Now
                        }
                    });
            }
            catch (Exception ex)
            {
                string exception = ex.Message;
            }

            return false;
        }

不要太在意 MethodInvoker 类。这是一个自定义类,用于在对象上创建数据访问操作。您可以使用 DataSetEntity 类、ManagerRepositoryMapper 来执行数据访问操作。如果您对 MethodInvoker 类感兴趣,请参阅博文“MethodInvoker”。

附加功能

此应用程序还需要实现一些额外的功能。其中一些列在下面:

  1. 一个计时器,它将异步获取等待房间的用户,而无需刷新页面。
  2. 不允许将重复用户添加到同一个房间。

更新

在发布时,我们讨论了一些可能有用的附加功能。其中一些显示在上面的“附加功能”部分。这里实现了这两个功能。

首先,让我们看看当新用户进入等待列表时如何更新界面。这个过程应该是异步的,这意味着屏幕不应在服务器端刷新,而应在客户端刷新。事实证明,这可以通过使用 ASP.NET Timer 控件轻松完成。Timer 控件将触发一个事件,该事件将触发服务器端的一个方法。首先,您需要在 UpdatePanel 控件内添加 Triggers 部分。

 <triggers>
     <asyncpostbacktrigger eventname="Tick" controlid="timer1">
     </triggers>

现在,让我们看看同样包含在 UpdatePanel 控件内的 Timer 控件。

<timer id="timer1" ontick="timer1_Tick" interval="5000" runat="server" />

Timer 控件每 5 秒触发一次 timer1_Tick 事件。现在,让我们看看 timer1_Tick 事件:

  protected void timer1_Tick(object sender, EventArgs e)
        {
            BindData();
            up1.Update();        }

这很简单!timer1_Tick 事件通过 BindData 方法从数据库获取数据,然后刷新 UpdatePanel 以更新用户界面。一切运行良好……持续 5 秒。5 秒后,您将无法拖放您的对象。

原因在于,当您使用 UpdatePanel 更新屏幕时,它会重置其中的所有控件。现在,您可以看到控件,但它们没有任何功能。有一个简单的方法可以解决这个问题。您所要做的就是再次使元素可拖动。请查看下面的实现:

protected void timer1_Tick(object sender, EventArgs e)
        {
            BindData();
            up1.Update();

            RegisterDragAndDropScript();
        }

        // this method is fired to register the scripts again 
        // since the timer will refresh the contents of the
        // update panel and hence the HTML controls will lose 
        // the drag and drop capability
        private void RegisterDragAndDropScript()
        {
            string script = "makeElementsDraggableAndDroppable();";

            ScriptManager.RegisterClientScriptBlock(this,this.GetType(),
                "DragAndDropScript", script, true);

        }

现在,当 UpdatePanel 刷新时,控件再次变得可拖动。

结论

在本文中,我们学习了如何使用 JQueryJQuery UI API 创建拖放 UI。希望您喜欢这篇文章;祝您编码愉快!

历史

  • 2008 年 3 月 5 日 -- 最初版本发布
  • 2008 年 3 月 7 日 -- 文章更新
© . All rights reserved.