YUI Library Home

YUI Library Examples: DataTable Control: Reorder Rows with Drag and Drop

DataTable Control: Reorder Rows with Drag and Drop

Reorder rows of a DataTable with Drag and Drop.

id
date
quantity
amount
title
YUI Datatable/DragDrop
po-0167
03/24/1980
1
$4.00
A Book About Nothing
po-0783
01/03/1983
0
$12.12
The Meaning of Life
po-0297
12/12/1978
12
$1.25
This Book Was Meant to Be Read Aloud
po-1482
03/11/1985
6
$3.50
Read Me Twice

Re-orderable table rows

This example shows users how to combine the Drag and Drop Utility with the Datatable widget to easily re-order table rows. There are some cases where the initial ordering of rows doesn't produce the desired output, but with this example we illustrate how users can manually order data by simply dragging and dropping to rearrange the rows.

Making your rows draggable

In order to make your rows draggable, the only thing you need to do is to subscribe to the cellMousedownEvent, then operate on the target row with a custom handler. In this case, onRowSelect is the function we have defined to do all the row dragging.

1myDataTable.subscribe('cellMousedownEvent', onRowSelect); 
view plain | print | ?

Our function, onRowSelect, will create a DDProxy for each row we are trying to drag. We define the custom action for all the predefined DD interesting moments: startDrag, endDrag and onDragOver.

Interesting DD moments

startDrag:
This is when the proxy element gets created and the source element we're dragging gets cached.
endDrag:
We adjust the visibility of the proxy and drag elements.
onDrag:
Determine the direction the drag element is going.
onDragOver:
This is when row and data order manipulation happens. As a table row is dragged over another table row, the two elements and underlying data get swapped.

Defining your targets

A custom init event handler is attached to make a DataTable's rows drag targets:

1////////////////////////////////////////////////////////////////////////////// 
2// Create DDRows instances when DataTable is initialized 
3////////////////////////////////////////////////////////////////////////////// 
4myDataTable.subscribe("initEvent"function() { 
5 
6    var i, id, 
7        allRows = this.getTbodyEl().rows; 
8 
9    for(i=0; i<allRows.length; i++) { 
10        id = allRows[i].id; 
11        // Clean up any existing Drag instances 
12        if (myDTDTargets[id]) { 
13            myDTDTargets[id].unreg(); 
14            delete myDTDTargets[id]; 
15        } 
16        // Create a Drag instance for each row 
17        myDTDTargets[id] = new YAHOO.util.DDTarget(id); 
18    } 
19}); 
view plain | print | ?

Also, it's important to know that whenever a drag/drop operation occurs, DataTable fires a "rowAddEvent" event, which is used to trigger the creation of that new row as a drag target:

1////////////////////////////////////////////////////////////////////////////// 
2// Create DDRows instances when new row is added 
3////////////////////////////////////////////////////////////////////////////// 
4myDataTable.subscribe("rowAddEvent",function(e){ 
5    var id = e.record.getId(); 
6 
7    myDTDTargets[id] = new YAHOO.util.DDTarget(id); 
8}) 
view plain | print | ?

Sample Code for this Example

Data:

1YAHOO.example.Data = { 
2    bookorders: [ 
3        {id:"po-0167", date:new Date(1980, 2, 24), quantity:1, amount:4, title:"A Book About Nothing"}, 
4        {id:"po-0783", date:new Date("January 3, 1983"), quantity:null, amount:12.12345, title:"The Meaning of Life"}, 
5        {id:"po-0297", date:new Date(1978, 11, 12), quantity:12, amount:1.25, title:"This Book Was Meant to Be Read Aloud"}, 
6        {id:"po-1482", date:new Date("March 11, 1985"), quantity:6, amount:3.5, title:"Read Me Twice"} 
7    ] 
8
view plain | print | ?

CSS:

1.custom-class { 
2    opacity0.6;filter:alpha(opacity=60); 
3    color:blue
4    border2px solid gray
5} 
6
7#datatable tr { 
8    cursorpointer
9} 
view plain | print | ?

Markup:

1<div id="datatable"></div> 
view plain | print | ?

JavaScript:

1YAHOO.util.Event.addListener(window, "load"function() { 
2    YAHOO.example.ReorderRows = function() { 
3        var Dom = YAHOO.util.Dom, 
4            Event = YAHOO.util.Event, 
5            DDM = YAHOO.util.DragDropMgr, 
6            myColumnDefs = [ 
7                {key:"id"}, 
8                {key:"date", formatter:"date"}, 
9                {key:"quantity", formatter:"number"}, 
10                {key:"amount", formatter:"currency"}, 
11                {key:"title"
12            ], 
13            myDataSource = new YAHOO.util.LocalDataSource( 
14                YAHOO.example.Data.bookorders, 
15                {responseSchema: {fields: ["id","date","quantity","amount","title"]}} 
16            ), 
17            myDataTable = new YAHOO.widget.DataTable("datatable", myColumnDefs, myDataSource, {caption:"YUI Datatable/DragDrop"}), 
18            myDTDTargets = {}, 
19            onRowSelect = function(ev) { 
20                    var par = myDataTable.getTrEl(Event.getTarget(ev)), 
21                        srcData, 
22                        srcIndex, 
23                        tmpIndex = null
24                        ddRow = new YAHOO.util.DDProxy(par.id); 
25 
26                    ddRow.handleMouseDown(ev.event); 
27 
28 
29                    /**
30                    * Once we start dragging a row, we make the proxyEl look like the src Element. We get also cache all the data related to the
31                    * @return void
32                    * @static
33                    * @method startDrag
34                    */ 
35                    ddRow.startDrag = function () { 
36                        proxyEl  = this.getDragEl(); 
37                        srcEl = this.getEl(); 
38                        srcData = myDataTable.getRecord(srcEl).getData(); 
39                        srcIndex = srcEl.sectionRowIndex; 
40                        // Make the proxy look like the source element 
41                        Dom.setStyle(srcEl, "visibility""hidden"); 
42                        proxyEl.innerHTML = "<table><tbody>"+srcEl.innerHTML+"</tbody></table>"
43                    }; 
44 
45                    /**
46                    * Once we end dragging a row, we swap the proxy with the real element.
47                    * @param x : The x Coordinate
48                    * @param y : The y Coordinate
49                    * @return void
50                    * @static
51                    * @method endDrag
52                    */ 
53                    ddRow.endDrag = function(x,y) { 
54                        Dom.setStyle(proxyEl, "visibility""hidden"); 
55                        Dom.setStyle(srcEl, "visibility"""); 
56                    }; 
57 
58 
59                    /**
60                    * This is the function that does the trick of swapping one row with another.
61                    * @param e : The drag event
62                    * @param id : The id of the row being dragged
63                    * @return void
64                    * @static
65                    * @method onDragOver
66                    */ 
67                    ddRow.onDragOver = function(e, id) { 
68                        // Reorder rows as user drags 
69 
70                        var destEl = Dom.get(id), 
71                            destIndex = destEl.sectionRowIndex; 
72 
73 
74 
75                        if (destEl.nodeName.toLowerCase() === "tr") { 
76                            if(tmpIndex !==null) { 
77                                myDataTable.deleteRow(tmpIndex); 
78                            } 
79                            else { 
80                                myDataTable.deleteRow(srcIndex); 
81                            } 
82 
83                        myDataTable.addRow(srcData, destIndex); 
84                        tmpIndex = destIndex; 
85 
86 
87                        DDM.refreshCache(); 
88                        } 
89                    }; 
90            }; 
91 
92 
93            myDataTable.subscribe('cellMousedownEvent', onRowSelect); 
94 
95 
96 
97 
98 
99        ////////////////////////////////////////////////////////////////////////////// 
100        // Create DDTarget instances when DataTable is initialized 
101        ////////////////////////////////////////////////////////////////////////////// 
102        myDataTable.subscribe("initEvent"function() { 
103 
104            var i, id, 
105                allRows = this.getTbodyEl().rows; 
106 
107 
108            for(i=0; i<allRows.length; i++) { 
109                id = allRows[i].id; 
110                // Clean up any existing Drag instances 
111                if (myDTDTargets[id]) { 
112                     myDTDTargets[id].unreg(); 
113                     delete myDTDTargets[id]; 
114                } 
115                // Create a Drag instance for each row 
116                myDTDTargets[id] = new YAHOO.util.DDTarget(id); 
117            } 
118        }); 
119 
120        ////////////////////////////////////////////////////////////////////////////// 
121        // Create DDTarget instances when new row is added 
122        ////////////////////////////////////////////////////////////////////////////// 
123        myDataTable.subscribe("rowAddEvent",function(e){ 
124            var id = e.record.getId(); 
125 
126            myDTDTargets[id] = new YAHOO.util.DDTarget(id); 
127        }); 
128    }(); 
129}); 
view plain | print | ?

Configuration for This Example

You can load the necessary JavaScript and CSS for this example from Yahoo's servers. Click here to load the YUI Dependency Configurator with all of this example's dependencies preconfigured.

Copyright © 2011 Yahoo! Inc. All rights reserved.

Privacy Policy - Terms of Service - Copyright Policy - Job Openings