5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<div class="intro">
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<p>This example shows how to make a sortable list using Custom Event Bubbling.</p>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<div class="example">
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass {{>list-drag-source}}
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<h3>Setting up the lists</h3>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<p>First we will make some lists that we want to make sortable.</p>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<div id="play">
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass <ul id="list1">
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass <li class="list1">Item #1</li>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass <li class="list1">Item #2</li>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass <li class="list1">Item #3</li>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass <li class="list1">Item #4</li>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass <li class="list1">Item #5</li>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass <ul id="list2">
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass <li class="list2">Item #1</li>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass <li class="list2">Item #2</li>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass <li class="list2">Item #3</li>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass <li class="list2">Item #4</li>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass <li class="list2">Item #5</li>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<h3>Setting up the YUI Instance</h3>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<p>Now we need to create our YUI instance and tell it to load the `dd-constrain`, `dd-proxy` and `dd-drop`, modules.</p>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav GlassYUI().use('dd-constrain', 'dd-proxy', 'dd-drop', function(Y) {
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<h3>Making the Nodes Drag Instances and Drop Targets</h3>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<p>Now we have our YUI instance ready, we can make the list items draggable. We will do this using `Y.Node.all`</p>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<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.
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav GlassUsing this selector syntax we will be able to add new list markup to the `#play` div and not have to change our code.</p>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<p>Then we will walk that `NodeList` and create our draggable Nodes.</p>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<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>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass//Get the list of li's in the lists and make them draggable
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glassvar lis = Y.Node.all('#play ul li');
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glasslis.each(function(v, k) {
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass var dd = new Y.DD.Drag({
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass //Make it Drop target and pass this config to the Drop constructor
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass padding: '0 0 0 20'
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass //Don't move the node at the end of the drag
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass moveOnEnd: false
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass //Keep it inside the #play node
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass constrain2node: '#play'
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<h3>Making the List Drop Targets too</h3>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<p>We need to make the UL nodes a Drop Target so we can catch drops on the empty space of the list.
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav GlassUsing this selector syntax we will be able to add new list markup to the `#play` div and not have to change our code.</p>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass//Create simple targets for the 2 lists.
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glassvar uls = Y.Node.all('#play ul');
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glassuls.each(function(v, k) {
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass var tar = new Y.DD.Drop({
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<h3>Using Event Bubbling</h3>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<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>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<h3>Start Drag Event</h3>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<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>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<p>We will also be copying the `innerHTML` of the `node` and copying that to the `innerHTML` of the `dragNode`. </p>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<p><em>It should be noted, that
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glassdoing 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
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glassof the nodes inside the `node` that is being dragged.
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav GlassY.DD.DDM.on('drag:start', function(e) {
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass //Get our drag object
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass //Set some styles here
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass drag.get('node').setStyle('opacity', '.25');
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass drag.get('dragNode').set('innerHTML', drag.get('node').get('innerHTML'));
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass drag.get('dragNode').setStyles({
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass opacity: '.5',
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass borderColor: drag.get('node').getStyle('borderColor'),
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass backgroundColor: drag.get('node').getStyle('backgroundColor')
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<h3>End Drag Event</h3>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<p>In this event, we will reset some of the styles set in the drag:start event.</p>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav GlassY.DD.DDM.on('drag:end', function(e) {
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass //Put our styles back
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass drag.get('node').setStyles({
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass visibility: '',
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass opacity: '1'
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<h3>Drag Event</h3>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<p>In this event, we will track the up/down movement for later use.</p>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav GlassY.DD.DDM.on('drag:drag', function(e) {
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass //Get the last y point
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass //is it greater than the lastY var?
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass if (y < lastY) {
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass //We are going up
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass goingUp = true;
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass //We are going down.
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass goingUp = false;
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass //Cache for next check
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<h3>Over Drop Event</h3>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<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>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav GlassY.DD.DDM.on('drop:over', function(e) {
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass //Get a reference to our drag and drop nodes
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass var drag = e.drag.get('node'),
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass drop = e.drop.get('node');
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass //Are we dropping on a li node?
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass if (drop.get('tagName').toLowerCase() === 'li') {
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass //Are we not going up?
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass if (!goingUp) {
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass drop = drop.get('nextSibling');
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass //Add the node to this list
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass e.drop.get('node').get('parentNode').insertBefore(drag, drop);
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass //Resize this nodes shim, so we can drop on it later.
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<h3>Drop Hit Event</h3>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<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>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav GlassY.DD.DDM.on('drag:drophit', function(e) {
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass var drop = e.drop.get('node'),
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass drag = e.drag.get('node');
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass //if we are not on an li, we must have been dropped on a ul
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass if (drop.get('tagName').toLowerCase() !== 'li') {
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass<h3>Full Javascript Source</h3>
5b139d58acfcae4b1bcab5a895706abafc2a87a0Dav Glass{{>list-drag-source-js}}