Deal of the Day

Home » Main » Manning Forums » 2005 » Ajax in Action

Thread: Changing width of page sections with mouse drag (non-frame solution)

Reply to this Thread Reply to this Thread Search Forum Search Forum Back to Thread List Back to Thread List

Permlink Replies: 5 - Pages: 1 - Last Post: Mar 30, 2006 1:22 PM by: Pascarello
DGadd

Posts: 24
From: Vancouver, BC
Registered: 3/16/06
Changing width of page sections with mouse drag (non-frame solution)
Posted: Mar 23, 2006 7:54 PM
  Click to reply to this thread Reply

I am wanting to create a page without frames that nevertheless has a frame-like behaviour: that content stored in different sections of the page can be made wider or narrower using a mouse drag action.

A good example of what I mean is the columns in a9.com: once the columns are loaded, they can have their width resized via a mouse drag.

In looking at their javascript, it appears that they are using table columns and providing code to respond to the mouse down, move and up events, but the amount of code they are using to achieve this is massive and of course, proprietary.

I'm wondering if anyone has seen a simple or "standard" Ajax example for changing the width of page areas (whether table columns, divs, or other document element.)

(I am referring to fixed areas, not the moveable subwindows as shown in the Ajax in Action portal example in chapter 11.)

Thanks,

David

DGadd

Posts: 24
From: Vancouver, BC
Registered: 3/16/06
Re: Changing width of page sections with mouse drag (non-frame solution)
Posted: Mar 28, 2006 5:05 PM   in response to: DGadd in response to: DGadd
  Click to reply to this thread Reply

removed as I've made a properly formatted version below...

Message was edited by: David Gadd
DGadd

DGadd

Posts: 24
From: Vancouver, BC
Registered: 3/16/06
Re: Changing width of page sections with mouse drag (non-frame solution)
Posted: Mar 28, 2006 5:23 PM   in response to: DGadd in response to: DGadd
  Click to reply to this thread Reply

Removed as I've gotten a properly edited version below.

Message was edited by:
DGadd

DGadd

Posts: 24
From: Vancouver, BC
Registered: 3/16/06
Re: Changing width of page sections with mouse drag (non-frame solution)
Posted: Mar 28, 2006 7:46 PM   in response to: DGadd in response to: DGadd
  Click to reply to this thread Reply

I've managed to make a solution to the problem described above. I have tested this in both IE and Firefox and it works correctly.

This solution uses div tags to created major pages sections, and traps mouse events to allow the columns to be dragged.

You can also reformat the height, width etc by adjusting the constants columns DIRECTLY ABOVE the html section at the bottom of this sample.

Thanks to a Feb 2004 sample by Eric Gunnerson found while googling last week that assisted me with the concept of event-trapping divs (from a javascript-based spreadsheet example). About 20%-30% of the code below, while refactored, has its source in Eric's spreadsheet sample. Thanks again.

David Gadd

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<html>
<head>
<title> Dynamic Table </title>
<style type="text/css">
#DragColumn_0
{
     position:relative;
     z-index:5;
}

#ContentColumn_1
{
     border: 1px solid #006699;
     position:absolute;
     overflow:hidden;
     z-index:10
}

#DragColumn_1
{
     position:absolute;
     cursor:e-resize;
     z-index:11;
}

#ContentColumn_2
{
     border: 1px solid #006699;
     position:absolute;
     overflow:hidden;
     z-index:10
}

#DragColumn_2
{
     position:absolute;
     cursor:e-resize;
     z-index:11;
}

#ContentColumn_3
{
     border: 1px solid #006699;
     position:absolute;
     overflow:hidden;
     z-index:10
}

#DragColumn_3
{
     position:absolute;     
     cursor:e-resize;
     z-index:11;
}
</style>

<script type="text/javascript">

window.onload = function()
{
     PageSetup();
}


// global constants
var ZERO_AMOUNT = 0;
var ONE_MILLISECOND = 1;
var SIX_MILLISECONDS = 6;

// global variables
var _xMousePosition = 0;
var _yMousePosition = 0;
var _mouseButtonDown = false;


// event handlers
function MouseMoveHandler(event) {
     var e = event || window.event;
     _xMousePosition = e.clientX + document.body.scrollLeft;
     _yMousePosition = e.clientY + document.body.scrollTop;
}

function MouseDownHandler(event) {
     var e = event || window.event;     
     var elementID = e.srcElement ? e.srcElement.id : e.target.id;
     var columnIndexValue = elementID.slice(elementID.length-1, elementID.length);
     _mouseButtonDown=true;
     ChangeColumnWidth(columnIndexValue);
}     

function MouseUpHandler(event){
     var e = event || window.event;
     _mouseButtonDown = false;
     var cursorResetFunctionCall = 'document.body.style.cursor = ""';
     window.setTimeout(cursorResetFunctionCall, SIX_MILLISECONDS);
}

function PageSetup()
{
     document.onmousemove = MouseMoveHandler;
     document.onmouseup = MouseUpHandler;
     
     var drag0 = document.getElementById("DragColumn_0");
     var drag1 = document.getElementById("DragColumn_1");
     var drag2 = document.getElementById("DragColumn_2");
     var drag3 = document.getElementById("DragColumn_3");
     var column1 = document.getElementById("ContentColumn_1");
     var column2 = document.getElementById("ContentColumn_2");
     var column3 = document.getElementById("ContentColumn_3");
     var colWidth1 = _columnWidthSettings[1];
     var colWidth2 = _columnWidthSettings[2];
     var colWidth3 = _columnWidthSettings[3];
     
     drag0.style.left = TABLE_LEFT + "px";
     drag0.style.top = TABLE_TOP + "px";
     drag0.style.height = TABLE_HEIGHT + "px";

     column1.style.left = TABLE_LEFT + "px";
     column1.style.width = colWidth1 + "px";
     column1.style.top = TABLE_TOP + "px";
     column1.style.height = TABLE_HEIGHT + "px";

     drag1.style.left = (TABLE_LEFT + colWidth1) + "px";
     drag1.style.width = DRAG_WIDTH + "px";
     drag1.style.top = TABLE_TOP + "px";
     drag1.style.height = TABLE_HEIGHT + "px";
     drag1.onmousedown=MouseDownHandler;
     
     column2.style.left = (TABLE_LEFT + colWidth1 + DRAG_WIDTH) + "px";
     column2.style.width = colWidth2 + "px";
     column2.style.top = TABLE_TOP + "px";
     column2.style.height = TABLE_HEIGHT + "px";

     drag2.style.left = (TABLE_LEFT + colWidth1 + DRAG_WIDTH + colWidth2) + "px";
     drag2.style.width = DRAG_WIDTH + "px";
     drag2.style.top = TABLE_TOP + "px";
     drag2.style.height = TABLE_HEIGHT + "px";
     drag2.onmousedown=MouseDownHandler;

     column3.style.left = (TABLE_LEFT + colWidth1 + DRAG_WIDTH + colWidth2 + DRAG_WIDTH) + "px";
     column3.style.width = colWidth3 + "px";
     column3.style.top = TABLE_TOP + "px";
     column3.style.height = TABLE_HEIGHT + "px";

     drag3.style.left = (TABLE_LEFT + colWidth1 + DRAG_WIDTH + colWidth2 + DRAG_WIDTH + colWidth3) + "px";
     drag3.style.width = DRAG_WIDTH + "px";
     drag3.style.top = TABLE_TOP + "px";
     drag3.style.height = TABLE_HEIGHT + "px";
     drag3.onmousedown=MouseDownHandler;
}



function ChangeColumnWidth(columnIndexValue){
     //alert("You reached to the top of the ChangeColumnWidth method!");
     var columnIndex = parseInt(columnIndexValue);

     if(columnIndex >= 0){
          document.body.style.cursor = "e-resize";

          var previousDragColumn = document.getElementById("DragColumn_" + (columnIndex-1));
          var currentDragColumn = document.getElementById("DragColumn_" + columnIndex);
          var currentContentColumn = document.getElementById("ContentColumn_" + columnIndex);
     
          var leftString = previousDragColumn.style["left"] ? previousDragColumn.style["left"]:previousDragColumn.currentStyle["left"];

          var previousDragLeftColumnPosition = parseInt(leftString.slice(0,leftString.length-2));
          var previousDragRightColumnPosition;
          if(columnIndex > 1)
          {
               previousDragRightColumnPosition = previousDragLeftColumnPosition + DRAG_WIDTH;
          }
          else
          {
               previousDragRightColumnPosition = previousDragLeftColumnPosition;
          }

          var distanceFromMouseToPreviousColumn = _xMousePosition - (previousDragRightColumnPosition);
          var dragColumnLeftPosition = 0;

          if(distanceFromMouseToPreviousColumn < MINIMUM_ALLOWED_WIDTH)
          {
               _columnWidthSettings[columnIndex] = MINIMUM_ALLOWED_WIDTH;
               dragColumnLeftPosition = previousDragLeftColumnPosition + MINIMUM_ALLOWED_WIDTH;
          }
          else
          {
               _columnWidthSettings[columnIndex] = distanceFromMouseToPreviousColumn;
               dragColumnLeftPosition = _xMousePosition;
          }

          currentContentColumn.style.width = (_columnWidthSettings[columnIndex]) + "px";
          currentDragColumn.style.left = dragColumnLeftPosition + "px";
          currentDragColumn.style.width = DRAG_WIDTH + "px";

     
          for(iteration=(columnIndex+1); iteration<_columnWidthSettings.length; iteration++)
          {
               var nextDragColumn = document.getElementById("DragColumn_" + iteration);
               var nextContentColumn = document.getElementById("ContentColumn_" + iteration);
          
               nextContentColumn.style.left = (dragColumnLeftPosition + DRAG_WIDTH) + "px";
               nextContentColumn.style.width = _columnWidthSettings[iteration] + "px";
               nextDragColumn.style.left = (dragColumnLeftPosition + DRAG_WIDTH + _columnWidthSettings[iteration]) + "px";
               nextDragColumn.style.width = DRAG_WIDTH + "px";
     
               dragColumnLeftPosition += DRAG_WIDTH + _columnWidthSettings[iteration];
          }

     }

     var recursiveFunctionCall = "ChangeColumnWidth('"+columnIndex+"')";

     if(_mouseButtonDown)
     {
          window.setTimeout(recursiveFunctionCall, ONE_MILLISECOND);
     }
}


// CUSTOMIZABLE LAYOUT SETTINGS - FEEL FREE TO MODIFY THESE.
var MINIMUM_ALLOWED_WIDTH = 30;
var MINIMUM_ALLOWED_HEIGHT = 30;
var TABLE_LEFT = 25;
var TABLE_TOP = 25;
var TABLE_HEIGHT = 500;
var DRAG_WIDTH = 10;
var _columnWidthSettings = new Array(0,200,300,200);
</script>
</head>


<body>

<div id="DragColumn_0"></div>
<div id="ContentColumn_1"></div>
<div id="DragColumn_1"></div>
<div id="ContentColumn_2"></div>
<div id="DragColumn_2"></div>
<div id="ContentColumn_3"></div>
<div id="DragColumn_3"></div>

</body>
</html>

Message was edited by: David Gadd
DGadd

michael_hodgins

Posts: 9
From: Lancashire, UK
Registered: 11/4/05
Re: Changing width of page sections with mouse drag (non-frame solution)
Posted: Mar 30, 2006 1:18 PM   in response to: DGadd in response to: DGadd
  Click to reply to this thread Reply

Hi David

That's really good. It works well in Opera too.

I wonder what the current thoughts are about putting the JavaScript inside comments, like this

<script type="text/javascript">
<!--
...
//-->
</scipt>

I've always done this from way back when I first learnt JavaScript but I notice that you haven't. I know that the w3 validator can fail on JavaScript that isn't commented out in a xhtml document.


Michael

Pascarello

Posts: 208
From: Laurel, Maryland, USA
Registered: 5/2/05
Re: Changing width of page sections with mouse drag (non-frame solution)
Posted: Mar 30, 2006 1:22 PM   in response to: michael_hodgins in response to: michael_hodgins
  Click to reply to this thread Reply

The comments were to keep a browser that did not support JavaScript from displaying it.

Not really required, but a nice to have.

For the script. I always meant to refactor my "excel like table" script it into an oo script, but never had time.

Eric

Legend
Gold: 300 + pts
Silver: 100 - 299 pts
Bronze: 25 - 99 pts
Manning Author
Manning Staff