list-drag.mustache revision 5b139d58acfcae4b1bcab5a895706abafc2a87a0
fa9e4066f08beec538e775443c5be79dd423fcabahrens<div class="intro">
fa9e4066f08beec538e775443c5be79dd423fcabahrens<p>This example shows how to make a sortable list using Custom Event Bubbling.</p>
fa9e4066f08beec538e775443c5be79dd423fcabahrens</div>
fa9e4066f08beec538e775443c5be79dd423fcabahrens
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens<div class="example">
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens {{>list-drag-source}}
fa9e4066f08beec538e775443c5be79dd423fcabahrens</div>
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens<h3>Setting up the lists</h3>
fa9e4066f08beec538e775443c5be79dd423fcabahrens<p>First we will make some lists that we want to make sortable.</p>
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens```
fa9e4066f08beec538e775443c5be79dd423fcabahrens<div id="play">
fa9e4066f08beec538e775443c5be79dd423fcabahrens <ul id="list1">
fa9e4066f08beec538e775443c5be79dd423fcabahrens <li class="list1">Item #1</li>
fa9e4066f08beec538e775443c5be79dd423fcabahrens <li class="list1">Item #2</li>
fa9e4066f08beec538e775443c5be79dd423fcabahrens <li class="list1">Item #3</li>
fa9e4066f08beec538e775443c5be79dd423fcabahrens <li class="list1">Item #4</li>
fa9e4066f08beec538e775443c5be79dd423fcabahrens <li class="list1">Item #5</li>
fa9e4066f08beec538e775443c5be79dd423fcabahrens </ul>
fa9e4066f08beec538e775443c5be79dd423fcabahrens <ul id="list2">
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens <li class="list2">Item #1</li>
fa9e4066f08beec538e775443c5be79dd423fcabahrens <li class="list2">Item #2</li>
fa9e4066f08beec538e775443c5be79dd423fcabahrens <li class="list2">Item #3</li>
fa9e4066f08beec538e775443c5be79dd423fcabahrens <li class="list2">Item #4</li>
fa9e4066f08beec538e775443c5be79dd423fcabahrens <li class="list2">Item #5</li>
fa9e4066f08beec538e775443c5be79dd423fcabahrens </ul>
fa9e4066f08beec538e775443c5be79dd423fcabahrens</div>
fa9e4066f08beec538e775443c5be79dd423fcabahrens```
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens<h3>Setting up the YUI Instance</h3>
fa9e4066f08beec538e775443c5be79dd423fcabahrens<p>Now we need to create our YUI instance and tell it to load the `dd-constrain`, `dd-proxy` and `dd-drop`, modules.</p>
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens```
fa9e4066f08beec538e775443c5be79dd423fcabahrensYUI().use('dd-constrain', 'dd-proxy', 'dd-drop', function(Y) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens```
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens<h3>Making the Nodes Drag Instances and Drop Targets</h3>
fa9e4066f08beec538e775443c5be79dd423fcabahrens<p>Now we have our YUI instance ready, we can make the list items draggable. We will do this using `Y.Node.all`</p>
fa9e4066f08beec538e775443c5be79dd423fcabahrens<p>We will be passing the selector string `#play ul li` to `Y.Node.all` to have it return a `NodeList` of the li's in our two lists.
fa9e4066f08beec538e775443c5be79dd423fcabahrensUsing this selector syntax we will be able to add new list markup to the `#play` div and not have to change our code.</p>
fa9e4066f08beec538e775443c5be79dd423fcabahrens<p>Then we will walk that `NodeList` and create our draggable Nodes.</p>
fa9e4066f08beec538e775443c5be79dd423fcabahrens<p>Note that we are adding the `DDProxy` and `DDConstrained` plugins to each Drag instance, and setting the following configuration options: `moveOnEnd, constrain2node, target`.</p>
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens```
b81d61a68b235e0529ebadc18e14d9d1dd52a258lling//Get the list of li's in the lists and make them draggable
fa9e4066f08beec538e775443c5be79dd423fcabahrensvar lis = Y.Node.all('#play ul li');
fa9e4066f08beec538e775443c5be79dd423fcabahrenslis.each(function(v, k) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens var dd = new Y.DD.Drag({
fa9e4066f08beec538e775443c5be79dd423fcabahrens node: v,
fa9e4066f08beec538e775443c5be79dd423fcabahrens //Make it Drop target and pass this config to the Drop constructor
fa9e4066f08beec538e775443c5be79dd423fcabahrens target: {
fa9e4066f08beec538e775443c5be79dd423fcabahrens padding: '0 0 0 20'
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }).plug(Y.Plugin.DDProxy, {
fa9e4066f08beec538e775443c5be79dd423fcabahrens //Don't move the node at the end of the drag
fa9e4066f08beec538e775443c5be79dd423fcabahrens moveOnEnd: false
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens }).plug(Y.Plugin.DDConstrained, {
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens //Keep it inside the #play node
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens constrain2node: '#play'
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens });
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens});
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens```
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens<h3>Making the List Drop Targets too</h3>
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens<p>We need to make the UL nodes a Drop Target so we can catch drops on the empty space of the list.
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrensUsing this selector syntax we will be able to add new list markup to the `#play` div and not have to change our code.</p>
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens```
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens//Create simple targets for the 2 lists.
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrensvar uls = Y.Node.all('#play ul');
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrensuls.each(function(v, k) {
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens var tar = new Y.DD.Drop({
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens node: v
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens });
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens});
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens```
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens<h3>Using Event Bubbling</h3>
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens<p>By default, all Drag and Drop instances bubble their events up to the DragDropMgr. In this example we are assuming that there are no other Drag Operations in this YUI Instance.</p>
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens<h3>Start Drag Event</h3>
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens<p>The first thing we will do is handle the drag:start event. In this event, we will set up some styles to apply to the `node` and `dragNode` of the current Drag instance.</p>
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens<p>We will also be copying the `innerHTML` of the `node` and copying that to the `innerHTML` of the `dragNode`. </p>
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens<p><em>It should be noted, that
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrensdoing this will also copy any `id`'s of the nodes inside the `node`. So if you are using this on something that is `id` based, you may need to remove the `id`'s
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrensof the nodes inside the `node` that is being dragged.
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens</em></p>
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens```
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrensY.DD.DDM.on('drag:start', function(e) {
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens //Get our drag object
fa9e4066f08beec538e775443c5be79dd423fcabahrens var drag = e.target;
fa9e4066f08beec538e775443c5be79dd423fcabahrens //Set some styles here
fa9e4066f08beec538e775443c5be79dd423fcabahrens drag.get('node').setStyle('opacity', '.25');
fa9e4066f08beec538e775443c5be79dd423fcabahrens drag.get('dragNode').set('innerHTML', drag.get('node').get('innerHTML'));
fa9e4066f08beec538e775443c5be79dd423fcabahrens drag.get('dragNode').setStyles({
fa9e4066f08beec538e775443c5be79dd423fcabahrens opacity: '.5',
fa9e4066f08beec538e775443c5be79dd423fcabahrens borderColor: drag.get('node').getStyle('borderColor'),
fa9e4066f08beec538e775443c5be79dd423fcabahrens backgroundColor: drag.get('node').getStyle('backgroundColor')
fa9e4066f08beec538e775443c5be79dd423fcabahrens });
fa9e4066f08beec538e775443c5be79dd423fcabahrens});
fa9e4066f08beec538e775443c5be79dd423fcabahrens```
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens<h3>End Drag Event</h3>
fa9e4066f08beec538e775443c5be79dd423fcabahrens<p>In this event, we will reset some of the styles set in the drag:start event.</p>
fa9e4066f08beec538e775443c5be79dd423fcabahrens
b81d61a68b235e0529ebadc18e14d9d1dd52a258lling```
b81d61a68b235e0529ebadc18e14d9d1dd52a258llingY.DD.DDM.on('drag:end', function(e) {
b81d61a68b235e0529ebadc18e14d9d1dd52a258lling var drag = e.target;
b81d61a68b235e0529ebadc18e14d9d1dd52a258lling //Put our styles back
b81d61a68b235e0529ebadc18e14d9d1dd52a258lling drag.get('node').setStyles({
b81d61a68b235e0529ebadc18e14d9d1dd52a258lling visibility: '',
b81d61a68b235e0529ebadc18e14d9d1dd52a258lling opacity: '1'
b81d61a68b235e0529ebadc18e14d9d1dd52a258lling });
b81d61a68b235e0529ebadc18e14d9d1dd52a258lling});
b81d61a68b235e0529ebadc18e14d9d1dd52a258lling```
b81d61a68b235e0529ebadc18e14d9d1dd52a258lling
b81d61a68b235e0529ebadc18e14d9d1dd52a258lling<h3>Drag Event</h3>
b81d61a68b235e0529ebadc18e14d9d1dd52a258lling<p>In this event, we will track the up/down movement for later use.</p>
b81d61a68b235e0529ebadc18e14d9d1dd52a258lling
fa9e4066f08beec538e775443c5be79dd423fcabahrens```
fa9e4066f08beec538e775443c5be79dd423fcabahrensY.DD.DDM.on('drag:drag', function(e) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens //Get the last y point
fa9e4066f08beec538e775443c5be79dd423fcabahrens var y = e.target.lastXY[1];
fa9e4066f08beec538e775443c5be79dd423fcabahrens //is it greater than the lastY var?
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (y &lt; lastY) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens //We are going up
fa9e4066f08beec538e775443c5be79dd423fcabahrens goingUp = true;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens //We are going down.
fa9e4066f08beec538e775443c5be79dd423fcabahrens goingUp = false;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens //Cache for next check
fa9e4066f08beec538e775443c5be79dd423fcabahrens lastY = y;
fa9e4066f08beec538e775443c5be79dd423fcabahrens});
fa9e4066f08beec538e775443c5be79dd423fcabahrens```
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens<h3>Over Drop Event</h3>
fa9e4066f08beec538e775443c5be79dd423fcabahrens<p>In this event, know which Target we are over, so we add the Drag node to the list either above or below the current Drop Target.</p>
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens```
fa9e4066f08beec538e775443c5be79dd423fcabahrensY.DD.DDM.on('drop:over', function(e) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens //Get a reference to our drag and drop nodes
fa9e4066f08beec538e775443c5be79dd423fcabahrens var drag = e.drag.get('node'),
fa9e4066f08beec538e775443c5be79dd423fcabahrens drop = e.drop.get('node');
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens //Are we dropping on a li node?
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (drop.get('tagName').toLowerCase() === 'li') {
fa9e4066f08beec538e775443c5be79dd423fcabahrens //Are we not going up?
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!goingUp) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens drop = drop.get('nextSibling');
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens //Add the node to this list
fa9e4066f08beec538e775443c5be79dd423fcabahrens e.drop.get('node').get('parentNode').insertBefore(drag, drop);
fa9e4066f08beec538e775443c5be79dd423fcabahrens //Resize this nodes shim, so we can drop on it later.
fa9e4066f08beec538e775443c5be79dd423fcabahrens e.drop.sizeShim();
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens});
fa9e4066f08beec538e775443c5be79dd423fcabahrens```
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens<h3>Drop Hit Event</h3>
fa9e4066f08beec538e775443c5be79dd423fcabahrens<p>In this event, we check to see if the target that was dropped on was not an LI node. If it wasn't, then we know it was dropped on the empty space of the UL.</p>
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens```
fa9e4066f08beec538e775443c5be79dd423fcabahrensY.DD.DDM.on('drag:drophit', function(e) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens var drop = e.drop.get('node'),
fa9e4066f08beec538e775443c5be79dd423fcabahrens drag = e.drag.get('node');
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens //if we are not on an li, we must have been dropped on a ul
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (drop.get('tagName').toLowerCase() !== 'li') {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!drop.contains(drag)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens drop.appendChild(drag);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens});
fa9e4066f08beec538e775443c5be79dd423fcabahrens```
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens<h3>Full Javascript Source</h3>
fa9e4066f08beec538e775443c5be79dd423fcabahrens```
fa9e4066f08beec538e775443c5be79dd423fcabahrens{{>list-drag-source-js}}
fa9e4066f08beec538e775443c5be79dd423fcabahrens```
fa9e4066f08beec538e775443c5be79dd423fcabahrens