Skip to content

Instantly share code, notes, and snippets.

@julesx
Created February 6, 2020 18:19
Show Gist options
  • Save julesx/a21d5d6aa1e159a810e1e8d389df02d2 to your computer and use it in GitHub Desktop.
Save julesx/a21d5d6aa1e159a810e1e8d389df02d2 to your computer and use it in GitHub Desktop.
(function ($) {
// register namespace
$.extend(true, window, {
"Slick": {
"CheckboxSelectionModel": CheckboxSelectionModel
}
});
function CheckboxSelectionModel(options) {
var _ranges = [];
var _self = this;
function init(grid) {
_self._grid = grid;
_self._grid.onClick.subscribe(handleGridClick);
}
function destroy() {
_self._grid.onClick.unsubscribe(self.handleGridClick);
}
function rangesToRows(ranges) {
var rows = [];
for (var i = 0; i < ranges.length; i++) {
for (var j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
rows.push(j);
}
}
return rows;
}
function rowsToRanges(rows) {
var ranges = [];
var lastCell = _self._grid.getColumns().length - 1;
for (var i = 0; i < rows.length; i++) {
ranges.push(new Slick.Range(rows[i], 0, rows[i], lastCell));
}
return ranges;
}
function setSelectedRanges(ranges) {
if ((!_ranges || _ranges.length === 0) && (!ranges || ranges.length === 0)) { return; }
_ranges = ranges;
_self.onSelectedRangesChanged.notify(_ranges);
}
function handleGridClick(e, args) {
if ($(e.target.previousElementSibling).is(':checkbox'))
{
var checkbox = $(e.target.previousElementSibling);
var selection = rangesToRows(_ranges);
var dataItem = _self._grid.getDataItem(args.row);
var expandedGroupingKeys = [];
var i = 0;
if (dataItem instanceof Slick.Group) {
if (dataItem.rows.length == 0) {
return;
}
for (i = 0; i < _self._grid.getDataLength(); i++) {
var tempDataItem = _self._grid.getDataItem(i);
if (tempDataItem instanceof Slick.Group)
{
_self._grid.invalidateRow(i);
if (tempDataItem.collapsed) {
expandedGroupingKeys.push(tempDataItem.groupingKey);
}
}
}
_self._grid.getData().expandAllGroups(null);
selection = rangesToRows(_ranges);
for (i = 0; i < dataItem.rows.length; i++) {
var groupRow = dataItem.rows[i];
var groupRowIndex = _self._grid.getData().getRowById(groupRow.id);
if (!checkbox.is(":checked")) {
if (groupRowIndex && selection.indexOf(groupRowIndex) == -1) {
selection.push(groupRowIndex);
}
}
else if (checkbox.is(":checked")) {
if (groupRowIndex) {
var indexInSelection = selection.indexOf(groupRowIndex);
selection.splice(indexInSelection, 1);
}
}
}
}
else {
if (!checkbox.is(":checked")) {
selection.push(args.row);
}
else if (checkbox.is(":checked")) {
selection.splice(selection.indexOf(args.row), 1);
}
}
var tempRanges = rowsToRanges(selection);
setSelectedRanges(tempRanges);
for (i = 0; i < expandedGroupingKeys.length; i++) {
_self._grid.getData().collapseGroup(expandedGroupingKeys[i]);
}
}
}
function getSelectedRanges() {
return _ranges;
}
$.extend(this, {
"init": init,
"destroy": destroy,
"setSelectedRanges": setSelectedRanges,
"getSelectedRanges": getSelectedRanges,
"onSelectedRangesChanged": new Slick.Event()
});
}
})(jQuery);
(function ($) {
// register namespace
$.extend(true, window, {
"Slick": {
"GroupedCheckboxSelectColumn": GroupedCheckboxSelectColumn
}
});
function GroupedCheckboxSelectColumn(options) {
var _grid;
var _self = this;
var _handler = new Slick.EventHandler();
var _selectedRowsLookup = {};
var _defaults = {
columnId: "_checkbox_selector",
cssClass: null,
toolTip: "Select/Deselect All",
width: 30
};
var _options = $.extend(true, {}, _defaults, options);
function init(grid) {
_grid = grid;
_handler
.subscribe(options.onSelectedRowIdsChangedHandler, handleSelectedRowIdsChanged)
.subscribe(_grid.onSelectedRowsChanged, handleSelectedRowsChanged)
.subscribe(_grid.onClick, handleClick)
.subscribe(_grid.onHeaderClick, handleHeaderClick)
.subscribe(_grid.onKeyDown, handleKeyDown);
}
function destroy() {
_handler.unsubscribeAll();
}
function getColumnHeaderHTML(isChecked, isPartial)
{
var checkboxContainer = $('<label>', {
'class': 'control checkbox',
'title': 'Select/Deselect All'
});
if (isPartial)
{
checkboxContainer.addClass('partial');
}
$('<input>', {
'type': 'checkbox',
'checked': isChecked,
'class': 'globalSelector'
}).appendTo(checkboxContainer);
$('<span>', {
'class': 'control-indicator',
}).appendTo(checkboxContainer);
return checkboxContainer.prop('outerHTML');
}
function getRowSelectorHTML(isChecked)
{
var checkboxContainer = $('<label>', {
'class': 'control checkbox'
});
$('<input>', {
'type': 'checkbox',
'checked': isChecked
}).appendTo(checkboxContainer);
$('<span>', {
'class': 'control-indicator',
}).appendTo(checkboxContainer);
return checkboxContainer.prop('outerHTML');
}
function handleSelectedRowsChanged(e, args) {
var selectedRows = _grid.getSelectedRows();
var lookup = {}, row, i;
for (i = 0; i < selectedRows.length; i++) {
row = selectedRows[i];
lookup[row] = true;
if (lookup[row] !== _selectedRowsLookup[row]) {
_grid.invalidateRow(row);
delete _selectedRowsLookup[row];
}
}
for (i in _selectedRowsLookup) {
_grid.invalidateRow(i);
}
_selectedRowsLookup = lookup;
_grid.render();
var itemCount = 0;
for (i = 0; i < _grid.getDataLength(); i++) {
var dataItem = _grid.getDataItem(i);
if (dataItem instanceof Slick.Group)
{
if (dataItem.level == 0) {
itemCount = itemCount + dataItem.rows.length;
}
}
}
var isChecked = itemCount > 0 && selectedRows.length == itemCount;
var isPartial = selectedRows.length > 0 && selectedRows.length < itemCount;
_grid.updateColumnHeader(_options.columnId, getColumnHeaderHTML(isChecked, isPartial), _options.toolTip);
}
function handleSelectedRowIdsChanged(e, args) {
var groups = [];
var itemCount = 0;
for (i = 0; i < _grid.getDataLength(); i++) {
var dataItem = _grid.getDataItem(i);
if (dataItem instanceof Slick.Group)
{
if (dataItem.level == 0) {
itemCount = itemCount + dataItem.rows.length;
}
groups.push(dataItem);
_grid.invalidateRow(i);
}
}
groups.map(function(group) {
var groupItemIds = group.rows.map(function(groupRow) { return groupRow.id; });
var selectedGroupRows = args.ids.filter(function(selectedItemId) {
return groupItemIds.indexOf(selectedItemId) > -1;
});
if (selectedGroupRows.length > 0 && selectedGroupRows.length < group.rows.length &&
group.title.indexOf('partial') == -1)
{
group.title = group.title.replace('class="control checkbox"', 'class="control checkbox partial"');
group.title = group.title.replace('checked="checked"', '');
}
else if (selectedGroupRows.length == 0)
{
group.title = group.title.replace('class="control checkbox partial"', 'class="control checkbox"');
group.title = group.title.replace('checked="checked"', '');
}
else if (selectedGroupRows.length == group.rows.length && group.title.indexOf('checked="checked"') == -1)
{
group.title = group.title.replace('<input type="checkbox"', '<input type="checkbox" checked="checked"');
group.title = group.title.replace('class="control checkbox partial"', 'class="control checkbox"');
}
else if (args.ids.length && args.ids.length == 0)
{
group.title = group.title.replace('checked="checked"', '');
}
});
_grid.render();
var isChecked = itemCount > 0 && args.ids.length == itemCount;
var isPartial = args.ids.length > 0 && args.ids.length < itemCount;
_grid.updateColumnHeader(_options.columnId, getColumnHeaderHTML(isChecked, isPartial), _options.toolTip);
}
function resetColumnHeader()
{
_grid.updateColumnHeader(_options.columnId, getColumnHeaderHTML(false, false), _options.toolTip);
}
function handleKeyDown(e, args) {
if (e.which == 32) {
if (_grid.getColumns()[args.cell].id === _options.columnId) {
var dataItem = _grid.getDataItem(args.row);
if (!(dataItem instanceof Slick.Group)) {
// if editing, try to commit
if (!_grid.getEditorLock().isActive() || _grid.getEditorLock().commitCurrentEdit()) {
toggleRowSelection(args.row);
}
e.preventDefault();
e.stopImmediatePropagation();
}
}
}
}
function handleClick(e, args) {
// clicking on a row select checkbox
if (_grid.getColumns()[args.cell].id === _options.columnId && $(e.target).is(":checkbox")) {
// if editing, try to commit
if (_grid.getEditorLock().isActive() && !_grid.getEditorLock().commitCurrentEdit()) {
e.preventDefault();
e.stopImmediatePropagation();
return;
}
var dataItem = _grid.getDataItem(args.row);
if (!(dataItem instanceof Slick.Group)) {
toggleRowSelection(args.row);
e.stopPropagation();
e.stopImmediatePropagation();
}
}
}
function toggleRowSelection(row) {
if (_selectedRowsLookup[row]) {
_grid.setSelectedRows($.grep(_grid.getSelectedRows(), function (n) {
return n != row
}));
} else {
_grid.setSelectedRows(_grid.getSelectedRows().concat(row));
}
}
function handleHeaderClick(e, args) {
if (args.column.id == _options.columnId && $(e.target).is(":checkbox")) {
// if editing, try to commit
if (_grid.getEditorLock().isActive() && !_grid.getEditorLock().commitCurrentEdit()) {
e.preventDefault();
e.stopImmediatePropagation();
return;
}
var expandedGroupingKeys = [];
for (i = 0; i < _grid.getDataLength(); i++) {
var tempDataItem = _grid.getDataItem(i);
if (tempDataItem instanceof Slick.Group)
{
if (tempDataItem.collapsed) {
expandedGroupingKeys.push(tempDataItem.groupingKey);
}
}
}
_grid.getData().expandAllGroups(null);
if ($(e.target).is(":checked")) {
var rows = [];
for (var i = 0; i < _grid.getDataLength(); i++) {
if (!(_grid.getDataItem(i) instanceof Slick.Group))
rows.push(i);
}
_grid.setSelectedRows(rows);
} else {
_grid.setSelectedRows([]);
}
for (var i = 0; i < expandedGroupingKeys.length; i++) {
_grid.getData().collapseGroup(expandedGroupingKeys[i]);
}
e.stopPropagation();
e.stopImmediatePropagation();
}
}
function getColumnDefinition() {
return {
id: _options.columnId,
name: getColumnHeaderHTML(false, false),
toolTip: _options.toolTip,
field: "sel",
width: _options.width,
resizable: false,
sortable: false,
cssClass: _options.cssClass,
formatter: checkboxSelectionFormatter
};
}
function checkboxSelectionFormatter(row, cell, value, columnDef, dataContext) {
if (dataContext) {
return _selectedRowsLookup[row]
? getRowSelectorHTML(true)
: getRowSelectorHTML(false)
}
return null;
}
$.extend(this, {
"init": init,
"destroy": destroy,
"resetColumnHeader": resetColumnHeader,
"getColumnDefinition": getColumnDefinition
});
}
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment