**~*網頁介面開發**
拖拉元素~調整排序**~!
**網頁介面開發技巧是--拖拉元素調整排序**
**網頁上會顯示五個<span>方塊,
假設其排序有特定意義(例如: 出場順序,
決定先用皮卡丘之後再派妙蛙種子之類的),
使用者可用滑鼠或手指直接拖曳方塊--
--改變其排列順序,當某個方塊被拖到另一個方塊上,就對調兩個方塊的位置,
藉此自由調整所有方塊的排列順序**
**
**
**
**
**有興趣了解程式開發細節的*來看看程式裡用到的技巧: *
**
- 產生五個<span>方塊的部分,採用的--
- -- MVVM的做法。宣告了一個viewModel函數,
- 透過ko.observableArray()保存資料物件陣列,
- <div id="dvList" data-bind="foreach: items">
- 將資料物件陣列的每個元素對應成一個<span>
- ,用<span data-bind="text: name">可將屬性
- 當成<span>的內容。 viewModel函數中,
- var self = this;的做法可視為knockout.js中
- 的Best Practice **
- 為突顯knockout.js可即時反應資料變化的特性,
- 我刻意每隔0.5秒塞入一筆資料,讓我們可--
- --觀察到Player0到Player4逐一出現的過程。
- 而由於setTimeout塞入資料為非同步作業,
- 為了確保在全部完成後才執行下一步驟,
- 再次使用$.Deferred()的技巧處理同步化 ~!**
*元素拖拉部分採用的是Kendo UI Web**的Drag &
Drop功能。實測發現,用Kendo UI所開發的拖拉 -
-功能,不管在PC使用滑鼠操作或在行動裝置進行
手指觸控操作都很順暢,不需針對不同裝置特意
改寫,十分便捷。(但有些小眉角,例如: 有多個--
--放置目標時如何取得當時的放置目標,需要點--
--小技巧,細節可參見程式註解) ***
**至於方塊對調位置的動畫效果,則是--
--將<span>元素先轉成position: absolute,
再靠.animate({ left: 新座標 })搞定,對 jQuery來說-
-不過小菜一碟。
移動過程為了讓使用者有方塊是浮起來在空中-
-飛移的錯覺,
借用了CSS3的transform:
scale(1.1,1.1)讓<span>放大10%,此時早先介紹的HTML5/CSS3瀏覽器
支援速查工具派上用場,
查詢結果顯示要IE10, FF16才支援不加-ms-,
–moz-的寫法,Safari/Chrome則仍需要-webkit-,
所以乖乖加上-ms-, –moz-, –webkit-寫成三筆 **
**<span>對調順序的部分,用jQuery的.after()就
可以解決,但為了定址方便,我偷偷加放了
一個空白<span class='item-pos'>,
程式碼瞬間簡化許多**
**完整程式碼如下,已內含不少註解,
但坦白說,因涉及不少進階技巧,
程式碼並不好懂,希望註解夠清楚 ~!!
**
**
排版顯示純文字複製文字
<title>Drag to Swap Demo</title>
<script src="../Scripts/jquery-1.7.2.min.js"></script>
<script src="../Scripts/kendo/kendo.web.js"></script>
<script src="../Scripts/knockout-2.1.0.js"></script>
<link href="../Content/kendo/kendo.common.min.css"
rel="stylesheet" type="text/css" />
<link href="../Content/kendo/kendo.metro.min.css"
rel="stylesheet" type="text/css" />
//將this另指派給self變數,之後以其代表View Model本體,
self.items = ko.observableArray();
//定義加入item的方法, 在items中加入具有name及score屬性的物件
self.addItem = function(name, score) {
self.items.push({ name: name, score: score });
var vm = new viewModel();
//每隔0.5秒加一筆以觀察knockoutJs讓UI即時反應資料變化的效果
//使用jQuery.Deferred處理實現完成時機的同步
vm.addItem("Player" + i, i * 100);
for (var i = 0; i < 5; i++) {
//等待所有job執行完畢,掛上Kendo UI拖拉功能
$.when.apply(null, jobs).then(function () {
var $items = $("span.item");
//加上拖曳特性,hint事件回傳拖曳過程顯示的元素
return e.clone().addClass("drag-item");
//由於kendoDropTarget事件中,
被放置對象this非亦無事件屬性可存取
//故使用Closure方式將元素存入$item供drop事件存取
//拖曳到目標元素上方及離開
時改變CSS,提供使用者可以放置的提示
dragenter: function (e)
{ $item.addClass("drop-item"); },
dragleave: function (e)
{ $item.removeClass("drop-item"); },
//在目標元素上方鬆開滑鼠或
手指離開觸控螢幕時觸發drop事件
var $drag = e.draggable.element;
$drop.removeClass("drop-item");
if ($drag.text() == $drop.text()) return;
$items.each(function () {
$elem.data("pos", $elem.position());
var pos = $elem.data("pos");
//$drag與$drop交換位置,使用animate
var dragLeft = $drag.data("pos").left + "px";
var dropLeft = $drop.data("pos").left + "px";
var $moving = $drag.add($drop);
$moving.addClass("move-item");
$drag.animate({ left: dropLeft }, 1000);
$drop.animate({ left:
dragLeft }, 1000, function () {
$moving.removeClass("move-item");
var $dragPos = $drag.prev(".item-pos");
$drop.prev(".item-pos").after($drag);
$items.css
({ position: "", left: "", top: "" });
html,body { font-size: 9pt; }
font-family: Segoe UI; display: inline-block;
margin-left: 5px; padding: 5px;
width: 80px; height: 25px;
background-color: #0099FF; color: white;
background-color: #FF3300;
-ms-transform: scale(1.1,1.1); /* IE 9 */
-webkit-transform: scale(1.1,1.1); /* Safari and Chrome */
-moz-transform: scale(1.1,1.1); /* Firefox */
#dvList { margin-top: 20px; }
background-color: Purple;
<div id="dvList" data-bind="foreach: items">
<span class='item-pos'></span>
<span class='item-name' data-bind="text: name"></span>
(<span class='item-score' data-bind="text: score"></span>)
**
**
**
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&