New Plugin: Fill Available Width

New Plugin: Fill Available Width

jlabancajlabanca Posts: 6Questions: 0Answers: 0
edited November 2012 in Plug-ins
Here is a plugin that I created to force datatables to fill the available width. The advantage of this plugin over setting "width: 100% !important" in CSS is that the latter will cause columns to shrink to the minimum width required to show the content, ignoring "sWidth" altogether. With this plugin, you can specify a sMinWidth, which will enforce a minimum column width even if it requires a horizontal scrollbar.

I offer this code with no support or guarantees whatsoever. Just thought it might be useful. See JavaDoc for details and recipes.

Instructions:
1. Copy the code below into "datatables.fillwidth.js"
2. Include the script on your page
3. Add an "F" to "sDom" when creating the datatable

[code]
/**
* Forces the data table to fill the available width.
*
* If the available width is larger than the width of the datatable, then the
* remaining width will be allocated according to the relative weight (sWidth)
* of columns. If one or more columns contains a percentage, then the remaining
* width is distributed only to those columns. See recipes below for more
* details.
*
* If the available width is smaller than the width of the datatable, then the
* datatable will overflow the width and a horizontal scrollbar will appear.
*
* This plugin introduces a new column attribute "sMinWidth", which sets the
* minimum width of the column. If not specified, the "sWidth" is used as the
* minimum width. "sMinWidth" is useful if you want a column to have a minimum
* width AND get a portion of the available width.
*
* NOTE: If the content of a column is wider than the minimum width, the column
* will be stretched anyway. That is, content is not truncated by sMinWidth.
*
* NOTE: If you resize the table, you must call fnDraw() to resize the columns
* using this plugin.
*
* USAGE:
*
*
* $("#myGrid").dataTable({
* "sDom" : "tF", // "F" enabled the fillwidth plugin
* });
*
*
* RECIPES:
*
* Allocate extra space to a single column
* Set the sWidth of the column to "100%", and set the sWidth of other
* columns in px.
*
*
* { sWidth: "50px" },
* { sWidth: "100%" }, // Takes all remainining space
* { sWidth: "200px" }
*
*
* Split extra space between multiple columns
* Set the sWidth of the columns in percentages (weights), and set the
* sWidth of other columns in px.
*
*
* { sWidth: "50px" },
* { sWidth: "60%" }, // Takes 60% of remaining space
* { sWidth: "40%" }, // Takes 40% of remaining space
* { sWidth: "200px" }
*
*
* Assign extra space to a column and also require a minimum width
*
*
*
* { sWidth: "50px" },
* { sWidth: "60%" }, // Takes 60% of remaining space
* {
* sMinWidth: "200px", // Starts out at a minimum 200px
* sWidth: "40%" // Takes 40% of remaining space
* },
* { sWidth: "200px" }
*
*
*
*
*
* If you want to set all columns to
*
* @author John LaBanca
*/
function __fillwidthPlugin(dtSettings) {
this.dtSettings = dtSettings; // DataTable settings.
}

__fillwidthPlugin.prototype = {

ondraw : function() {
/*
* Add a sizer div to each header. The sizer forces the TH (and thus the
* column) to have the minimum width because a cell will expand to fit its
* content even if it means ignoring the cell's width.
*/
for ( var i = 0; i < this.dtSettings.aoColumns.length; i++) {
var column = this.dtSettings.aoColumns[i];
var sizer = this._ensureSizer(column);

// Set the width of the sizer to the minimum width.
var minWidth = this._calculateMinWidth(column);
if (minWidth) {
sizer.width(minWidth);
}
}

/*
* Set the tbody to 100% width. Setting the width here is better than
* setting it in CSS because datatable will be able to override the setting
* after calculations are complete. If we set the width in CSS, it will
* override anything that datatables does.
*/
var tbody = $(this.dtSettings.nTBody);
var tbodyTable = tbody.parent();
tbodyTable.width("100%");
},

/**
* Ensures that the column contains a sizer div and returns it.
*
* @param aoColumn the column
* @return the sizer div
*/
_ensureSizer : function(aoColumn) {
var th = $(aoColumn.nTh);
var sizer = th.children(".__fillwidthPluginSizer");

// Create the sizer if it doesn't exist.
if (sizer.size() == 0) {
sizer = $('');
th.append(sizer);
}

return sizer;
},

/**
* Calculates the minimum column width.
*/
_calculateMinWidth : function(aoColumn) {
// Default minimum width is the sWidth.
var minWidth = aoColumn.sWidth;

// Calculate the min width if it is provided separately.
if (typeof aoColumn.sMinWidth != "undefined") {
var iTmpWidth = this.dtSettings.oInstance.oApi._fnConvertToWidth(aoColumn.sMinWidth,
this.dtSettings.nTable.parentNode);
if (iTmpWidth !== null) {
minWidth = iTmpWidth;
}
}

return minWidth;
}
};

$.fn.dataTableExt.aoFeatures.push({
"fnInit" : function(oDTSettings) {
var plugin = new __fillwidthPlugin(oDTSettings);
oDTSettings.aoDrawCallback.push({
"fn" : function() {
plugin.ondraw();
},
"sName" : "FillWidth"
});

// Return void because we do not require a DOM element.
return;
},
"cFeature" : "F",
"sFeature" : "FillWidth"
});
[/code]

Replies

  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    Superb - thanks for sharing that with us! This will be quite useful in many x-scrolling tables I'm certain :-)

    Regards,
    Allan
This discussion has been closed.