Unobtrusive table column resize with jquery

With this piece of code, simple add the class  ‘resizabletable’ to your table and the columns can be easily resized by drag and drop!

I was inspired by the flexigrid, but wanted a simpler solution. This one also nicely integrates into Wicket DataTable, for example.

Update: fixed the multi table on a page bug, kindly pointed out by Nick (see comments)

To see it working: http://www.audenaerde.org/example.html

<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript"
        src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript"
        src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.js"></script>
    <script type="text/javascript">
    function resetTableSizes (table, change, columnIndex)
    {
        //calculate new width;
        var tableId = table.attr('id');
        var myWidth = $('#'+tableId+' TR TH').get(columnIndex).offsetWidth;
        var newWidth = (myWidth+change)+'px';

        $('#'+tableId+' TR').each(function()
        {
            $(this).find('TD').eq(columnIndex).css('width',newWidth);
            $(this).find('TH').eq(columnIndex).css('width',newWidth);
        });
        resetSliderPositions(table);
    };

    function resetSliderPositions(table)
    {
        var tableId = table.attr('id');
        //put all sliders on the correct position
        table.find(' TR:first TH').each(function(index)
        {
            var td = $(this);
            var newSliderPosition = td.offset().left+td.outerWidth() ;
            $("#"+tableId+"_id"+(index+1)).css({  left:   newSliderPosition , height: table.height() + 'px'}  );
        });
    }

    function makeResizable(table)
    {        
        //get number of columns
        var numberOfColumns = table.find('TR:first TH').size();

        //id is needed to create id's for the draghandles
        var tableId = table.attr('id');
        for (var i=0; i<=numberOfColumns; i++)
        {
            //enjoy this nice chain :)
            $('<div id="'+tableId+'_id'+i+'"></div>').insertBefore(table).data('tableid', tableId).data('myindex',i).draggable(
            { axis: "x",
              start: function () 
              {
                var tableId = ($(this).data('tableid'));
                $(this).toggleClass( "dragged" );
                //set the height of the draghandle to the current height of the table, to get the vertical ruler
                $(this).css({ height: $('#'+tableId).height() + 'px'} );
              },
              stop: function (event, ui) 
              {
                var tableId = ($(this).data('tableid'));
                $( this ).toggleClass( "dragged" ); 
                var oldPos  = ($( this ).data("draggable").originalPosition.left);
                var newPos = ui.position.left;
                var index =  $(this).data("myindex");
                resetTableSizes($('#'+tableId), newPos-oldPos, index-1);
              }          
            }
            );;
        };

        resetSliderPositions(table);

    }
    $(document).ready(function()
    {
        $(".resizabletable").each(function(index)
        {
            makeResizable($(this));
        });

    });

    </script>
    <style>
        .draghandle.dragged
        {
            border-left: 1px solid #333;
        }

        .draghandle
        {
            position: absolute;
            z-index:5;
            width:5px;
            cursor:e-resize;
        }
        TH
        {
            border-left: 1px solid #333;
            border-bottom: 1px solid #333;
        }
    </style>
</head>
<body>
<div id="container" style="border: 1px solid blue;">
    <table id="mytable" style="width:100%; border: 1px solid red;" border="0" cellspacing="0" cellpadding="0" >
    <thead>
        <tr>
            <th style="">Dit is een interessante zin!</th>
            <th style="">b</th>
            <th style="">b</th>
            <th style="">b</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td style="">Dit is een interessante zin!</td>
            <td style="">b</td>
            <td style="">b</td>
            <td style="">b</td>
        </tr>
        <tr>
            <td style="">b</td>
            <td style="">a</td>
            <td style="">b</td>
            <td style="">b</td>
            </tr>
        <tr>
            <td style="">b</td>
            <td style="">a</td>
            <td style="">b</td>
            <td style="">b</td>
        </tr>
    </tbody>
    </table>
</div>
</body>
</html>

Enjoy :)
About these ads

22 Responses to “Unobtrusive table column resize with jquery”

  1. deepx Says:

    Hey there awesome code, ive been sitting here for a while trying to get it to work on a simple html table

    Any idea what im doing wrong?

    /**
    * Author: Rob Audenaerde
    */
    function resetTableSizes (table, change, columnIndex)
    {
    alert(‘resize’);

    //calculate new width;
    var tableId = table.attr(‘id’);
    var myWidth = $(‘#’+tableId+’ TR TH’).get(columnIndex).offsetWidth;
    var newWidth = (myWidth+change)+’px’;

    $(‘#’+tableId+’ TR’).each(function()
    {
    $(this).find(‘TD’).eq(columnIndex).css(‘width’,newWidth);
    $(this).find(‘TH’).eq(columnIndex).css(‘width’,newWidth);
    });
    resetSliderPositions(table);
    };

    function resetSliderPositions(table)
    {
    var tableId = table.attr(‘id’);
    //put all sliders on the correct position
    table.find(‘ TR:first TH’).each(function(index)
    {
    var td = $(this);
    var newSliderPosition = td.offset().left+td.outerWidth() ;
    $(“#”+tableId+”_id”+(index+1)).css({ left: newSliderPosition , height: table.height() + ‘px’} );
    });
    }

    function makeResizable(table)
    {
    //get number of columns
    var numberOfColumns = table.find(‘TR:first TH’).size();

    //id is needed to create id’s for the draghandles
    var tableId = table.attr(‘id’);

    for (var i=0; i<=numberOfColumns; i++)
    {

    //enjoy this nice chain :)
    $('’).insertBefore(table).data(‘tableid’, tableId).draggable(
    { axis: “x”,
    start: function ()
    {
    var tableId = ($(this).data(‘tableid’));
    $(this).toggleClass( “dragged” );

    //set the height of the draghandle to the current height of the table, to get the vertical ruler
    $(this).css({ height: $(‘#’+tableId).height() + ‘px’} );
    },
    stop: function (event, ui)
    {
    var tableId = ($(this).data(‘tableid’));
    $( this ).toggleClass( “dragged” );
    var oldPos = ($( this ).data(“draggable”).originalPosition.left);
    var newPos = ui.position.left;
    var index = $(‘.draghandle’).index(this);

    resetTableSizes($(‘#’+tableId), newPos-oldPos, index-1);
    }
    }
    );
    };

    resetSliderPositions(table);

    }
    $(document).ready(function()
    {
    $(“.resizabletable”).each(function(index)
    {

    makeResizable($(this));
    });

    });

    .draghandle.dragged
    {
    border-left: 1px solid #333;
    }

    .draghandle
    {
    position: absolute;
    z-index:100;
    width:5px;
    cursor:e-resize;
    }
    TH
    {
    border-left: 1px solid #333;
    border-bottom: 1px solid #333;
    }

    column01
    column02
    column03
    column04
    column05
    column06
    column07
    column08

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

    row
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu
    qqwoiruqwuor qwruryue ruyu

  2. deepx Says:

    dam sorry the html isnt showing up properly here, probably what happened to your post above

  3. deepx Says:

    ahh yea fixed it

    the problem was on line :

    $(”).insertBefore(table).data(‘tableid’, tableId).draggable(

    change to

    $(”).insertBefore(table).data(‘tableid’, tableId).draggable(

    • deepx Says:

      ahh yea fixed it

      the problem was on line :

        $('').insertBefore(table).data('tableid', tableId).draggable( 
      
      change to 
      
      
        $('').insertBefore(table).data('tableid', tableId).draggable( 
    • deepx Says:

      sorry about this, code is not posting correctly,

      add class .”draghandle” on the line above

      • gullbyrd Says:

        Thanks for posting this. Once I found this buried fix (actually, I figured it out myself before I saw it here), I got it to work nicely. I guess you aren’t able to edit the original post. Where is the most up to date version with all fixes?

  4. Nick Says:

    Hi,

    Can you post an example of the fix please? I cannot get this to work… :(

    Cheers!

  5. robau Says:

    Sorry for the broken code folks, it seems something went wrong during the edit. I adjusted it and also put a live working example on the net.

    Have fun with it :)

    • Nick Says:

      Hi!

      Thats great, thank you for this… it works perfectly!! :)

      The only problem I seem to have is if you have more than one tabl on the page it seems to not reset the column index for the second table.

      So only the columns in the first one resize correctly.

      It seems to be this line causing problems:

      var index = $(‘.draghandle’).index(this);
      resetTableSizes($(‘#’ + tableId), newPos – oldPos, index – 1);

      Do you have any idea’s that could fix this? I’ve tried several things such as using this rather than .draghandle etc.. no luck!

      Thanks,

      Nick

  6. Alex Says:

    Thanks a lot for figuring this out, it’s been enormously helpful. JQuery has lots of nice table plugins, but I was having a terrible time coming up with something that *just* did column re-sizing.

  7. robau Says:

    I fixed the multi-table problem Nicky was having. The code is even cleaner now, so thanks for pointing that out Nick!

  8. Ani Says:

    I m new to JQuery. but I have requirement for the re-sizable columns. I tried pasting the above code and I downloaded 2 js files from internet and pointed to those. but its not allowing me to drag. I am not getting the draggable icon at all. Can you please let me know what I am doing wrong?

    • Murray Says:

      In other words, you are yet another Indian ‘developer’ who takes on paying clients by promising them the world for ridiculously low fees, even though you have absolutely no idea how to achieve the desired outcome and then proceed to copy and paste other peoples work without any understanding or accreditation, then when you cant even manage to hack it into something fragile but stable enough to return half-finished to the client you post at the source of the script and ask them to do your work for you.

      Can I not visit one blog or forum where there isn’t an example of this!?

      • pradeep Says:

        Until I read this comment I had googd opinion about you and the article. But now I understand you are just a immature idiot with good jquery knowledge. By the way good article.

  9. Murray Says:

    I want to add, great code Rob. It should definitely be turned int a plugin, I’ve looked at lots of table addons over the last few days and your’s is the only one that does just what it needs to without any unnecessary bloat.

  10. Murray Says:

    Hi, sorry for the repeat posts, a suggestion for your code, i think your slider position should be set as follows:

    var newSliderPosition = (td.offset().left + td.outerWidth()) – table.offset().left;

    I found it works much better with nested elements.

    I also had to add position:absolute to the drag-handle css line as mine rendered relative, I think this might onyl relate to my own project though.

  11. robau Says:

    Hi all, see my mew post for the plug-in version. Also, Murray, I looked at you suggestion on the sliderpositions, but that would not work, the draghandle’s would be off by the distance form the table left to the border of the browser..

    What was the problem you where experiencing?

    • gullbyrd Says:

      I agree with Murray. When the table is nested inside a position:relative div that is offset from the edge of the page, the draggablehandle x coordinate is off by the value of the offset. Subtracting table.offset().left fixes the problem.

  12. robau Says:

    Hi all, see my mew post for the plug-in version. Also, Murray, I looked at you suggestion on the sliderpositions, but that would not work, the draghandle’s would be off by the distance form the table left to the border of the browser..

    What was the problem you where experiencing?

  13. ely Says:

    It doesn’t work in my table :(

  14. Test Autositze Says:

    It’s really a nice and useful piece of information. I am satisfied that you just shared this helpful information with us. Please stay us informed like this. Thank you for sharing.

  15. anu Says:

    $(”).insertBefore(table).data(‘tableid’, tableId).data(‘myindex’,i).draggable(
    this line throws an error : Uncaught TypeError: undefined is not a function
    Could any one suggest what is the problem .. please
    thank you.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: