Browse files

Made is dead simple to sync selection and cellCssStyles on DataView c…

…hanges.

DataView:
- New "mapIdsToRows" and "mapRowsToIds" helper methods.
- "syncGridSelection" and "syncGridCellCssStyles" keep selection and
cell CSS styles (set via grid.setCellCssStyles) in sync across DataView
changes.  Use them if you want or write your version that incorporates
your requirements.

SlickGrid:
- Added an "onCellCssStylesChanged" event and a "getCellCssStyles"
accessor.
  • Loading branch information...
1 parent 42e35cb commit 8892f4a3e07c605c3e0b85d2895bd6ff46022191 @mleibman mleibman committed Jan 27, 2012
Showing with 142 additions and 60 deletions.
  1. +6 −35 examples/example4-model.html
  2. +89 −0 slick.dataview.js
  3. +47 −25 slick.grid.js
View
41 examples/example4-model.html
@@ -106,8 +106,6 @@
var dataView;
var grid;
var data = [];
-var selectedRowIds = [];
-
var columns = [
{id: "sel", name: "#", field: "num", behavior: "select", cssClass: "cell-selection", width: 40, cannotTriggerInsert: true, resizable: false, selectable: false },
{id: "title", name: "Title", field: "title", width: 120, minWidth: 120, cssClass: "cell-title", editor: Slick.Editors.Text, validator: requiredFieldValidator, sortable: true},
@@ -206,8 +204,8 @@
// move the filter panel defined in a hidden div into grid top panel
$("#inlineFilterPanel")
- .appendTo(grid.getTopPanel())
- .show();
+ .appendTo(grid.getTopPanel())
+ .show();
grid.onCellChange.subscribe(function (e, args) {
dataView.updateItem(args.item.id, args.item);
@@ -226,28 +224,14 @@
}
var rows = [];
- selectedRowIds = [];
-
for (var i = 0; i < dataView.getLength(); i++) {
rows.push(i);
- selectedRowIds.push(dataView.getItem(i).id);
}
grid.setSelectedRows(rows);
e.preventDefault();
});
- grid.onSelectedRowsChanged.subscribe(function (e) {
- selectedRowIds = [];
- var rows = grid.getSelectedRows();
- for (var i = 0, l = rows.length; i < l; i++) {
- var item = dataView.getItem(rows[i]);
- if (item) {
- selectedRowIds.push(item.id);
- }
- }
- });
-
grid.onSort.subscribe(function (e, args) {
sortdir = args.sortAsc ? 1 : -1;
sortcol = args.sortCol.field;
@@ -285,20 +269,6 @@
dataView.onRowsChanged.subscribe(function (e, args) {
grid.invalidateRows(args.rows);
grid.render();
-
- if (selectedRowIds.length > 0) {
- // since how the original data maps onto rows has changed,
- // the selected rows in the grid need to be updated
- var selRows = [];
- for (var i = 0; i < selectedRowIds.length; i++) {
- var idx = dataView.getRowById(selectedRowIds[i]);
- if (idx != undefined) {
- selRows.push(idx);
- }
- }
-
- grid.setSelectedRows(selRows);
- }
});
dataView.onPagingInfoChanged.subscribe(function (e, pagingInfo) {
@@ -356,11 +326,8 @@
}
var rows = [];
- selectedRowIds = [];
-
for (var i = 0; i < 10 && i < dataView.getLength(); i++) {
rows.push(i);
- selectedRowIds.push(dataView.getItem(i).id);
}
grid.setSelectedRows(rows);
@@ -377,6 +344,10 @@
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);
+
$("#gridContainer").resizable();
})
</script>
View
89 slick.dataview.js
@@ -257,6 +257,28 @@
return items[idxById[id]];
}
+ function mapIdsToRows(idArray) {
+ var rows = [];
+ ensureRowsByIdCache();
+ for (var i = 0; i < idArray.length; i++) {
+ var row = rowsById[idArray[i]];
+ if (row != null) {
+ rows[rows.length] = row;
+ }
+ }
+ return rows;
+ }
+
+ function mapRowsToIds(rowArray) {
+ var ids = [];
+ for (var i = 0; i < rowArray.length; i++) {
+ if (rowArray[i] < rows.length) {
+ ids[ids.length] = rows[rowArray[i]][idProperty];
+ }
+ }
+ return ids;
+ }
+
function updateItem(id, item) {
if (idxById[id] === undefined || id !== item[idProperty]) {
throw "Invalid or non-matching id";
@@ -638,6 +660,69 @@
}
}
+ function syncGridSelection(grid, preserveHidden) {
+ var self = this;
+ var selectedRowIds = self.mapRowsToIds(grid.getSelectedRows());;
+ var inHandler;
+
+ grid.onSelectedRowsChanged.subscribe(function(e, args) {
+ if (inHandler) { return; }
+ selectedRowIds = self.mapRowsToIds(grid.getSelectedRows());
+ });
+
+ this.onRowsChanged.subscribe(function(e, args) {
+ if (selectedRowIds.length > 0) {
+ inHandler = true;
+ var selectedRows = self.mapIdsToRows(selectedRowIds);
+ if (!preserveHidden) {
+ selectedRowIds = self.mapRowsToIds(selectedRows);
+ }
+ grid.setSelectedRows(selectedRows);
+ inHandler = false;
+ }
+ });
+ }
+
+ function syncGridCellCssStyles(grid, key) {
+ var hashById;
+ var inHandler;
+
+ // since this method can be called after the cell styles have been set,
+ // get the existing ones right away
+ storeCellCssStyles(grid.getCellCssStyles(key));
+
+ function storeCellCssStyles(hash) {
+ hashById = {};
+ for (var row in hash) {
+ var id = rows[row][idProperty];
+ hashById[id] = hash[row];
+ }
+ }
+
+ grid.onCellCssStylesChanged.subscribe(function(e, args) {
+ if (inHandler) { return; }
+ if (key != args.key) { return; }
+ if (args.hash) {
+ storeCellCssStyles(args.hash);
+ }
+ });
+
+ this.onRowsChanged.subscribe(function(e, args) {
+ if (hashById) {
+ inHandler = true;
+ ensureRowsByIdCache();
+ var newHash = {};
+ for (var id in hashById) {
+ var row = rowsById[id];
+ if (row != undefined) {
+ newHash[row] = hashById[id];
+ }
+ }
+ grid.setCellCssStyles(key, newHash);
+ inHandler = false;
+ }
+ });
+ }
return {
// methods
@@ -660,13 +745,17 @@
"getRowById": getRowById,
"getItemById": getItemById,
"getItemByIdx": getItemByIdx,
+ "mapRowsToIds": mapRowsToIds,
+ "mapIdsToRows": mapIdsToRows,
"setRefreshHints": setRefreshHints,
"setFilterArgs": setFilterArgs,
"refresh": refresh,
"updateItem": updateItem,
"insertItem": insertItem,
"addItem": addItem,
"deleteItem": deleteItem,
+ "syncGridSelection": syncGridSelection,
+ "syncGridCellCssStyles": syncGridCellCssStyles,
// data provider methods
"getLength": getLength,
View
72 slick.grid.js
@@ -1542,49 +1542,69 @@ if (typeof Slick === "undefined") {
}
}
+ function updateCellCssStylesOnRenderedRows(addedHash, removedHash) {
+ var node, columnId, addedRowHash, removedRowHash;
+ for (var row in rowsCache) {
+ removedRowHash = removedHash && removedHash[row];
+ addedRowHash = addedHash && addedHash[row];
+
+ if (removedRowHash) {
+ for (columnId in removedRowHash) {
+ if (!addedRowHash || removedRowHash[columnId] != addedRowHash[columnId]) {
+ node = getCellNode(row, getColumnIndex(columnId));
+ if (node) {
+ $(node).removeClass(removedRowHash[columnId]);
+ }
+ }
+ }
+ }
+
+ if (addedRowHash) {
+ for (columnId in addedRowHash) {
+ if (!removedRowHash || removedRowHash[columnId] != addedRowHash[columnId]) {
+ node = getCellNode(row, getColumnIndex(columnId));
+ if (node) {
+ $(node).addClass(addedRowHash[columnId]);
+ }
+ }
+ }
+ }
+ }
+ }
+
function addCellCssStyles(key, hash) {
if (cellCssClasses[key]) {
throw "addCellCssStyles: cell CSS hash with key '" + key + "' already exists.";
}
cellCssClasses[key] = hash;
+ updateCellCssStylesOnRenderedRows(hash, null);
- var node;
- for (var row in rowsCache) {
- if (hash[row]) {
- for (var columnId in hash[row]) {
- node = getCellNode(row, getColumnIndex(columnId));
- if (node) {
- $(node).addClass(hash[row][columnId]);
- }
- }
- }
- }
+ trigger(self.onCellCssStylesChanged, { "key": key, "hash": hash });
}
function removeCellCssStyles(key) {
if (!cellCssClasses[key]) {
return;
}
- var node;
- for (var row in rowsCache) {
- if (cellCssClasses[key][row]) {
- for (var columnId in cellCssClasses[key][row]) {
- node = getCellNode(row, getColumnIndex(columnId));
- if (node) {
- $(node).removeClass(cellCssClasses[key][row][columnId]);
- }
- }
- }
- }
-
+ updateCellCssStylesOnRenderedRows(null, cellCssClasses[key]);
delete cellCssClasses[key];
+
+ trigger(self.onCellCssStylesChanged, { "key": key, "hash": null });
}
function setCellCssStyles(key, hash) {
- removeCellCssStyles(key);
- addCellCssStyles(key, hash);
+ var prevHash = cellCssClasses[key];
+
+ cellCssClasses[key] = hash;
+ updateCellCssStylesOnRenderedRows(hash, prevHash);
+
+ trigger(self.onCellCssStylesChanged, { "key": key, "hash": hash });
+ }
+
+ function getCellCssStyles(key) {
+ return cellCssClasses[key];
}
function flashCell(row, cell, speed) {
@@ -2633,6 +2653,7 @@ if (typeof Slick === "undefined") {
"onDrag": new Slick.Event(),
"onDragEnd": new Slick.Event(),
"onSelectedRowsChanged": new Slick.Event(),
+ "onCellCssStylesChanged": new Slick.Event(),
// Methods
"registerPlugin": registerPlugin,
@@ -2700,6 +2721,7 @@ if (typeof Slick === "undefined") {
"addCellCssStyles": addCellCssStyles,
"setCellCssStyles": setCellCssStyles,
"removeCellCssStyles": removeCellCssStyles,
+ "getCellCssStyles": getCellCssStyles,
"init": finishInitialization,
"destroy": destroy,

0 comments on commit 8892f4a

Please sign in to comment.