You need to set up the menu from Wordpress admin.
Jul 24, 2009

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.

Expandable ColumnsSuprisingly, 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">&nbsp;<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">&nbsp;<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">&nbsp;<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
 }

 });
 });

11 Comments

  • 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?

Leave a comment