Mootools Expandable Columns
For a current project I am working on I needed an admin tool that consited of 3 columns with dynamic adjustable widths.
Suprisingly, I couldn’t find anything in google (using the mootools library) similar to what I needed so, always up for the challenge, I decided to code one myself.
In the hope that it might be useful to someone else, here is the code that I finally came up with.
See Demo
The result is a simple layout made up of absolutly positioned layers that uses Mootools to adjust the column widths at will.
The final code is actually suprisingly simple. Now, if I could just convert it into a class….
The html
<div id="col_wrapper"> <div id="col_1"> <div id="col_1_title"> <span id="col_1_msg"></span></div> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <div class="resize"></div> </div> <div id="col_2"> <div id="col_1_title"> <span id="col_2_msg"></span></div> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <div class="resize"></div> </div> <div id="col_3"> <div id="col_1_title"> <span id="col_3_msg"></span></div> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> </div> <div class="clear"></div> </div>
The CSS
#col_wrapper{
border:1px solid #0066cc;
position:relative;
min-height:300px;
}
.column {
position:relative;
min-height:300px;
}
#col_1 {
position:absolute;
top:0px;
left:0px;
width:200px;
background:#ECECEC;
}
#col_2 {
position:absolute;
top:0px;
left:200px;
width:558px;
border-right:1px dotted #0066cc;
border-left:1px dotted #0066cc;
background:#EEEEEE;
}
#col_3 {
position:absolute;
top:0px;
left:760px;
width: 200px;
background:#EDEDED;
}
.column .col_title{
padding:4px;
background:#0066cc;
border-bottom:1px solid #FFF;
color:#FFF;
}
.column .col_msg{
float:right;
font-size:90%;
color:#FFF;
}
.resize {
position: absolute;
top: 26px;
right: -3px;
height: 30px;
width: 3px;
background: #666 url("images/handle.gif");
cursor: col-resize;
z-index:200;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border: 1px solid #666;
}
The Javascript (mootools)
window.addEvent('domready', function() {
// define column elemnts
var col_wrap = $('col_wrapper'); // define the column wrapper so as to be able to get the total width via mootools
var col_left = $('col_1');
var col_center = $('col_2');
var col_right = $('col_3');
// define padding (seperator line widths) for column borders as defined in css
var pad = 1;
// define snap if required - set to 0 for no snap
var w_snap = 5;
var w_total = col_wrap.getWidth()-(pad*2); // total width of wrapper
var w_min = 120; // minimum width for columns
var w_min_c = w_min-(2*pad);
// define message output elements (not essential to script)
var col_1_msg = $("col_1_msg");
var col_2_msg = $("col_2_msg");
var col_3_msg = $("col_3_msg");
//show column start widths in col headers (just for show)
col_1_msg.innerHTML = col_left.getWidth()+"px";
col_2_msg.innerHTML = col_center.getWidth()+"px";
col_3_msg.innerHTML = col_right.getWidth()+"px";
// left column - affects center column position and width
col_left.makeResizable({
handle: col_left.getChildren('.resize'),
grid: w_snap,
modifiers: {x: 'width', y: false},
limit: {x: [w_min,null]},
onStart:function(el){
// get available width - total width minus right column - minimum col with
w_avail=(w_total-col_right.getWidth())-w_min;
},
onDrag: function(el) {
if(el.getWidth()>=w_avail){
// max width reached - stop drag (force max widths)
el.setStyle("width",w_avail);
}
// set center col left position
col_center.setStyle("left",col_left.getWidth());
// define and set center col width (total minus left minus right)
w_center=w_total-col_left.getWidth()-col_right.getWidth();
col_center.setStyle("width",w_center.toInt()-(pad*2));
// messages
col_1_msg.innerHTML=" "+col_left.getWidth()+"px";
col_2_msg.innerHTML=" "+col_center.getWidth()+"px";
col_3_msg.innerHTML=" "+col_right.getWidth()+"px";
},
onComplete: function() {
//could add final width to form field here
}
});
// mootools can't resize to the left so we have to resize the center column rather than the right-hand column
col_center.makeResizable({
handle: col_center.getChildren('.resize'),
grid: w_snap,
modifiers: {x: 'width', y: false},
limit: {x: [w_min_c,null]},
onStart:function(el){
// get start width so as to be able to adjust center column width
w_start=el.getWidth();
// get available width - total width minus left column - minimum col with
w_avail=w_total-col_left.getWidth()-w_min-(pad*2);
},
onDrag: function(el) {
if(el.getWidth()>=w_avail){
// max width reached - stop drag (force max widths)
el.setStyle("width",w_avail);
}else if(el.getWidth()==w_min_c){
// ensure that right col has complete available width
el.setStyle("width",w_min_c);
}
// define new left position
l_new = col_left.getWidth()+col_center.getWidth(); // force left space for right col
col_right.setStyle("left",l_new.toInt());
// define and set right column width - will always be result of left and center columns
w_new = w_total-col_left.getWidth()-col_center.getWidth();
col_right.setStyle("width",w_new.toInt());
// show messages
col_1_msg.innerHTML=" "+col_left.getWidth()+"px";
col_2_msg.innerHTML=" "+col_center.getWidth()+"px";
col_3_msg.innerHTML=" "+col_right.getWidth()+"px";
},
onComplete: function() {
//could add final width to form field here
}
});
});

Hei very smooth effect, nice one. Cool blog and i like your choice for mootools, its awesome!
Have fun!
Thanks, just starting out with this blog so let’s see how it goes!
I really like mootools too, my only “but” being the lack of documentation.
Very cool. I love mootools, unfortunately my work is centered around drupal which ships with jquery in the core so I am forced to deal with jquery…
Thanks, I am sure that this could be ported to jquery without too much trouble.
It really is just a small part of a larger tool that I am creating but I thought that I would share it as I have found nothing similar that has been published.
Really Good Startup, Keep up the Good Work and bring new ideas from Mootools, i am also one of the mootools lover. And i used this idea in my .NET application. Thank you
Great, I am glad that you liked at and that it has been useful to you 🙂
Great !
But could be nicer in a class with the columns names as options on startup.
Let me know if you plan to make it more flexible !
Hi,
Changing the column names is simple – you just need to change these lines:
var col_left = $('col_1');var col_center = $('col_2');
var col_right = $('col_3');
That said, I would love to be able to make it into a class but classes is not something I am very good at.
If any one fancies giving me a hand to make a class out of it…..
Chris
Hi there,
I was just wondering if it’s possible to apply the effect to s with the same id?
For example:
window.addEvent('domready', function(){
$('blogContent').makeResizable({modifiers: {x: false, y: 'height'},limit: {y: [150, 'height']}});
});
...
Some text.
Some text.
Some text.
When tried, only the first div will be resizable; any ideas?
cheers,
Dan
Wow, this effect is awesome!
Very useful for interface design. Big THX!
Great that is what I am looking for. Are you planing to improve it more?