30 Days of Mootools 1.2 Tutorials - Day 12 - Drag and Drop using Drag.Move

- Troy

Drag.Move - Drag and Drop with Mootools 1.2

If you haven’t already, be sure and check out the rest of the Mootools 1.2 tutorials in our 30 days series.

Welcome to Day 12 of 30 Days of Mootools. Today we are going to take a close look at Drag.Move, a powerful Mootools class that lets you add drag and drop functionality to your web application. It is set up like the rest of the plugins we have looked at: you create your “new” Drag.Move object and pass it to a var. Then you define your options and events. That’s pretty much all there is to it, but be sure to check out the description of IE CSS quirks in the example.

The Basics

Drag.Move

Setting up your drag object is very easy. Just take a look below. Notice how we have separated out our Drag.Move options and events from our Drag options and events. Drag.Move extends Drag, so it will accept both its options and events, as well as Drag’s. We are not going to look at Drag specifically today, but we are going to explore a few of the useful options and events. Take a look at the code below, then read on to learn the specifics.

var myDrag = new Drag.Move(dragElement, {
	        // Drag.Move Options
		droppables: dropElement,
		container: dragContainer,
		// Drag Options
		handle: dragHandle,
		// Drag.Move Events
                // the Drag.Move events pass the dragged element, 
                // and the dropped into droppable element
		onDrop: function(el, dr) {
                        //will alert the id of the dropped into droppable element
                        alert(dr.get('id'));
		},
                // Drag Events
                // Drag events pass the dragged element
                onComplete: function(el) {
			alert(el.get('id'));
		}
	});

Let’s break this down a bit…

Drag.Move Options

The Drag.Move options let you set two important elements:

droppables - Set the selector of droppable elements (which elements will register on drop related events)

container - Set the drag element’s container (will keep the element inside)

Setting the options is simple:

//here we define a single element by id 
var dragElement = $('drag_element');
//here we define an array of elements by class
var dropElements = $$('.drag_element');
 
var dragContainer = $('drag_container');
//now we set up our Drag.Move object
var myDrag = new Drag.Move(dragElement , {
	        // Drag.Move Options
                // set up our droppables element with the droppables var we defined above
		droppables: dropElements ,
               // set up our container element with the container element var
		container: dragContainer 
	});

Now your draggable element is contained and you have a class that will accept drops.

Drag.Move Events

The events give you the ability to fire a function at different points, such as when you start to drag the object or when you drop it. Each Drag.Move event will pass the dragged element and the dropped into element (as long as its droppable) as parameters.

onDrop - this will fire when you drop the draggable element into a droppable element

onLeave - fires when a draggable element leaves a droppable element’s bounds

onEnter - fires when a draggable element enters a droppable element

Each of these events will call a function and that function will fire when the event happens.

var dragContainer = $('drag_container');
 
var myDrag = new Drag.Move(dragElement , {
	        // Drag.Move Options
		droppables: dropElements ,
		container: dragContainer ,
	        // Drag.Move Options
                // the Drag.Move functions will pass the draggable element ('el' in this case)
                // and the droppable element the draggable is interacting with ('dr' here)
                onDrop: function(el, dr) {
                        // roughly translates to, "if the element you drop onto is NOT a droppable element
			if (!dr) { 
                            //dont do anything
                        }
                        // otherwise (logically meaning, if the element you drop onto IS droppable
                        // do this other thing here
        	        else {
			    //have something happen when you drop on a droppable
			};
		},
		onLeave: function(el, dr) {
			// this will fire when a draggable leaves a droppable element
		},
		onEnter: function(el, dr) {
			// this will fire when a draggable enters a droppable element
		}
	});

A few Drag events and options

There are quite a few options and events for Drag, but here we are just going to look at a few.

snap - option

Snap lets you set how many px the user must drag their cursor before the draggable element starts dragging. The default is 6, and you can set it any number or variable representing a number. Clearly, there are limits to what is reasonable (setting snap to 1000 wouldn’t be all that useful), but this does come in handy by letting you customize the user experience that much more.

var myDrag = new Drag.Move(dragElement , {
	        // Drag Options
		snap: 10 
	});

handle - option

Handle adds a handle to your draggable element. The handle becomes the only element that will accept the ‘grab,’ letting you use the rest of the element for other things. To set up a handle, just call the element.

// here we are setting up an array using a class selector
// this will let us easily add multiple handles if we decide to have multiple draggables
var dragHandle = $('drag_handle');
var myDrag = new Drag.Move(dragElement , {
	        // Drag Options
		handle: dragHandle 
	});

onStart - event

On start does what it says, fires an event on the start of drag. If you have a long snap set, then this event wouldn’t fire until the mouse had gone that distance.

var myDrag = new Drag.Move(dragElement , {
	        // Drag Options
                // Drag options will pass the dragged element as a parameter
		onStart: function(el) {
                    // put whatever you want to happen on start in here
               }
	});

onDrag - event

This event, onDrag, will fire continuously while you are dragging an element.

var myDrag = new Drag.Move(dragElement , {
	        // Drag Options
                // Drag options will pass the dragged element as a parameter
		onDrag: function(el) {
                    // put whatever you want to happen on drag in here
               }
	});

onComplete - event

Finally, onComplete refers to when you drop a grabbable, and it will fire whether or not you land in a droppable.

var myDrag = new Drag.Move(dragElement , {
	        // Drag Options
                // Drag options will pass the dragged element as a parameter
		onComplete: function(el) {
                    // put whatever you want to happen on complete
               }
	});

Example

Let’s put this all together in a way that highlights when different events fire, and let’s use the options we looked at above to configure the Drag.Move object:

window.addEvent('domready', function() {
	var dragElement = $('drag_me');
	var dragContainer = $('drag_cont');
	var dragHandle = $('drag_me_handle');
	var dropElement = $$('.draggable');
	var startEl = $('start');
	var completeEl = $('complete');
	var dragIndicatorEl = $('drag_ind');
	var enterDrop = $('enter');
	var leaveDrop = $('leave');
	var dropDrop = $('drop_in_droppable'); 
 
	var myDrag = new Drag.Move(dragElement, {
	    // Drag.Move options
		droppables: dropElement,
		container: dragContainer,
		// Drag options
		handle: dragHandle,
		// Drag.Move Events
		onDrop: function(el, dr) {
			if (!dr) { }
 
        	        else {
				dropDrop.highlight('#FB911C'); //flashes orange
				el.highlight('#fff'); //flashes white
				dr.highlight('#667C4A'); //flashes green
			};
		},
		onLeave: function(el, dr) {
			leaveDrop.highlight('#FB911C'); //flashes orange
		},
		onEnter: function(el, dr) {
			enterDrop.highlight('#FB911C'); //flashes orange
		},
		// Drag Events
		onStart: function(el) {
			startEl.highlight('#FB911C'); //flashes orange
		},
		onDrag: function(el) {
			dragIndicatorEl.highlight('#FB911C'); //flashes orange
		},
		onComplete: function(el) {
			completeEl.highlight('#FB911C'); //flashes orange
		}
	});
});

Note on the css: For the Drag.Move container to register properly in IE, you will need to be sure to include positioning spelled out in the following css. The important part is to remember to set the container with “position: relative” and the draggable with “position: absolute,” then be sure to set the position of the draggable with “left” and “top.” Now, if you are just building for all the other browsers that follow the rules, you can ignore this part:

/* this is generally a good idea */
body {
	margin: 0
	padding: 0
}
 
/* make sure the draggable element has "position: absolute" 
*/ and then top and left are set for the start position
#drag_me {
	width: 100px
	height: 100px
	background-color: #333
	position: absolute
	top: 0
	left: 0
}
 
 
#drop_here {
	width: 200px
	height: 200px
	background-color: #eee
}
 
/* make sure the drag container is set with position relative */
#drag_cont {
	background-color: #ccc  
	height: 600px 
	width: 500px
	position: relative
	margin-top: 100px
	margin-left: 100px
}
 
 
#drag_me_handle {
	width: 100%
	height: auto
	background-color: #666
}
 
#drag_me_handle span {
	display: block
	padding: 5px
}
 
 
.indicator {
	width: 100%
	height: auto
	background-color: #0066FF
	border-bottom: 1px solid #eee
}
 
.indicator span {
	padding: 10px
	display: block
}
 
.draggable {
	width: 200px
	height: 200px
	background-color: blue
}

And now we set up our html:

<div id="drag_cont">
    <div id="start" class="indicator"><span>Start</span></div>
    <div id="drag_ind" class="indicator"><span>Drag</span></div>
    <div id="complete" class="indicator"><span>Complete</span></div>
    <div id="enter" class="indicator"><span>Enter Droppable Element</span></div>
    <div id="leave" class="indicator"><span>Leave Droppable Element</span></div>
    <div id="drop_in_droppable" class="indicator"><span>Dropped in Droppable Element</span></div>
    <div id="drag_me">
        <div id="drag_me_handle"><span>handle</span></div>
    </div>
 
    <div id="drop_here" class="draggable"></div>
</div>
Start
Drag
Complete
Enter Droppable Element
Leave Droppable Element
Dropped in Droppable Element
handle

To Learn More…

Here are few relevant sections from the docs:

Download a zip with everything you need to get started

Including the mootools 1.2 core, the mootools 1.2 more library, an external javascript file for your functions, an external css file for your styles, and simple html file and the example above.

Tomorrow’s Tutorial

For Day 13, we are going to look at using regular expressions with Mootools 1.2

Questions, Comments, Suggestions?

There are still some more basic concepts to cover, but we are going to now branch out deeper into the library. Within the next week or so we are going to start to feature some practical projects that will give you more control over your user interface. Please let us know if there are any more ‘fundamentals’ you would like to cover, if there are any projects you would like to see featured here, and of course, any questions, comments or suggestions. Thanks and hope you are finding this series useful.

Bookmark and Share

Comments (7)
  1. Peace


    Oh, that's great.
    Maybe I should just use the drag.Move class but with the 'drop' event.
    I still can't understand why samples can successfully combine the drag.Move class and the 'drop' event. Do they have relationship with each other? This may sound stupid.
    Could you make some time to see the 'drop' event and drop me a answer, too?
  2. Troy


    I'm not sure if I understand your questions Peace. By 'drop' event are you referring to onDrop? Part of the important thing to keep in mind with onDrop is that it will measure when you drop it, so you need to add extra logic in there that say "do this ONLY if you drop inside a droppable." Not sure if this helps at all.
  3. Peace


    The following is the sample named "Drag.Absolutely" of mootools demos, thought the version is 1.11.
    "

    var droppables = $$('div.dropper');

    var container = $('containment');

    new Drag.Move('dragger', {'container': container, 'droppables': droppables});

    droppables.addEvent('over', function(){
    this.setStyle('background-color', '#000');
    });

    droppables.addEvent('leave', function(){
    this.setStyle('background-color', '#ff3300');
    });

    droppables.addEvent('drop', function(){
    this.setStyle('background-color', '#face8f');
    });

    "
    In this sample, the "droppables" are add 'drop' event and performs well. I tried this with the version 1.2 and just doesn't work.
    Did I misunderstand? Or missed somthing important?
  4. Troy


    quite a bit has changed with the 1.2 build, i would recommend starting from a basic build of the drag and drop example we have above, and then tweaking it to your needs from there.
  5. Patto


    Hey this collection is awsome!!
    I find it easy to follow, clear and logical. I've had some (unpleasant) experiences with learning JavaScript and specially trying to use the Mootools library, and you've achieved one of the finest tutorials i've seen around.
    Have you considered compiling it into .pdf or something printable? (once the 'month' is over, of course)
  6. Enqvist


    nice job guys. I love your tutorial and the layout and ui behaviour of your blog. thumbs up.
  7. Mazhar


    great work guys!


Leave a Reply