How To: Prototype Resize Handle

This is just a short post to share some JavaScript that I wrote to be able to add a drag corner to an html element to make it resizable.

I did this using prototype.js. As an example the two divs below have been made resizable. (Go ahead. Drag the bottom right corner around.)

Div One
 

Div Two
 

And below is the code that makes it possible. If you take a look at it and read the comments, You'll see that it's actually pretty simple. The thing that had me stuck for a while was asking Prototype how tall or wide something is isn't the whole story. Border and padding add to width and height. I have some code in there that will compensate for that. However, I only covered situations where the border/passing were uniform all the way around. Anyway, love to hear what you think about this.

<div id="SomeDiv" style="position: relative; width: 200px; height:100px; border: 2px solid black; padding: 3px;">
   Div One
   <div class="corner" id="DragHandle">&nbsp;</div>
</div>

<div id="DivTwo" style="position:relative; width:150px; height:75px; border:1px dashed red;">
   Div Two
   <div class="corner" id="DragHandleTwo">&nbsp;</div>
</div>

<script type="text/javascript" language="javascript">

   function DragCorner(container, handle) {
      var container = $(container);
      var handle = $(handle);
      
      /* Add property to container to store position variables */
      container.moveposition = {x:0, y:0};
      
      function moveListener(event) {
         /* Calculate how far the mouse moved */
         var moved = {
                     x:(event.pointerX() - container.moveposition.x),
                     y:(event.pointerY() - container.moveposition.y)
                  };
         /* Reset container's x/y utility property */
         container.moveposition = {x:event.pointerX(), y:event.pointerY()};
         /* Border adds to dimensions */
         var borderStyle = container.getStyle('border-width');
         var borderSize = borderStyle.split(' ')[0].replace(/[^0-9]/g,'');
         /* Padding adds to dimensions */
         var paddingStyle = container.getStyle('padding');
         var paddingSize = paddingStyle.split(' ')[0].replace(/[^0-9]/g,'');
         /* Add things up that change dimensions */
         var sizeAdjust = (borderSize*2) + (paddingSize*2);
         /* Update container's size */
         var size = container.getDimensions();
         container.setStyle({
               height: size.height+moved.y-sizeAdjust+'px',
               width:size.width+moved.x-sizeAdjust+'px'
            });
      }
      
      /* Listen for 'mouse down' on handle to start the move listener */
      handle.observe('mousedown', function(event) {
         /* Set starting x/y */
         container.moveposition = {x:event.pointerX(),y:event.pointerY()};
         /* Start listening for mouse move on body */
         Event.observe(document.body,'mousemove',moveListener);
      });
      
      /* Listen for 'mouse up' to cancel 'move' listener */
      Event.observe(document.body,'mouseup', function(event) {
         Event.stopObserving(document.body,'mousemove',moveListener);
      });
   }
   
   DragCorner('SomeDiv','DragHandle');
   
   DragCorner('DivTwo','DragHandleTwo');
   
</script>

Comments
Jamie Krug's Gravatar @Chris, looks great. Did you also check out the <a href="http://docs.jquery.com/UI/API/1.7/Resizable">jQuery UI's Resizable</a>? You've gotta like doing it with one line of JavaScript :)

$("any_selector").resizable();

There are tons of other customizations available, but the basics are nice and simple. Just thought I'd throw it out there.
# Posted By Jamie Krug | 3/2/09 7:19 AM
Chris Phillips's Gravatar @Jamie, that jQuery method works really slick. I bet they already did a way better job than I ever will with all the math to make it work correctly with different properties in different browsers. But, we use, prototype and scriptaculous at work. And I didn't see a "Resizable" method for those. So, I just did it really quick for a fun experiment.
# Posted By Chris Phillips | 3/2/09 10:45 AM
Lemmi's Gravatar Great Idea. Why don't you create in a class like for example scriptaculous? Although great work!
# Posted By Lemmi | 7/14/09 4:29 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.6.002.