Resizeable DIVs (aka SplitPanes)
I've been using ruby-on-rails and script.aculo.us for a portal I've been writing but I needed the ability to resize the columns in the portal. Dojo has something that could do it, but I've no idea how to make that play nice with script.aculo.us and, anyway, the point of doing this sort of thing for fun is to learn, so I set out to do it myself. Below shows the result. In this case there happen to be three columns but there could be two or four or whatever.
This looks pretty garish - I’ve styled this example using CSS so that you can see what is happening.:
This is some wrapped text that will be in the left column.
This is some text that will be in the middle column.
This is some text that will be in the right column.
The basic concept is that each column has to be a div which is a child of the same parent div. This is the HTML for the above example:
<div id="parent">
<div id="lhs" class="column"><p class="content">
<span style="display: block; white-space: nowrap; overflow: hidden">This is some clipped text that will be in the left column.</span>
<span style="display: block">This is some wrapped text that will be in the left column.</span>
</p></div>
<div id="mid" class="column"><p class="content">This is some text that will be in the middle column.</p></div>
<div id="rhs" class="column"><p class="content">This is some text that will be in the right column.</p></div>
</div>
Then, you just create some instances of the JavaScript SplitPane class as follows:
<script language="JavaScript" type="text/JavaScript"><!--
new SplitPane("lhs", 33.3, "mid", 33.33, 33.3, { active: true });
new SplitPane("mid", 33.3, "rhs", 66.66, 33.3, { active: true }); //-->
</script>
This class creates another div with the class splitpane-divider and positions it half-way between the two columns. If you specify the active option it then wires it all up to events so that you can drag the divider around and the columns are resized as you do so.
Why is it optional to allow you to actually resize the columns? Well in my application, if the owner of a page is viewing the page then they can modify its appearance. If anyone else is viewing the page then they can't. So depending on who is viewing the page the splitpane is made active or it isn't.
The SplitPane class has a serialize method which can be used to post the changes to the column widths and positions to a server using AJAX - this is basically the same type of functionality that the script.aculo.us sortable class provides - it allows you to save changes to columns in a persistent store. This wouldn't be much use unless you could tell when a column was being resized, so you can pass in optional event handlerswhen you create an instance of a splitpane. Here's an example of some code that will do that:
<script language="JavaScript" type="text/JavaScript"><!--
function handleDragEnd(splitPane, event) {
new Ajax.Request(’/main/split’, {asynchronous:true, evalScripts:true, parameters:splitPane.serialize()});
}
new SplitPane(”lhs”, 33.33, “mid”, 33.33, 33.33, { onEnd: handleDragEnd, active: true });
new SplitPane(”mid”, 33.33, “rhs”, 66.66, 33.33, { onEnd: handleDragEnd, active: true }); //–>
</script>
The exact result you obtain depends to some extent on the CSS you use - in particular the column CSS. This is the CSS I used in the above example:
/* Elements with this class are generated by the JavaScript code */
/* Make the dividers visible for this demo */
.splitpane-divider {
border: 1px solid black;
background:#5B207B;
opacity: .5;
filter: alpha(opacity=50);
}
/* The classes/ids below are just used in this example. You can use whatever you like */
#parent {
width: 100%;
background: #eeeeee;
}
.column {
float: left; /* This is forces the page content to adjust to changes in height of the columns */
overflow: hidden; /* As a precaution, all content is clipped to the column width */
margin: 0; /* This and padding need to be zero */
padding: 0;
z-index: 1;
background:#E7FECD;
color: #666666;
width: 33%; /* Default value, overridden by class */
}
/* Any spacing must be on a child of the column, not the column itself */
.content {
border: 1px solid black;
margin: 5px;
padding: 5px;
}
Finally, you can browse the source in subversion here and read the naturaldocs documentation here.







August 27th, 2007 at 12:39 am
Hi,
I am not a programer and it is not very clear for me how to set the things to make an identical effect to the exemple above. However, i desperately need this piece of code to implement it in my company s intra net application.
I would like to know if it is possible for you to send me an html doc containing the code with all the settings to reproduce what you have done here. That would be very helpful for a me.
Thanxs
yaz
August 27th, 2007 at 10:16 am
or at least give me an exemple of what could be filled in the following par ot the code to make it work :
initialize: function(div1_id, div1_width, div2_id, div2_left, div2_width, options) {
this.options = {
onStart: Prototype.emptyFunction,
onDrag: Prototype.emptyFunction,
onEnd: Prototype.emptyFunction,
active: false
}
Object.extend(this.options, options || {});
this.div1 = $(div1_id);
this.div2 = $(div2_id);
this.container = this.div1.parentNode; // This had better be the same for both divs
this.div1_width = div1_width; // as a percentage
this.div2_left = div2_left; // as a percentage
this.div2_width = div2_width; // as a percentage
thanks
yaz
August 28th, 2007 at 6:56 am
You don’t fill in that part of the code. The article gives examples of what to do, plus you can look at the source to this page. I think you probably need some Javascript programming experience to be able to use this.
August 28th, 2007 at 12:27 pm
I think that i need to install the script.aculo.us library and other files coming in the zip on my site. I ll try that and if it works i ll leave the solution here
October 17th, 2007 at 3:10 am
Hello.
Big thanks for this script. But i have trouble in IE6 with start position anf height of dividers
They are not 100% height on load. In FF - ok.
October 17th, 2007 at 3:18 am
I’m use your “splitpane.js” with “layout_manager.js” from http://blog.xilinus.com/2007/10/3/simple-layout-manager-with-prototype-1-6
Look at my example: http://frogtail.ru/splitpanes/test.html
October 17th, 2007 at 8:04 am
It looks as though you are using some javascript to set the height of those divs. You probably need to call setDividerHeight() on each splitpane instance after the div heights have been set. You can use some code like the following:
for(i=0; i<SplitPane.cache.length; i++){ SplitPane.cache[i].setDividerHeight(); }October 18th, 2007 at 5:54 pm
=) Yeah) It works)
I removed “onload” methods from “layout_manager” and “splitpane” and merged in one.
Event.observe(window, “load”, function() {
layoutManager = new LayoutManager();
SplitPane.setAll();
})
Thanks…
December 5th, 2007 at 8:06 am
I’m using the 3 column layout above with the 2 dividers. Normally it works fine but I’ve added an FCKEditor in the 3rd column and this is causing a problem. When I move a divider (with an FCKEditor on its right side) to the right , the mouse usually ‘beats’ the divider and ends up going into the FCKEditor. The events are then consumed by FCKEditor and the divider stops working. So my question is: Is there a way to dynamically disable the FCKEditor (or any other javascript object) while moving the divider?
January 29th, 2008 at 4:41 am
Alex,
Did you ever resolve your problem with the FCKEditor? I’ve a similar issue with dragging and dropping into the editor. I half resolved it by modfying dragdrop.js to attach an extra mousemove event to the FCKEditor IFrame, but it’s still not perfect.
February 27th, 2008 at 9:15 am
Hi,
First of all I want to thank you for this api. We use it now in our project. But I made some changes because I had some bugs, and needed more features.
Bugfix: In firefox when scrollbar appears the divider isn’t reset correctly.
- Added an onmouse over and onmouse out effect.
- Added new options:
> div1MinWidth - The minimum width of the first div.
> div2MinWidth - The minimum width of the second div.
> dividerBlockedColor - Color of the divider when the div has reach his minimum width
> dividerHoverColor - Color to display on Mouse Over of the divider.
Here is an example of it http://www.mg-x.eu/javascript/splitpane/ and the api http://www.mg-x.eu/javascript/splitpane/splitpane-patched.js.
Let me know what you think about it
Ciao
February 27th, 2008 at 10:57 am
They look like good additions.
July 8th, 2008 at 12:33 pm
I just found this javascript while looking for the same functionality for a horizontal divider: i.e. I have a top and bottom div that I want to be able to resize with a divider. I wonder if this script can be easily modified (or a parameter passed in) to switch between vertical and horizontal division.
July 8th, 2008 at 8:56 pm
Well, it can certainly be modified. But I’m not sure about the ‘easy’ part - that would depend on how familiar you are with JavaScript/HTML/CSS