Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
Markdown Monster - The Markdown Editor for Windows

jQuery-resizable and Table Column Resizing


:P
On this page:

Last week I wrote about a small jQuery resizing plug-in that handles resizing of DOM elements and I showed a couple of common use cases for resizable windows and slider panels for multi-panel layouts which were a couple of use cases that I needed the plug-in for. You can check out the plug-in on GitHub and see a few CodePen samples that demonstrate this functionality:

Table Column Resizing

Well, that didn't take long! Almost immediately I got a number of questions regarding using the plug-in with HTML tables and resizing of columns which is a scenario I didn't think about initially. My first thought was "That's not going to work." However, after some experimenting, and as I show in this post with a little bit of extra code you can make table columns resizable as well.

Yeah, we all know tables suck when it comes to building HTML layouts that are responsive and need to be styled nicely, but… hey, they are heavily used anyway in many applications. And hate them or not, there use cases where tabular data is required and tables work for those grid style displays of true multi-column data. Resizing of columns is a nice feature and one that you don't see all that often in HTML forms so it'd be nice if this worked with the jquery-resizable plugin. It does, but it takes a little extra effort.

Check out the example here:

tableresizing

The jquery-resize plug-in was designed to be very minimal so it handles it resizing without any dependencies on CSS or the HTML layout as it relies entirely on the DOM element resizing for managing the resizing process. In other words as the element expands or shrinks in size the sizing handle moves with it. This is how this small plug-in is so small. Tables are a bit more complicated because when you resizing columns you generally don't have a sizing handle, so in order to make this work, we need to inject the resizing handles into the document and display them in the each column you want to resize.

Essentially what needs to happen is this:

  • Add a resizing handle to each column that is to be resized
  • Attach the handle dynamically to the resizer
  • Provide some CSS styling to ensure the resizing handle shows in the right location

To make a long story short here is the essential code to make this work using interactive code and styling:

<style>
    /*
        this is important!
        make sure you define this here
        or in jQuery code
    */
    .resizer {
        position: absolute;
        top: 0;
        right: -8px;
        bottom: 0;
        left: auto;
        width: 16px;    
        cursor: col-resize;       
    }
</style>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js" type="text/javascript"></script>
<script src="../src/jquery-resizable.js"></script>
<script src="../src/jquery-resizableTableColumns.js"></script>
<script>
    //$("td,th").resizableTableColumns();

    $("td:first-child,td:nth-child(2),td:nth-child(3)").resizableTableColumns();

$("td,th")
//$("td:first-child,td:nth-child(2),td:nth-child(3)")
    .css({ position: "relative" })
    .prepend("<div class='resizer'></div>")            
    .resizable({
        resizeHeight: false,
        // we use the column as handle and filter
        // by the contained .resizer element
        handleSelector: "",
        onDragStart: function (e, $el, opt) {
            // only drag resizer
            if (!$(e.target).hasClass("resizer"))
                return false;
            return true;
        }
    });
   
</script>

The hardest part in all of this was to get the CSS to work for the dynamically added resizing handles. The trick to making this work is to make the table cells (and/or headers) position:relative so that we can insert the element and push it to the right of the column. The resizer basically overlaps the column separator with a negative margin and cursor: col-resize to show the resizing cursor so that the cursor shows up when hovering on the column border. If you play with the demo, try setting the background of the .resizer style to green so you can see how the overlay works.

The code also sets the handle selector to the actual column and then later checks the actual dragStart target to see if it's the resizer we're triggering. This is because initially the resizer doesn't exist, so the handle selection really occurs at runtime when you grab the handle.

This is all a bit of a hack, but it works suprisingly well. You may see some odd sizing behavior on the last column, but that's acceptable given that this is such a simple and light weight solution.

Making it into a jQuery Plug-in

The code above works but you can easily abstract this into another plug-in so it's a little more user friendly. Rolled into a plug-in the code looks like this:

/// <reference path="jquery.js" />
/// <reference path="jquery-resizable.js" />
/*
jquery-resizable-table-columns
Version 0.14 - 1/4/2015
© 2015 Rick Strahl, West Wind Technologies 
www.west-wind.com
Licensed under MIT License
*/
(function($, undefined) {
    $.fn.resizableTableColumns = function(opt) {
        opt = $.extend({
            resizeHeight: false,
            // we use the column as handle and filter
            // by the contained .resizer element
            handleSelector: "",
            onDragStart: function(e, $el, opt) {
                // only drag resizer
                if (!$(e.target).hasClass("resizer"))
                    return false;
                return true;
            }
        }, opt);

        return this.each(function() {
            $(this)
                .css({ position: "relative" })
                .prepend("<div class='resizer'></div>")
                .resizable(opt);
        });
    };
})(jQuery, undefined);

and you can now call this using code like this:

$("td,th").resizableTableColumns();

or as before:

$("td:first-child,td:nth-child(2),td:nth-child(3)").resizableTableColumns();

Note that you still have to add the .resizer {} CSS to the page:

<style>
    .resizer {
        position: absolute;
        top: 0;
        right: -8px;
        bottom: 0;
        left: auto;
        width: 16px;    
        cursor: col-resize;       
    }
</style>

to ensure that the resizer renders properly in each column. One enhancement to this plugin might be to integrate the CSS logic into the code so that there are no extra dependencies by simply assigning the .css() attributes via jQuery. While this makes the code self-contained without dependencies, it also reduces the configurability so I prefer to have the CSS external as shown here.

Code on GitHub

I've updated the existing plug-in and added the jquery-resizableTableColumns plug-in and you can find the code, links to the samples, documentation there….

Resources

Posted in jQuery  JavaScript  HTML5  

The Voices of Reason


 

Shruthy
October 22, 2018

# re: jQuery-resizable and Table Column Resizing

Hi Rick, The code on table column resizing is good. But you can also show the content inside the cell editable while resizing the column.


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024