YUI Library Home

YUI Library Examples: Drag & Drop: Reordering a List

Drag & Drop: Reordering a List

This example demonstrates how to create a list that can have the order changed with the Drag & Drop Utility.

List 1

  • list 1, item 1
  • list 1, item 2
  • list 1, item 3

List 2

  • list 2, item 1
  • list 2, item 2
  • list 2, item 3

Drag and Drop List Ordering

The YUI Drag & Drop Utility lets you make HTML elements draggable.

In this example, list reordering is implemented by extending YAHOO.util.DDProxy instead of YAHOO.util.DD so that we can use the source element as the "insertion point". When the drag starts, the proxy element style and content is adjusted to match the source element, and visibility:hidden is applied to the source element.

To facilitate dragging into an empty list, we make the two list elements DDTargets. When interacting with the list items, we will get two notifications (one for the list, one for the list item). We ignore all dragOver events that happen on the list and ignore all dragDrop events unless the drop was in the list's negative space (not over another list item).

Create the elements:

1<div class="workarea"
2  <h3>List 1</h3> 
3  <ul id="ul1" class="draglist"
4    <li class="list1" id="li1_1">list 1, item 1</li> 
5    <li class="list1" id="li1_2">list 1, item 2</li> 
6    <li class="list1" id="li1_3">list 1, item 3</li> 
7  </ul> 
8</div> 
9 
10<div class="workarea"
11  <h3>List 2</h3> 
12  <ul id="ul2" class="draglist"
13    <li class="list2" id="li2_1">list 2, item 1</li> 
14    <li class="list2" id="li2_2">list 2, item 2</li> 
15    <li class="list2" id="li2_3">list 2, item 3</li> 
16  </ul> 
17</div> 
view plain | print | ?

Now we create the instances of YAHOO.util.DDProxy, passing the element ids or references for our demo elements.

1<script type="text/javascript"
2 
3(function() { 
4 
5var Dom = YAHOO.util.Dom; 
6var Event = YAHOO.util.Event; 
7var DDM = YAHOO.util.DragDropMgr; 
8 
9////////////////////////////////////////////////////////////////////////////// 
10// example app 
11////////////////////////////////////////////////////////////////////////////// 
12YAHOO.example.DDApp = { 
13    init: function() { 
14 
15        var rows=3,cols=2,i,j; 
16        for (i=1;i<cols+1;i=i+1) { 
17            new YAHOO.util.DDTarget("ul"+i); 
18        } 
19 
20        for (i=1;i<cols+1;i=i+1) { 
21            for (j=1;j<rows+1;j=j+1) { 
22                new YAHOO.example.DDList("li" + i + "_" + j); 
23            } 
24        } 
25 
26        Event.on("showButton""click"this.showOrder); 
27        Event.on("switchButton""click"this.switchStyles); 
28    }, 
29 
30    showOrder: function() { 
31        var parseList = function(ul, title) { 
32            var items = ul.getElementsByTagName("li"); 
33            var out = title + ": "
34            for (i=0;i<items.length;i=i+1) { 
35                out += items[i].id + " "
36            } 
37            return out; 
38        }; 
39 
40        var ul1=Dom.get("ul1"), ul2=Dom.get("ul2"); 
41        alert(parseList(ul1, "List 1") + "\n" + parseList(ul2, "List 2")); 
42 
43    }, 
44 
45    switchStyles: function() { 
46        Dom.get("ul1").className = "draglist_alt"
47        Dom.get("ul2").className = "draglist_alt"
48    } 
49}; 
50 
51////////////////////////////////////////////////////////////////////////////// 
52// custom drag and drop implementation 
53////////////////////////////////////////////////////////////////////////////// 
54 
55YAHOO.example.DDList = function(id, sGroup, config) { 
56 
57    YAHOO.example.DDList.superclass.constructor.call(this, id, sGroup, config); 
58 
59    this.logger = this.logger || YAHOO; 
60    var el = this.getDragEl(); 
61    Dom.setStyle(el, "opacity", 0.67); // The proxy is slightly transparent 
62 
63    this.goingUp = false
64    this.lastY = 0; 
65}; 
66 
67YAHOO.extend(YAHOO.example.DDList, YAHOO.util.DDProxy, { 
68 
69    startDrag: function(x, y) { 
70        this.logger.log(this.id + " startDrag"); 
71 
72        // make the proxy look like the source element 
73        var dragEl = this.getDragEl(); 
74        var clickEl = this.getEl(); 
75        Dom.setStyle(clickEl, "visibility""hidden"); 
76 
77        dragEl.innerHTML = clickEl.innerHTML; 
78 
79        Dom.setStyle(dragEl, "color", Dom.getStyle(clickEl, "color")); 
80        Dom.setStyle(dragEl, "backgroundColor", Dom.getStyle(clickEl, "backgroundColor")); 
81        Dom.setStyle(dragEl, "border""2px solid gray"); 
82    }, 
83 
84    endDrag: function(e) { 
85 
86        var srcEl = this.getEl(); 
87        var proxy = this.getDragEl(); 
88 
89        // Show the proxy element and animate it to the src element's location 
90        Dom.setStyle(proxy, "visibility"""); 
91        var a = new YAHOO.util.Motion(  
92            proxy, {  
93                points: {  
94                    to: Dom.getXY(srcEl) 
95                } 
96            },  
97            0.2,  
98            YAHOO.util.Easing.easeOut  
99        ) 
100        var proxyid = proxy.id; 
101        var thisid = this.id; 
102 
103        // Hide the proxy and show the source element when finished with the animation 
104        a.onComplete.subscribe(function() { 
105                Dom.setStyle(proxyid, "visibility""hidden"); 
106                Dom.setStyle(thisid, "visibility"""); 
107            }); 
108        a.animate(); 
109    }, 
110 
111    onDragDrop: function(e, id) { 
112 
113        // If there is one drop interaction, the li was dropped either on the list, 
114        // or it was dropped on the current location of the source element. 
115        if (DDM.interactionInfo.drop.length === 1) { 
116 
117            // The position of the cursor at the time of the drop (YAHOO.util.Point) 
118            var pt = DDM.interactionInfo.point;  
119 
120            // The region occupied by the source element at the time of the drop 
121            var region = DDM.interactionInfo.sourceRegion;  
122 
123            // Check to see if we are over the source element's location.  We will 
124            // append to the bottom of the list once we are sure it was a drop in 
125            // the negative space (the area of the list without any list items) 
126            if (!region.intersect(pt)) { 
127                var destEl = Dom.get(id); 
128                var destDD = DDM.getDDById(id); 
129                destEl.appendChild(this.getEl()); 
130                destDD.isEmpty = false
131                DDM.refreshCache(); 
132            } 
133 
134        } 
135    }, 
136 
137    onDrag: function(e) { 
138 
139        // Keep track of the direction of the drag for use during onDragOver 
140        var y = Event.getPageY(e); 
141 
142        if (y < this.lastY) { 
143            this.goingUp = true
144        } else if (y > this.lastY) { 
145            this.goingUp = false
146        } 
147 
148        this.lastY = y; 
149    }, 
150 
151    onDragOver: function(e, id) { 
152     
153        var srcEl = this.getEl(); 
154        var destEl = Dom.get(id); 
155 
156        // We are only concerned with list items, we ignore the dragover 
157        // notifications for the list. 
158        if (destEl.nodeName.toLowerCase() == "li") { 
159            var orig_p = srcEl.parentNode; 
160            var p = destEl.parentNode; 
161 
162            if (this.goingUp) { 
163                p.insertBefore(srcEl, destEl); // insert above 
164            } else { 
165                p.insertBefore(srcEl, destEl.nextSibling); // insert below 
166            } 
167 
168            DDM.refreshCache(); 
169        } 
170    } 
171}); 
172 
173Event.onDOMReady(YAHOO.example.DDApp.init, YAHOO.example.DDApp, true); 
174 
175})(); 
176</script> 
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 © 2009 Yahoo! Inc. All rights reserved.

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