Skip to content

Commit

Permalink
Enable hidden property for column. Adds example-column-hidden, method…
Browse files Browse the repository at this point in the history
… getVisibleColumns() and alternate method updateColumns() calling event onBeforeUpdateColumns() for when a hidden property has changed but the column list itself has not changed.
  • Loading branch information
6pac committed May 9, 2023
1 parent f20e5c6 commit a58d329
Show file tree
Hide file tree
Showing 4 changed files with 479 additions and 17 deletions.
2 changes: 2 additions & 0 deletions controls/slick.columnpicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@

let columnId, columnLabel, excludeCssClass;
for (var i = 0; i < columns.length; i++) {
if (columns[i].hidden) continue;

columnId = columns[i].id;
excludeCssClass = columns[i].excludeFromColumnPicker ? "hidden" : "";

Expand Down
378 changes: 378 additions & 0 deletions examples/example-column-hidden.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,378 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="shortcut icon" type="image/ico" href="favicon.ico" />
<title>SlickGrid example: Hidden Columns</title>
<link rel="stylesheet" href="../slick.grid.css" type="text/css"/>
<link rel="stylesheet" href="../controls/slick.pager.css" type="text/css"/>
<link rel="stylesheet" href="../examples/examples.css" type="text/css"/>
<link rel="stylesheet" href="../examples/examples-unicode-icons.css" type="text/css"/>
<link rel="stylesheet" href="../controls/slick.columnpicker.css" type="text/css"/>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/flatpickr.css">
<style>
.cell-title {
font-weight: bold;
}

.cell-effort-driven {
text-align: center;
}

.cell-selection {
border-right-color: silver;
border-right-style: solid;
background: #f5f5f5;
color: gray;
text-align: right;
font-size: 10px;
}

.slick-row.selected .cell-selection {
background-color: transparent; /* show default selected row background */
}
</style>
</head>
<body>
<div style="position:relative">
<div style="width:600px;">
<div class="grid-header" style="width:100%">
<label>SlickGrid</label>
<span style="float:right;margin:0px 4px auto 6px;background:transparent;cursor:pointer;" class="slick-icon-search" title="Toggle search panel"
onclick="toggleFilterRow()"></span>
</div>
<div id="myGrid" style="width:100%;height:500px;"></div>
<div id="pager" style="width:100%;height:20px;"></div>
</div>

<div class="options-panel">
<b>Search:</b>
<hr/>
<div style="padding:6px;">
<label style="width:200px;float:left">Show tasks with % at least: </label>

<div style="padding:2px;">
<input style="width:100px;display:inline-block;" id="pcSlider" type="range" min="1" max="100" value="1">
</div>
<br/>
<label style="width:200px;float:left">And title including:</label>
<input type=text id="txtSearch" style="width:100px;">
<br/><br/>
<button id="btnSelectRows">Select first 10 rows</button>
<br/><br/>
<input id="chkHideColumn" type="checkbox"/> Hide Duration Column
<br/>

<h2>Demonstrates:</h2>
<ul>
<li>a filtered Model (DataView) as a data source instead of a simple array</li>
<li>grid reacting to model events (onRowCountChanged, onRowsChanged)</li>
<li>
<b>FAST</b> DataView recalculation and <b>real-time</b> grid updating in response to data changes.<br/>
The grid holds <b>50'000</b> rows, yet you are able to sort, filter, scroll, navigate and edit as if it had 50
rows.
</li>
<li>adding new rows, bidirectional sorting</li>
<li>column options: cannotTriggerInsert</li>
<li>events: onCellChange, onAddNewRow, onKeyDown, onSelectedRowsChanged, onSort</li>
<li><font color=red>NOTE:</font> all filters are immediately applied to new/edited rows</li>
<li>Handling row selection against model changes.</li>
<li>Paging.</li>
<li>inline filter panel</li>
</ul>
<h2>View Source:</h2>
<ul>
<li><A href="https://github.com/6pac/SlickGrid/blob/master/examples/example-column-visible.html" target="_sourcewindow"> View the source for this example on Github</a></li>
</ul>

</div>
</div>
</div>

<div id="inlineFilterPanel" style="display:none;background:#dddddd;color:black;">
Show tasks with title including <input type="text" id="txtSearch2">
and % at least &nbsp;
<input style="width:100px;display:inline-block;" id="pcSlider2" type="range" min="1" max="100" value="1">
</div>

<script src="../lib/firebugx.js"></script>

<script src="../lib/jquery-3.1.0.js"></script>
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<script src="https://cdn.jsdelivr.net/npm/sortablejs/Sortable.js"></script>

<script src="../slick.core.js"></script>
<script src="../slick.interactions.js"></script>
<script src="../slick.formatters.js"></script>
<script src="../slick.editors.js"></script>
<script src="../plugins/slick.rowselectionmodel.js"></script>
<script src="../slick.grid.js"></script>
<script src="../slick.dataview.js"></script>
<script src="../controls/slick.pager.js"></script>
<script src="../controls/slick.columnpicker.js"></script>

<script>
function isIEPreVer9() { var v = navigator.appVersion.match(/MSIE ([\d.]+)/i); return (v ? v[1] < 9 : false); }

var dataView;
var grid;
var data = [];
var columns = [
{id: "sel", name: "#", field: "num", behavior: "select", cssClass: "cell-selection", width: 40, cannotTriggerInsert: true, resizable: false, selectable: false, excludeFromColumnPicker: true },
{id: "title", name: "Title", field: "title", width: 120, minWidth: 120, cssClass: "cell-title", editor: Slick.Editors.Text, validator: requiredFieldValidator, sortable: true},
{id: "duration", name: "Duration", field: "duration", editor: Slick.Editors.Text, sortable: true},
{id: "%", defaultSortAsc: false, name: "% Complete", field: "percentComplete", width: 80, resizable: false, formatter: Slick.Formatters.PercentCompleteBar, editor: Slick.Editors.PercentComplete, sortable: true},
{id: "start", name: "Start", field: "start", minWidth: 60, editor: Slick.Editors.Flatpickr, sortable: true},
{id: "finish", name: "Finish", field: "finish", minWidth: 60, editor: Slick.Editors.Flatpickr, sortable: true},
{id: "effort-driven", name: "Effort Driven", width: 80, minWidth: 20, maxWidth: 80, cssClass: "cell-effort-driven", field: "effortDriven", formatter: Slick.Formatters.Checkbox, editor: Slick.Editors.Checkbox, cannotTriggerInsert: true, sortable: true}
];

var options = {
columnPicker: {
columnTitle: "Columns",
hideForceFitButton: false,
hideSyncResizeButton: false,
forceFitTitle: "Force fit columns",
syncResizeTitle: "Synchronous resize",
},
editable: true,
enableAddRow: true,
enableCellNavigation: true,
asyncEditorLoading: true,
forceFitColumns: false,
topPanelHeight: 25
};

var sortcol = "title";
var sortdir = 1;
var percentCompleteThreshold = 0;
var searchString = "";

function requiredFieldValidator(value) {
if (value == null || value == undefined || !value.length) {
return {valid: false, msg: "This is a required field"};
}
else {
return {valid: true, msg: null};
}
}

function myFilter(item, args) {
if (item["percentComplete"] < args.percentCompleteThreshold) {
return false;
}

if (args.searchString != "" && item["title"].indexOf(args.searchString) == -1) {
return false;
}

return true;
}

function percentCompleteSort(a, b) {
return a["percentComplete"] - b["percentComplete"];
}

function comparer(a, b) {
var x = a[sortcol], y = b[sortcol];
return (x == y ? 0 : (x > y ? 1 : -1));
}

function toggleFilterRow() {
grid.setTopPanelVisibility(!grid.getOptions().showTopPanel);
}


$(".grid-header .ui-icon")
.addClass("ui-state-default ui-corner-all")
.mouseover(function (e) {
$(e.target).addClass("ui-state-hover")
})
.mouseout(function (e) {
$(e.target).removeClass("ui-state-hover")
});

$(function () {
// prepare the data
for (var i = 0; i < 50000; i++) {
var d = (data[i] = {});

d["id"] = "id_" + i;
d["num"] = i;
d["title"] = "Task " + i;
d["duration"] = "5 days";
d["percentComplete"] = Math.round(Math.random() * 100);
d["start"] = "01/01/2009";
d["finish"] = "01/05/2009";
d["effortDriven"] = (i % 5 == 0);
}


dataView = new Slick.Data.DataView({ inlineFilters: true });
grid = new Slick.Grid("#myGrid", dataView, columns, options);
grid.setSelectionModel(new Slick.RowSelectionModel());

var pager = new Slick.Controls.Pager(dataView, grid, $("#pager"));
var columnpicker = new Slick.Controls.ColumnPicker(columns, grid, options);


// move the filter panel defined in a hidden div into grid top panel
$("#inlineFilterPanel")
.appendTo(grid.getTopPanel())
.show();

grid.onCellChange.subscribe(function (e, args) {
dataView.updateItem(args.item.id, args.item);
});

grid.onAddNewRow.subscribe(function (e, args) {
var item = {"num": data.length, "id": "new_" + (Math.round(Math.random() * 10000)), "title": "New task", "duration": "1 day", "percentComplete": 0, "start": "01/01/2009", "finish": "01/01/2009", "effortDriven": false};
$.extend(item, args.item);
dataView.addItem(item);
});

grid.onKeyDown.subscribe(function (e) {
// select all rows on ctrl-a
if (e.which != 65 || !e.ctrlKey) {
return false;
}

var rows = [];
for (var i = 0; i < dataView.getLength(); i++) {
rows.push(i);
}

grid.setSelectedRows(rows);
e.preventDefault();
});

grid.onSort.subscribe(function (e, args) {
sortdir = args.sortAsc ? 1 : -1;
sortcol = args.sortCol.field;

if (isIEPreVer9()) {
// using temporary Object.prototype.toString override
// more limited and does lexicographic sort only by default, but can be much faster

var percentCompleteValueFn = function () {
var val = this["percentComplete"];
if (val < 10) {
return "00" + val;
} else if (val < 100) {
return "0" + val;
} else {
return val;
}
};

// use numeric sort of % and lexicographic for everything else
dataView.fastSort((sortcol == "percentComplete") ? percentCompleteValueFn : sortcol, args.sortAsc);
} else {
// using native sort with comparer
// preferred method but can be very slow in IE with huge datasets
dataView.sort(comparer, args.sortAsc);
}
});

// wire up model events to drive the grid
// !! both dataView.onRowCountChanged and dataView.onRowsChanged MUST be wired to correctly update the grid
// see Issue#91
dataView.onRowCountChanged.subscribe(function (e, args) {
grid.updateRowCount();
grid.render();
});

dataView.onRowsChanged.subscribe(function (e, args) {
grid.invalidateRows(args.rows);
grid.render();
});

dataView.onPagingInfoChanged.subscribe(function (e, pagingInfo) {
grid.updatePagingStatusFromView( pagingInfo );

// show the pagingInfo but remove the dataView from the object, just for the Cypress E2E test
delete pagingInfo.dataView;
console.log('on After Paging Info Changed - New Paging:: ', pagingInfo);
});

dataView.onBeforePagingInfoChanged.subscribe(function (e, previousPagingInfo) {
// show the previous pagingInfo but remove the dataView from the object, just for the Cypress E2E test
delete previousPagingInfo.dataView;
console.log('on Before Paging Info Changed - Previous Paging:: ', previousPagingInfo);
});

var h_runfilters = null;

// wire up the slider to apply the filter to the model
var slider = document.getElementById("pcSlider");
var slider2 = document.getElementById("pcSlider2");
var sliderCallback = function() {
Slick.GlobalEditorLock.cancelCurrentEdit();

if (percentCompleteThreshold != this.value) {
window.clearTimeout(h_runfilters);
h_runfilters = window.setTimeout(updateFilter, 10);
percentCompleteThreshold = this.value;
}
}

slider.oninput = sliderCallback;
slider2.oninput = sliderCallback;

// wire up the search textbox to apply the filter to the model
$("#txtSearch,#txtSearch2").keyup(function (e) {
Slick.GlobalEditorLock.cancelCurrentEdit();

// clear on Esc
if (e.which == 27) {
this.value = "";
}

searchString = this.value;
updateFilter();
});

function updateFilter() {
dataView.setFilterArgs({
percentCompleteThreshold: percentCompleteThreshold,
searchString: searchString
});
dataView.refresh();
}

$("#btnSelectRows").click(function () {
if (!Slick.GlobalEditorLock.commitCurrentEdit()) {
return;
}

var rows = [];
for (var i = 0; i < 10 && i < dataView.getLength(); i++) {
rows.push(i);
}

grid.setSelectedRows(rows);
});

$("#chkHideColumn").change(function () {
var hideCol = $("#chkHideColumn").prop('checked') || false;
columns[2].hidden = hideCol;
grid.setColumns(columns);
});

// initialize the model after all the events have been hooked up
dataView.beginUpdate();
dataView.setItems(data);
dataView.setFilterArgs({
percentCompleteThreshold: percentCompleteThreshold,
searchString: searchString
});
dataView.setFilter(myFilter);
dataView.endUpdate();

// if you don't want the items that are not visible (due to being filtered out
// or being on a different page) to stay selected, pass 'false' to the second arg
dataView.syncGridSelection(grid, true);
})
</script>
</body>
</html>
Loading

0 comments on commit a58d329

Please sign in to comment.