-
Notifications
You must be signed in to change notification settings - Fork 804
Grid Slickgrid AutoColumn resize
Basic Building Blocks Series: Within the basic building blocks series over time I will add all the little things which someone who just starts with Serenity Framework would have to spend a lot of time figuring it out him/herself.
What you get with this article:
(1) Create new slickgrid plugin file called slick.autocolumnsize.js and place it under: \Scripts\SlickGrid\plugins\
(function($) {
$.extend(true, window, {
"Slick": {
"AutoColumnSize": AutoColumnSize
}
});
function AutoColumnSize(initialAutosize) {
var grid, $container, context,
keyCodes = {
'A': 65
};
function init(_grid) {
grid = _grid;
//maxWidth = maxWidth || 200;
maxwidth = 200;
$container = $(grid.getContainerNode());
$container.on("dblclick.autosize", ".slick-resizable-handle", reSizeColumn);
$container.keydown(handleControlKeys);
context = document.createElement("canvas").getContext("2d");
if (initialAutosize) {
$container.ready(resizeAllColumns());
}
}
function destroy() {
$container.off();
}
function handleControlKeys(event) {
if (event.ctrlKey && event.shiftKey && event.keyCode === keyCodes.A) {
resizeAllColumns();
}
}
function resizeAllColumns() {
// *** John Ranger 2017-02-12 added in order to make this plugin work with current serenity version (2.9.4). Somehow it takes some time until all data is loaded in the grid - so we have to make sure that the data is there before we try to find out the max width of each column ***
var data = grid.getData();
data = data.getItems();
if (data.length >0) {
var elHeaders = $container.find(".slick-header-column");
var allColumns = grid.getColumns();
elHeaders.each(function (index, el) {
// *** John Ranger 2019-04-08: Modified logic to skip row selection checkbox if there is one (as this crashed the initial autosize of the grid) ***
var columnDef = $(el).data('column');
var colIndex = grid.getColumnIndex(columnDef.id);
var column = allColumns[colIndex];
if (allColumns[colIndex].headerCssClass != "select-all-header") {
var headerWidth = getElementWidth(el);
var autoSizeWidth = Math.max(headerWidth, getMaxColumnTextWidth(columnDef, colIndex)) + 1;
// *** John Ranger 2016-03-23: Remarked as this causes some problems with some columns ***
//autoSizeWidth = Math.min(maxWidth, autoSizeWidth);
column.width = autoSizeWidth;
};
});
grid.setColumns(allColumns);
grid.onColumnsResized.notify();
} // *** John Ranger 2017-02-12 added in order to make this plugin work with current serenity version (2.9.4). Somehow it takes some time until all data is loaded in the grid - so we have to make sure that the data is there before we try to find out the max width of each column ***
else {
setTimeout(resizeAllColumns, 100);
}
}
function reSizeColumn(e) {
var headerEl = $(e.currentTarget).closest('.slick-header-column');
var columnDef = headerEl.data('column');
if (!columnDef || !columnDef.resizable) {
return;
}
e.preventDefault();
e.stopPropagation();
var headerWidth = getElementWidth(headerEl[0]);
var colIndex = grid.getColumnIndex(columnDef.id);
var allColumns = grid.getColumns();
var column = allColumns[colIndex];
var autoSizeWidth = Math.max(headerWidth, getMaxColumnTextWidth(columnDef, colIndex)) + 1;
if (autoSizeWidth !== column.width) {
column.width = autoSizeWidth;
grid.setColumns(allColumns);
grid.onColumnsResized.notify();
}
}
function getMaxColumnTextWidth(columnDef, colIndex) {
var texts = [];
var rowEl = createRow(columnDef);
var data = grid.getData();
// *** John Ranger 2016-03-23: Block remarked as this causes the plugin not to work within serenity framework ***
//if (Slick.Data && data instanceof Slick.Data.DataView) {
// alert('jojo in 2.5');
// data = data.getItems();
//}
data = data.getItems(); // *** John Ranger 2017-02-09 added in order to make this plugin work with current serenity version (2.9.4) ***
//alert(data.length);
for (var i = 0; i < data.length; i++) {
texts.push(data[i][columnDef.field]);
}
var maxWidth = getMaxWidth(texts, columnDef, colIndex, data, rowEl); // *** Using new function to directly get max width without running over template mechanism (which does not work anymore) ***
deleteRow(rowEl);
maxWidth = maxWidth + 15; // *** Additional space for better reading and to accomodate additional little space used by diverse invisible objects - adjust if needed ***
return maxWidth;
}
function getMaxWidth(texts, columnDef, colIndex, data, rowEl) {
var max = 0;
var formatFun = columnDef.formatter;
$(texts).each(function (index, text) {
var template;
if (formatFun) {
template = $("<span>" + formatFun(index, colIndex, text, columnDef, data) + "</span>");
text = template.text() || text;
}
var length = text ? getElementWidthUsingCanvas(rowEl, text) : 0;
if (length > max) {
max = length;
}
});
return max;
}
function createRow(columnDef) {
var rowEl = $('<div class="slick-row"><div class="slick-cell"></div></div>');
rowEl.find(".slick-cell").css({
"visibility": "hidden",
"text-overflow": "initial",
"white-space": "nowrap"
});
var gridCanvas = $container.find(".grid-canvas");
$(gridCanvas).append(rowEl);
return rowEl;
}
function deleteRow(rowEl) {
$(rowEl).remove();
}
function getElementWidth(element) {
var width, clone = element.cloneNode(true);
clone.style.cssText = 'position: absolute; visibility: hidden;right: auto;text-overflow: initial;white-space: nowrap;';
element.parentNode.insertBefore(clone, element);
width = clone.offsetWidth;
clone.parentNode.removeChild(clone);
return width;
}
function getElementWidthUsingCanvas(element, text) {
context.font = element.css("font-size") + " " + element.css("font-family");
var metrics = context.measureText(text);
return metrics.width;
}
return {
init: init,
resizeAllColumns: resizeAllColumns,
destroy: destroy
};
}
}(jQuery));
(2) Create a new Folder called SlickGrid under \Scripts\typings
Then create the file slick.autocolumnsize.d.ts under above path with the following content:
declare namespace Slick {
function AutoColumnSize(initialAutosize: boolean): void;
}
(3) In your xyzGrid.ts (of the grid which you want to have the autocolumnresize feature), add the following:
private autoSize;
protected createSlickGrid(): Slick.Grid {
let grid = super.createSlickGrid();
this.autoSize = new Slick.AutoColumnSize(true); // *** If you want to make it autoresize when grid is loaded, use: new Slick.AutoColumnSize(true);
grid.registerPlugin(this.autoSize);
return grid;
}
// *** Resizes the columns after changes are made to the grid (ex. Column Picker) *
protected markupReady() {
super.markupReady();
if (this.autoSize != null) {
this.autoSize.resizeAllColumns();
}
}
(4) Go to Views/Shared/_LayoutHead.cshtml and add the following
@Html.Script("~/Scripts/SlickGrid/Plugins/slick.autocolumnsize.js")
Credits: Please note that the original Slickgrid plugin for autocolumnResize is from here: https://github.com/naresh-n/slickgrid-column-data-autosize. I just had to put in some workarrounds and fixes in order to make it work with current serenity Framework and typescript.
Important: There are other contributors which have made this nice plugin work again under current Serenity Framework. Thank you guys!
Copyright © Serenity Platform 2017-present. All rights reserved.
Documentation | Serene Template | Live Demo | Premium Support | Issues | Discussions