Lately I’ve been playing a lot with jqGrid, a very nice Grid / Table plugin for jQuery / jQuery UI. It does some really amazing things including allowing you to have a scrollbar that replaces the standard “next page” / “previous page” that you see in most web applications. I have tables that are sortable on multiple columns that have tens of thousands of results and I can scroll through them easily. It is also easy to leverage filtering, etc. All this takes a touch of server-side code, but it is all astoundingly easy.
The one trick I couldn’t figure out how to do was to set the column with based on the Title. In most grids with just a few columns, this isn’t an issue – you set the size (in pixels) and go on your way. But what if you don’t know the column names ahead of time (they come from the database) and you just want to make sure the column with is a minimum of a number but a maximum big enough to hold the title plus a bit of padding?
After the grid has been created, you cannot programmatically set the width of columns, so it has to be done before the grid is created. Normally you create a jqGrid as such:
<table id="list"></table>
<div id="pager"></div>
<script type="text/javascript">
 var colNamesData = ['Inv No','Date Of the Transaction', 'Amount That Is Owed'];
var colModelData = [
{name:'invid', index:'invid', width:55},
{name:'invdate', index:'invdate', width:90},
{name:'amount', index:'amount', width:80, align:'right'}];
jQuery(document).ready(function(){
jQuery("#list").jqGrid({
...
colNames: colNamesData,
colModel: colModelData,
...
});
</script>
To set the column widths automatically to the title, for any column in the column model I added a new boolean attribute resizeToTitleWidth and only resized the column if this was set to true. Here is the new code that resizes the desired columns.
<table id="list"></table>
<div id="pager"></div>
<span id='ruler' class='ui-th-column' style='visibility:hidden;font-weight:bold'></span>
<script type="text/javascript">
var colNamesData = ['Inv No','Date Of the Transaction', 'Amount That Is Owed'];
var colModelData = [
{name:'invid', index:'invid', width:55},
{name:'invdate', index:'invdate', resizeToTitleWidth:true},
{name:'amount', index:'amount', align:'right', resizeToTitleWidth:true}];
jQuery(document).ready(function() {
var ruler = document.getElementById('ruler');
for (var i in colNamesData) {
if (colModelData[i].resizeToTitleWidth != true) {
continue;
}
// Measure the title using the ruler span
ruler.innerHTML = colNamesData[i];
// The +26 allows for padding and to fit the sorting UI
var newWidth = ruler.offsetWidth + 26;
if (newWidth < 100) {
// Nothing smaller than 100 pixels
newWidth = 100;
}
colModelData[i].width = newWidth;
}
jQuery("#list").jqGrid({
...
colNames: colNamesData,
colModel: colModelData,
shrinkToFit:false,
...
});
</script>
The key to obtaining the width is the additional hidden HTML span tag with the id of ruler. This hidden span has the same CSS style as the column header, so we can place the column title text into this span and obtain the width of the text geting the span‘s offsetWidth. After we have the width, we pad the width with enough extra space to hold the sorting UI.
It would have been nice if the column had an attribute that forced the width to accommodate the the columns title (but allowed for a minimum width, here 100 pixels) but we find that it isn’t too difficult to add the functionality ourselves.
The above example is meant to be illustrative rather that a complete working sample. I’ve put together what should be a simple, working sample you can try.