Creating a dragable, dropable, resizbleable div in javascript using MooTools

Warning:This code and post is extensively commented and very descriptive. It’s geared towards newer JS programmers to help them grasp the concepts.
If you know what you’re doing just Download Drag / Drop / Resize Source

An implementation can be found at http://olarchitect.com and the source is available at

http://olarchitect.com/scripts/dragdrop.js

There are many ways to create moveable, resizable, dragable, dropable, etc.able divs / boxes in javascript.   For OpenLayers Architect, I want to create multiple draggable and resizeable divs. Normally, this would be very easy to do, but there are a few extra requirements I have that aren’t widely used.

The problem I had is that I want the draggable / resizeable div to be inside an element and restricted to that element’s extent.  Therefore, the resize limit is based off the position of the draggable div, and the drag limit is based off the variable width / height.  MooTools makes it very easy to apply limits to a draggable div and resize limits, but not a combination of both by default.  The easy fix is to use a variable for the limits of both the draggable and resizable elements.

Here’s the code to limit a draggable and resizble div to an element called “mapContainer.”  You can easily change this to specify fixed width / height values.
What happens is basically this
-Whenever the element is dragged, change two variables called dragLimitMaxX and dragLimitMaxY. These values are based on the container element’s width minus the draggable element’s width, the same goes for the height.
-Resizing works similarly, except the values are calculated from the container element’s width minus the resizeable element’s left position.
-My draggable element is a div called “draggableDivContainer”
-the drag handle is a div within the container called “draggableDiv”, and the resize handler is a div within the container called “draggableDivResize”

Download Drag / Drop / Resize Source

/*global dragLimits*/
var dragLimitMaxX;
var dragLimitMaxY;

/*global resizeLimits*/
var reSizeLimitMaxX;
var reSizeLimitMaxY;

window.addEvent(‘domready’, function(){
/*If we wanted to confine the limits to a certain width or height, we would just specify the values instead of getting the style. i.e. elWidth = 200
get element styles – use mootools to get the style, otherwise we’d have to use something like .offsetWidth – borderWidth which isn’t as pretty*/

var elWidth = parseInt($(‘mapContainer’).getStyle(‘width’));
var elHeight = parseInt($(‘mapContainer’).getStyle(‘height’));

/*create the draggable box*/
var myDrag = new Drag(‘draggableDivContainer’, {
snap: 5, //Must move box 5 pixels before the actual box starts moving
handle: ‘draggableDiv’, //The div “draggableDiv” is the div that you move the mouse over to drag
limit: { x:[0,elWidth], y:[0,elHeight]},
onSnap: function(el){
el.addClass(‘dragging’);
},
onDrag: function(el){
/*OLD, BUSTED WAY
if(parseInt(this.element.style.left) + parseInt(this.element.style.width) > 619)
this.stop();*/

/*”this” is the element that is being dragged*/
dragLimitMaxX = elWidth – parseInt(this.element.getStyle(‘width’)); //use parseInt to get the integer value – otherwise we would get a value with “px” appended – i.e. 500px
dragLimitMaxY = elHeight – parseInt(this.element.getStyle(‘height’));
/*We could also use this.element.style.width or .height, but we’d have to declare in first to make sure the values weren’t empty (or use something like offsetWidth), but as we’re using MooTools we can just use .getStyle(‘property’);*/

/*set the limit to the variable set above*/
this.limit = { x:[0, dragLimitMaxX], y:[0,dragLimitMaxY] };
},
onComplete: function(el){
el.removeClass(‘dragging’);
}
});

/*Make the resizeable div. In this case, there’s a small div in the bottom righthand corner that will resize the entire div*/
var myResize = $(‘draggableDivContainer’).makeResizable({
handle:’draggableDivResize’,
/*set the min x and y limit so the drag handler is still visible*/
limit: { x:[45, elWidth], y:[20,elHeight]},
onDrag: function(el){

reSizeLimitMaxX = elWidth – parseInt(this.element.getStyle(‘left’));
reSizeLimitMaxY = elHeight – parseInt(this.element.getStyle(‘top’));
this.limit = { x:[45, reSizeLimitMaxX], y:[20,reSizeLimitMaxY] };
},
onComplete: function(){
}
});
});

I’ll cover all the major concepts here, but the code itself should be well commented enough to give you an idea of how to tailor this to your own project.

The first thing we do is set up some empty global variables that we’ll use in the code later (using globals may not be the best way to accomplish this, but . By default, the limits for both the drag and resize are equal to the element’s width / height. If you wanted to use certain values instead of an element’s values, you could specify it here.

window.addEvent('domready', function(){
We’ll set up the drag elements when the document is finished loading.

We’ll create the drag element and configure the draggable box options. The limit would be set here by default, but for our purposes we’ll be using a limit that gets set whenever the element is dragged. I admit this is not the most efficient way to do it, but it’s the best way I found that keeps the dragging and resizing smooth.
At first I tried to use a conditional statement and call the stop() function which did stop the dragging and resizing, but the problem with it is that it released the event. Basically, if you dragged an element outside the extent, the element would stop at the extent and it would be “released” – you would have to click on it again to drag it again. Setting the limit, however, allows us to drag the element to the extent but doesn’t “release” the element so we don’t have to click on it again if we wanted to drag it somewhere else within the limits. The same situation is true for resizing.

dragLimitMaxX = elWidth - parseInt(this.element.getStyle('width'))
If we didn’t resize the element, we could just set the Max X limit (how far to the right it can be dragged) to a constant number, i.e. 500. We could only drag the element 500px to the right before we can drag it no more. However, we also want to be able to resize the div. Therefore, we have a variable width of the draggable div element so we must account for it. The simple way to achieve this is to use the container’s width (or the constant number in this example, 500) minus the draggable div’s width. The div’s actual position is irrelevant, it’s only size that matters. Therefore, if the width of the div was 200 and we used the constant 500, the new MaxX limit is 300. Therefore, the element can only be dragged 300px before it would stop – before it would reach the extent of the container div’s width (or the number 500). The same goes for the height.

reSizeLimitMaxX = elWidth - parseInt(this.element.getStyle('left'));
The resize limit works similar to the drag limit. However, we’ll be using the position instead of the width. If the div didn’t have to be resized, we could just use a constant number for the limit. However, as we won’t know where the div is located we must account for it’s position. We do this by using the container element’s width (for example, 500) minus the draggable div’s position (by getting the “left” style property. This tells us how far, in pixels, from the left an element is. for example
0____10
| X |
|_____| in this horrible ascii art, if X is the draggable element, and the box it is inside represents the container div with a width of 10, the 0 in this picture would be the default left value, and in this example X would have a left value of about 5 – it’s about halfway in the middle of the container)
Therefore, the maximum X limit the draggable element can be resized to is equal to the container width minus the element’s left position. Going back to the ascii “art”, if X has a left value of 5, the maximum amount you could resize it would be 5 pixels (the container width ( 10 ) – the element’s left value ( 5 ) = ( 5 ) ). If the left position of X was 0, the max limit would be 10 ( 10 – 0 ).
The Y limit is similar, but uses the “top” css property.

Download Drag / Drop / Resize Source

You can leave a response, or trackback from your own site.
7 Responses to “Creating a dragable, dropable, resizbleable div in javascript using MooTools”
  1. Someone says:

    Good article, and maybe I’m blind, but it would have been nice to see a demo before the article. :)

  2. Erik says:

    You’re right, I’m really absent minded at times :X. The implementation can be found at http://olarchitect.com
    -Create a control such as overview map to see it in action
    http://olarchitect.com/scripts/dragdrop.js has the full source. Next time I’ll create an implementation specifically for the blog.

  3. gary says:

    Is it possible to use this with a little more explaination and no javascript experience; Like what goes in the and what goes in the <div ?

    Thank you for your time,
    Gary

  4. Erik says:

    Hey Gary. Sorry the post is a bit convoluted and not very explanatory. You can copy the javascript code and paste it at the bottom of the page you want the draggable divs to be on. To make a div draggable, first create a div with and give it an ID (can be whatever you want, ex. id=’draggableDiv’) I believe in this post’s example I had a mapContainer and a draggableDivContainer – the latter was nested inside the map container ( i.e.

    )
    You can follow the same structure and just replace in the javascript code occurances of $(‘mapContainer’) with the ID of your first container div and $(‘draggableDivContainer’) with the actual div ID that you want to be dragged.
    Sorry if that’s a bit verbose and only made things worse – I haven’t looked at this post’s code in a year or so. I’d be happy to help you if I can clear anything up for you

  5. gary says:

    No luck yet. Can you email or do you have a post anywhere on an empty webpage, only what is required to demonstrate and example this?
    Thank you, gary@garyfernandes.com

  6. Erik says:

    Sorry I don’t really have any examples =( The only instance of this code being used is at http://olarchitect.com

    Next week I will most likely have time to explain it more thoroughly and create an example page with this code alone. I’ll send you an email when I make a new post about it.

  7. Serge says:

    Thanks a lot! I can’t find this decision for a long time and have big troubles with making div both resizable and draggable. That is decision and works well. Thanks again!

Leave a Reply

Subscribe to RSS Feed My tweets