如何在ASP.NET網(wǎng)站中使用HTML 5拖放功能
譯文拖放操作在桌面應用程序中司空見慣?,F(xiàn)在的Web應用程序也試圖利用拖放操作的簡易性和強大功能,提供改善的用戶體驗。Web開發(fā)人員經(jīng)常借助基于JavaScript的庫或自定義方法,以便在自己的應用程序中能夠?qū)崿F(xiàn)拖放操作。幸運的是,HTML5本身內(nèi)置了支持拖放的功能。你使用拖放功能,可以拖動某個HTML元素,將它拖放到另一個HTML元素中。在此過程中,還可以將數(shù)據(jù)從源元素傳送到目標元素。如果把拖放操作與服務器端處理集成起來,你就可以提供豐富的用戶體驗。本文介紹了如何在ASP.NET網(wǎng)站中使用HTML5的拖放功能。
為HTML元素啟用拖動功能
要使用HTML5的拖放功能,第一步是讓一個或多個元素可以拖動。為此,你只需要將HTML元素的可拖動屬性設成true。比如說,下面這行標記代碼將<DIV>元素設成了可拖動元素:
- <div class="myclass" draggable="true">Some content</div>
拖放事件
將一個或多個DOM元素標為可拖動元素只完成了一部分工作。想讓你的拖放操作實際可以使用,而且對最終用戶有視覺吸引力,就要處理某些事件。下面列出了這些事件:
事件 | 描述 |
dragstart | 拖動操作開始時,該事件被觸發(fā)。 |
drag | 元素拖動時,該事件被觸發(fā)。 |
dragenter | 可拖動元素被拖動,并輸入有效的拖放目標后,該事件被觸發(fā)。 |
dragleave | 被拖放到有效拖放目標的可拖動元素離開拖放目標后,該事件被觸發(fā)。 |
dragover | 可拖動元素被拖放到有效拖放目標上方后,該事件被觸發(fā)。 |
drop | 已拖動元素被拖放到有效拖放目標上面后,該事件被觸發(fā)。 |
dragend | 拖動操作結束后,該事件被觸發(fā)。 |
你可以兩種方法將事件處理函數(shù)連接到這些事件,即在DOM元素標記中,使用onxxxx語法,或者使用JavaScript(或基于JavaScript的庫,如jQuery)。下列標記和代碼顯示了這兩種方法。
- <div class="myclass" draggable="true" ondragstart="OnDragStart" ondrop="OnDrop"></div>
- $("div").each(function () {
- this.addEventListener('dragstart', OnDragStart, false);
- this.addEventListener('drop', OnDrop, false);
- });
要注意上述代碼如何使用jQuery代碼中的addEventListener()方法來連接事件處理函數(shù)。
拖操作與放操作之間傳送數(shù)據(jù)
大多數(shù)時候,拖動某個元素,然后把它拖放到另外某個元素上也需要在源元素與目標元素之間傳送一些數(shù)據(jù)。為了完成這項數(shù)據(jù)傳送任務,HTML5提供了DataTransfer對象。下列表格列出了DataTransfer對象的一些重要屬性和方法。
屬性/方法 | 描述 |
effectAllowed | 表明所允許操作的類型。可能的值是:none、copy、copyLink、 copyMove、link、linkMove、move、all和uninitialized。 |
dropEffect | 表明目前選擇的操作的類型。如果操作類型得不到effectAllowed 屬性的支持,那么操作就失效??赡艿闹凳牵簄one、copy、link和move。 |
setDragImage () | 設置拖動操作期間顯示的特定元素。 |
setData() | 設置所傳送的特定數(shù)據(jù)。 |
getData() | 檢索之前設置的數(shù)據(jù),以便進一步處理。 |
clearData() | 清除之前存儲的數(shù)據(jù)。 |
你通常會在dragstart和drop事件處理函數(shù)中使用dataTransfer對象的屬性和方法。
執(zhí)行拖放操作
現(xiàn)在不妨把你到目前為止獲得的信息放入到一個簡單而實用的應用程序中。先建立一個新的ASP.NET網(wǎng)站。你將創(chuàng)建一個酷似下圖的簡單的Web表單:
#p#
簡單的Web表單
注意:該實例在最新版的Firefox上經(jīng)過了測試,但是應該也可以在最新版的其他主要瀏覽器上運行。正如你所見,Web表單表示一輛簡單的購物手推車。各產(chǎn)品由放在DataList控件里面的DIV元素來表示。這些產(chǎn)品可以拖放到購物袋上。一旦所有需要的產(chǎn)品添加完畢,你可以點擊“Place Order”按鈕,即可將產(chǎn)品數(shù)據(jù)發(fā)送到服務器、下訂單。上面這個例子使用了如下所示的Entity Framework數(shù)據(jù)模型。你可以從本文所附的代碼下載鏈接(http://developer.com/imagesvr_ce/6920/drag_drop_Code.zip)獲得SQL Server Express數(shù)據(jù)庫和數(shù)據(jù)模型。
該例子使用了Entity Framework數(shù)據(jù)模型。
上面所示的數(shù)據(jù)模型只包括基本的細節(jié)。在實際環(huán)境下的購物手推車系統(tǒng)中,你可以捕捉到多得多的細節(jié)。產(chǎn)品目錄是一個DataList控件,它的ItemTemplate包括一個可拖動<DIV>元素。該DIV包裝了某個產(chǎn)品的所有產(chǎn)品細節(jié)。
- <asp:DataList ID="DataList1" runat="server" DataSourceID="EntityDataSource1" RepeatDirection="Horizontal">
- <ItemTemplate>
- <div class="product" draggable="true">
- <header><%# Eval("Name") %></header>
- <div><asp:Image runat="server" ID="img1" ImageUrl='<%# Eval("ImageUrl") %>' /></div>
- <div><%# Eval("Description") %></div>
- <br />
- <div><%# Eval("Cost","Cost : ${0}") %></div>
- </div>
- </ItemTemplate>
- </asp:DataList>
- <div class="bag">
- <asp:Image runat="server" ID="img1" ImageUrl="~/images/cart.jpg" />
- <br /><br />
- <input id="Button1" type="button" value="Place Order" />
- <br />
- <input id="Button2" type="button" value="Clear Cart" />
- </div>
請注意表示產(chǎn)品的DIV元素如何被標以設成true的可拖動屬性。負責處理產(chǎn)品外觀和感覺的product CSS類如下所示:
- .product
- {
- height: 300px;
- width: 150px;
- float: left;
- border: 2px solid #666666;
- background-color: white;
- padding:3px;
- margin:5px;
- text-align: center;
- cursor: move;
- }
購物手推車還是帶CSS類bag的DIV元素。
- .bag
- {
- padding:10px;
- text-align: center;
- cursor: move;
- }
下一步是將拖放事件處理函數(shù)連接到各個元素。將使用jQuery來完成這一步,所以確保在<head>部分中引用了jQuery庫。
- <script src="scripts/jquery-1.4.4.min.js"
- type="text/javascript"></script>
連接各個事件處理函數(shù)的jQuery代碼會在ready()事件處理函數(shù)中編寫,如下所示:
- $(document).ready(function () {
- $("div .product").each(function () {
- this.addEventListener('dragstart', OnDragStart, false);
- });
- $("div .bag").each(function () {
- this.addEventListener('dragenter', OnDragEnter, false);
- this.addEventListener('dragleave', OnDragLeave, false);
- this.addEventListener('dragover', OnDragOver, false);
- this.addEventListener('drop', OnDrop, false);
- this.addEventListener('dragend', OnDragEnd, false);
- });
- })
正如你所見,第一個each()調(diào)用為dragstart事件添加了事件偵聽函數(shù)。所有的產(chǎn)品DIV元素應該會處理該事件,那樣代碼就會根據(jù)CSS類product來過濾元素。同樣,購物手推車元素應該會處理其他事件,尤其是drop事件。
下列標記代碼顯示了完整的事件處理函數(shù):OnDragStart、OnDragEnter、OnDragLeave、OnDragOver、OnDrop和OnDragEnd。
- function OnDragStart(e) {
- this.style.opacity = '0.3';
- srcElement = this;
- e.dataTransfer.effectAllowed = 'move';
- e.dataTransfer.setData('text/html', $(this).find("header")[0].innerHTML);
- }
- function OnDragOver(e) {
- if (e.preventDefault) {
- e.preventDefault();
- }
- $(this).addClass('highlight');
- e.dataTransfer.dropEffect = 'move';
- return false;
- }
- function OnDragEnter(e) {
- $(this).addClass('highlight');
- }
- function OnDragLeave(e) {
- $(this).removeClass('highlight');
- }
- function OnDrop(e) {
- if (e.stopPropagation) {
- e.stopPropagation();
- }
- srcElement.style.opacity = '1';
- $(this).removeClass('highlight');
- var count = $(this).find("div[data-product-name='" + e.dataTransfer.getData('text/html') + "']").length;
- if (count <= 0) {
- $(this).append("<div class='selectedproduct' data-product-name='" + e.dataTransfer.getData('text/html') + "'>" + e.dataTransfer.getData('text/html') + "</div>");
- }
- else {
- alert("This product is already added to your cart!");
- }
- return false;
- }
- function OnDragEnd(e) {
- $("div .bag").removeClass('highlight');
- this.style.opacity = '1';
- }
讓我們逐個詳細介紹上面顯示的每個事件處理函數(shù)。
OnDragStart
- function OnDragStart(e) {
- this.style.opacity = '0.3';
- srcElement = this;
- e.dataTransfer.effectAllowed = 'move';
- e.dataTransfer.setData('text/html', $(this).find("header")[0].innerHTML);
- }
dragstart事件處理函數(shù)減少了被拖動元素的不透明度,那樣最終用戶就能獲得關于拖動操作的視覺線索。拖動操作的來源存儲在全局變量srcElement中,因為我們以后在drop事件處理函數(shù)中需要它。dataTransfer對象的effectAllowed屬性被設成了move。此外,setData()方法將數(shù)據(jù)設成了傳送到dataTransfer對象中header元素(即產(chǎn)品名稱)的innerHTML。這樣一來,drop事件處理函數(shù)就知道哪個產(chǎn)品添加到購物手推車中。setData()方法的第一個參數(shù)表明了所傳送數(shù)據(jù)的類型(這里是“text/html”)。
OnDragOver
- function OnDragOver(e) {
- ...
- $(this).addClass('highlight');
- e.dataTransfer.dropEffect = 'move';
- return false;
- }
dragover事件處理函數(shù)將CSS類添加到拖放目標,以便為最終用戶提供關于這一操作的視覺線索。higlight CSS類如下所示:
- .highlight
- {
- background-color:Yellow;
- }
OnDragOver函數(shù)也將dataTransfer對象的dropEffect設成move。
OnDragEnter和OnDragLeave
- function OnDragEnter(e) {
- $(this).addClass('highlight');
- }
- function OnDragLeave(e) {
- $(this).removeClass('highlight');
- }
dragenter和dragleave事件處理函數(shù)很簡單,只是將highlight CSS類添加到目標元素,或者從目標元素中清除這個類。
OnDrop
- function OnDrop(e) {
- ...
- srcElement.style.opacity = '1';
- $(this).removeClass('highlight');
- var count = $(this).find("div[data-product-name='" +
- e.dataTransfer.getData('text/html') + "']").length;
- if (count <= 0) {
- $(this).append("<div class='selectedproduct' data-product-name='" +
- e.dataTransfer.getData('text/html') + "'>" +
- e.dataTransfer.getData('text/html') + "</div>");
- }
- else {
- alert("This product is already added to your cart!");
- }
- return false;
- }
drop事件處理函數(shù)將源元素的不透明度設回成了1,因為拖放操作已完成。它還清除了目標元素中的highlight CSS類。然后,它將被拖動的產(chǎn)品添加到目標元素后面。注意使用getData()方法,檢索之前在dragstart事件處理函數(shù)中設置的數(shù)據(jù)。還要進行檢查,確保同一產(chǎn)品不能添加多次。
OnDragEnd
- function OnDragEnd(e) {
- $("div .bag").removeClass('highlight');
- this.style.opacity = '1';
- }
dragend事件處理函數(shù)只是清除拖放目標中的highlight CSS類。
#p#
將數(shù)據(jù)從客戶端傳送到服務器
要將購物手推車中的產(chǎn)品實際傳送到服務器端代碼,你就要使用jQuery的$.ajax()方法。“Place Order”的click事件處理函數(shù)擁有相關編碼,如下所示:
- $("#Button1").click(function () {
- var data = new Array();
- $("div .bag div").each(function (index) {
- data[index] = "'" + this.innerHTML + "'";
- });
- $.ajax({
- type: 'POST',
- url: 'shoppingcart.aspx/PlaceOrder',
- contentType: "application/json; charset=utf-8",
- data: '{ products:[' + data.join() + ']}',
- dataType: 'json',
- success: function (results) { alert(results.d); },
- error: function () { alert('error'); }
- });
- });
正如你所見,$.ajax()調(diào)用駐留在ShoppingCart.aspx Web表單里面的Web方法PlaceOrder。PlaceOrder Web方法如下所示。
[WebMethod]
- public static string PlaceOrder(string[] products)
- {
- Guid orderId = Guid.NewGuid();
- DatabaseEntities db = new DatabaseEntities();
- foreach (string p in products)
- {
- Order order = new Order();
- order.OrderId = orderId;
- order.ProductName = p;
- order.Qty = 1;
- db.Orders.AddObject(order);
- }
- db.SaveChanges();
- return "Order with " + products.Length.ToString() + " products has been added!";
- }
PlaceOrder Web方法只是把訂單細節(jié)放入到Orders表格中。PlaceOrder() Web方法接受一組表示產(chǎn)品名稱的字符串。要注意$.ajax()如何傳送采用JSON格式的產(chǎn)品參數(shù)。Web方法一旦成功完成,success處理函數(shù)就會向最終用戶顯示提醒信息?,F(xiàn)在運行Web表單,將一個或多個產(chǎn)品拖放到購物手推車上,然后點擊“Place Order”按鈕,就可以將產(chǎn)品名稱從購物手推車傳送到服務器。
結束語
HTML5提供了能夠在網(wǎng)頁中實現(xiàn)拖放功能的一種原生方式。使用這些功能,你就可以改善最終用戶體驗,讓你的網(wǎng)站更具交互性、更容易使用。DOM元素的可拖動屬性管理著某個元素可不可以拖動。dragstart、dragenter、dragleave、 dragover、drop和dragend這些事件讓你可以控制整個拖放操作。dataTransfer對象讓你可以在拖動來源和拖放目標之間傳送數(shù)據(jù)。dataTransfer對象的setData()和getData()方法其任務分別是設置所傳送的數(shù)據(jù)和檢索已傳送的數(shù)據(jù)。
原文:http://www.developer.com/lang/using-html5-drag-and-drop-in-asp.net.html
【編輯推薦】