首頁

2013年6月23日 星期日

**網頁介面開發**拖拉元素~調整排序**~!

**~*網頁介面開發**
拖拉元素~調整排序**~!

**網頁介面開發技巧是--拖拉元素調整排序**
**網頁上會顯示五個<span>方塊,
假設其排序有特定意義(例如: 出場順序,
決定先用皮卡丘之後再派妙蛙種子之類的),
使用者可用滑鼠或手指直接拖曳方塊--
--改變其排列順序,當某個方塊被拖到另一個方塊上,就對調兩個方塊的位置,
藉此自由調整所有方塊的排列順序**
****
****

**有興趣了解程式開發細節的*來看看程式裡用到的技巧:       *
**
  1. 產生五個<span>方塊的部分,採用的--
  2. -- MVVM的做法。宣告了一個viewModel函數,
  3. 透過ko.observableArray()保存資料物件陣列,
  4. <div id="dvList" data-bind="foreach: items">
  5. 將資料物件陣列的每個元素對應成一個<span>
  6. ,用<span data-bind="text: name">可將屬性
  7. 當成<span>的內容。 viewModel函數中,
  8. var self = this;的做法可視為knockout.js中
  9. 的Best Practice  **
  10. 為突顯knockout.js可即時反應資料變化的特性,
  11. 我刻意每隔0.5秒塞入一筆資料,讓我們可--
  12. --觀察到Player0到Player4逐一出現的過程。
  13. 而由於setTimeout塞入資料為非同步作業,
  14. 為了確保在全部完成後才執行下一步驟,
  15. 再次使用$.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'>,
程式碼瞬間簡化許多**

**完整程式碼如下,已內含不少註解,
但坦白說,因涉及不少進階技巧,
程式碼並不好懂,希望註解夠清楚 ~!!
**
**
排版顯示純文字
<!DOCTYPE html>

 
<html> 
<head> 
    <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" /> 
    <script> 
       //定義ViewModel類別 
        function viewModel() { 
          //將this另指派給self變數,之後以其代表View Model本體,
            //避免與函數中的this所指的對象混淆  
            var self = this; 
          //定義一個集合存放資料 
            self.items = ko.observableArray(); 
          //定義加入item的方法, 在items中加入具有name及score屬性的物件 
            self.addItem = function(name, score) { 
                self.items.push({ name: name, score: score }); 
          };  
        } 
 
        $(function () { 
           //建立ViewModel 
           var vm = new viewModel(); 
           //每隔0.5秒加一筆以觀察knockoutJs讓UI即時反應資料變化的效果 
            //使用jQuery.Deferred處理實現完成時機的同步 
            function job(i) { 
                var df = $.Deferred(); 
                setTimeout(function () { 
                    vm.addItem("Player" + i, i * 100); 
                    df.resolve(); 
                }, i * 500); 
                return df.promise(); 
            } 
            //建立延遲0-4秒執行的加入item作業 
            var jobs = []; 
            for (var i = 0; i < 5; i++) { 
                jobs.push(job(i)); 
            } 
            //等待所有job執行完畢,掛上Kendo UI拖拉功能 
            $.when.apply(null, jobs).then(function () { 
                var $items = $("span.item"); 
                //加上拖曳特性,hint事件回傳拖曳過程顯示的元素 
    $items.kendoDraggable({ 
                    hint: function (e) { 
                        return e.clone().addClass("drag-item"); 
                    } 
                }) 
                .each(function () { 
                    //由於kendoDropTarget事件中,
被放置對象this非亦無事件屬性可存取 
                       //故使用Closure方式將元素存入$item供drop事件存取 
                    var $item = $(this);
                    //加上放置目標特性才能接成為拖曳的目標 
                    $item.kendoDropTarget({
                        //拖曳到目標元素上方及離開
時改變CSS,提供使用者可以放置的提示
                        dragenter: function (e)
 { $item.addClass("drop-item"); },
                        dragleave: function (e)
 { $item.removeClass("drop-item"); },
                        //在目標元素上方鬆開滑鼠或 
手指離開觸控螢幕時觸發drop事件 
                           drop: function (e) { 
                            //透過以下方式取得拖曳元素及放置元素 
                                 var $drag = e.draggable.element; 
                            var $drop = $item; 
                            $drop.removeClass("drop-item"); 
                            //拖曳對象與放置目標相同時不處理 
                                 if ($drag.text() == $drop.text()) return; 
                            //顯示位置交換動畫 
                                //先將全部元素轉為絕對座標 
                            $items.each(function () { 
                                //先記下座標值,以.data()保存 
                                var $elem = $(this); 
                                $elem.data("pos", $elem.position()); 
                            }) 
                            .each(function () { 
                                //維持座標位置,但換成絕對座標 
                                      var $elem = $(this); 
                                var pos = $elem.data("pos"); 
                                $(this).css({ 
                                    position: "absolute", 
                                    top: pos.top + "px", 
                                    left: pos.left + "px" 
                                }); 
                            }); 
                            //$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);  
                                $dragPos.after($drop); 
                                //改回相對座標 
                                $items.css
({ position: "", left: "", top: "" }); 
                            }); 
                        } 
                    }); 
                }); 
            }); 
            //將ViewModel與UI結合 
            ko.applyBindings(vm); 
        }); 
    </script> 
    <style> 
        html,body { font-size: 9pt; } 
        .item 
        { 
            font-family: Segoe UI; display: inline-block; 
            border: 1px solid gray; 
            margin-left: 5px; padding: 5px; 
            width: 80px; height: 25px; 
            background-color: #0099FF; color: white; 
            text-align: center; 
        } 
        .drag-item 
        { 
            opacity: 0.5; 
            background-color: #FF3300; 
        } 
        .move-item  
        { 
            z-index: 9; 
            -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; } 
        .drop-item 
        { 
            background-color: Purple; 
        } 
    </style> 
</head> 
<body> 
<div id="dvList" data-bind="foreach: items"> 
    <span class='item-pos'></span> 
    <span class='item'> 
        <span class='item-name' data-bind="text: name"></span> 
        (<span class='item-score' data-bind="text: score"></span>) 
    </span> 
</div> 
</body> 
</html> 

**
****
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

沒有留言:

張貼留言


if you like make fds, wellcome you here~~anytime***

my free place for everyones who want the good software,

come & download them~ wellcome!!