Last active
December 24, 2015 07:36
-
-
Save dibley1973/60d65b8ccca8af856b93 to your computer and use it in GitHub Desktop.
Slickgrid Extension to create a simple searchable grid
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
/ File: slickgrid.extensions.js | |
/ Requires: JQuery | |
/ SlickGrid | |
*/ | |
(function ($) { | |
// Register namespace | |
$.extend(true, window, { | |
"Slick": { | |
"SimpleFilteredGridBuilder": SimpleFilteredGridBuilder | |
} | |
}); | |
function SimpleFilteredGridBuilder(options) { | |
var _grid; | |
var _columns = []; | |
var _gridOptions; | |
var _filter; | |
var _dataView; | |
var _$searchTextField; | |
var _searchString; | |
var _guard = new Guard(); | |
var _options; | |
var defaults = { | |
data: [], | |
gridSelector: "", | |
searchTextFieldSelector: "", | |
searchableColumnName: "" | |
}; | |
guardArguments(options); | |
setOptions(options); | |
function guardArguments(options) { | |
_guard.argumentNotNullOrUndefined(options.data, "data"); | |
_guard.argumentNotNullUndefinedOrEmpty(options.gridSelector, "gridSelector"); | |
_guard.argumentNotNullUndefinedOrEmpty(options.searchTextFieldSelector, "searchTextFieldSelector"); | |
_guard.argumentNotNullUndefinedOrEmpty(options.searchableColumnName, "searchableColumnName"); | |
} | |
function setOptions(options) { | |
_options = $.extend(defaults, options); | |
} | |
function buildGrid() { | |
/// <summary> | |
/// Builds the grid, once columns have been set. | |
/// </summary> | |
try { | |
initSearchField(); | |
initFilter(); | |
initDataView(); | |
initGridOptions(); | |
initGrid(); | |
} catch (e) { | |
throw new Error("Failed to initialise grid. " + e.message); | |
} | |
} | |
function initSearchField() { | |
_$searchTextField = $(_options.searchTextFieldSelector); | |
if (!textSearchFieldExists) | |
throw new Error("No text search field exists for selector '" + searchTextFieldSelector + "'"); | |
bindSearchFieldHandlers(); | |
setSearchStringFromField(); | |
} | |
function textSearchFieldExists() { | |
return _$searchTextField.length > 0; | |
} | |
function bindSearchFieldHandlers() { | |
_$searchTextField.on("keyup change", filterDataView); | |
} | |
function setSearchStringFromField() { | |
_searchString = _$searchTextField.val().toLowerCase(); | |
} | |
function withAutoColumns() { | |
/// <summary> | |
/// Automatically creates columns from the properties of the | |
/// first row object. Existing columns will be cleared first! | |
/// </summary> | |
var data = _options.data; | |
var noData = (data.length === 0); | |
if (noData) throw new Error("Cannot create auto columns when no data is present! "); | |
clearColumns(); | |
var firstRow = data[0]; | |
createColumnsFromRow(firstRow); | |
} | |
function createColumnsFromRow(row) { | |
for (var property in row) { | |
if (row.hasOwnProperty(property)) { | |
var column = createColumnFromProperty(property); | |
withColumn(column); | |
} | |
} | |
} | |
function createColumnFromProperty(property) { | |
return { | |
name: property, | |
field: property, | |
id: property | |
} | |
} | |
function clearColumns() { | |
/// <summary> | |
/// Clears the columns array. Only need to be called if columns have been | |
/// added with `withColumn(column)` | |
/// </summary> | |
_columns = []; | |
} | |
function withColumn(column) { | |
/// <summary> | |
/// Adds the specified column to the columns array. | |
/// </summary> | |
if (column == null) throw new Error("column must not be null. "); | |
_columns.push(column); | |
} | |
function getGrid() { | |
/// <summary> | |
/// Returns a reference to the grid. | |
/// </summary> | |
return _grid; | |
} | |
function filterDataView() { | |
_searchString = $(this).val().toLowerCase(); | |
_dataView.refresh(); | |
} | |
function initFilter() { | |
_filter = filter; | |
} | |
function initDataView() { | |
var dataView = new Slick.Data.DataView(); | |
dataView.beginUpdate(); | |
dataView.setItems(_options.data, _options.searchableColumnName); | |
dataView.setFilterArgs({ searchString: _searchString }); | |
dataView.setFilter(_filter); | |
dataView.endUpdate(); | |
dataView.onRowCountChanged.subscribe(onRowCountChanged); | |
dataView.onRowsChanged.subscribe(onRowsChanged); | |
_dataView = dataView; | |
} | |
function onRowsChanged(e, args) { | |
_grid.invalidateRows(args.rows); | |
_grid.render(); | |
} | |
function onRowCountChanged() { | |
_grid.updateRowCount(); | |
_grid.render(); | |
} | |
function initGridOptions() { | |
_gridOptions = { | |
forceFitColumns: true, | |
autoSizeColumns: true, | |
enableColumnReorder: false | |
} | |
} | |
function initGrid() { | |
ensureColumnsExist(); | |
_grid = new Slick.Grid( | |
_options.gridSelector, | |
_dataView, | |
_columns, | |
_gridOptions); | |
_grid.render(); | |
} | |
function ensureColumnsExist() { | |
if (_columns.length === 0) { | |
throw new Error("Columns must be set before building the grid. " + | |
"Please use the 'withColumn(column)' function to add each column. "); | |
} | |
} | |
function filter(item) { | |
var filterCriteriaMet = true; | |
var searchableString = item[_options.searchableColumnName].toLowerCase(); | |
var orSearchDelimiter = ","; | |
var andSearchDelimiter = " "; | |
var searchString = _searchString; | |
var performOrSearch = (searchString.indexOf(orSearchDelimiter) !== -1); | |
var performAndSearch = (searchString.indexOf(andSearchDelimiter) !== -1); | |
if (performOrSearch) { | |
//Option A - When the search string includes a comma, treat it as an OR search, e.g. expand the results | |
filterCriteriaMet = orSearchHasMatch(searchableString); | |
} else if (performAndSearch) { | |
// Option B - When the search string includes a space, treat it as an AND search, e.g. restrict the results | |
filterCriteriaMet = andSearchHasMatch(searchableString); | |
} else { | |
// Option C - Single word exact match | |
var singleWordExactMatchNotFound = (searchString !== "" && searchableString.indexOf(searchString) === -1); | |
if (singleWordExactMatchNotFound) filterCriteriaMet = false; | |
} | |
return filterCriteriaMet; | |
} | |
function orSearchHasMatch(searchableString) { | |
var matchFound = false; | |
var searchStringItems = _searchString.split(","); | |
for (var index = 0; index < searchStringItems.length; index++) { | |
var trimmedItem = searchStringItems[index].trim(); | |
var notEmpty = trimmedItem !== ""; | |
var searchableStringContainsTrimmedItem = (searchableString.indexOf(trimmedItem) !== -1); | |
var matchOnTrimmedOrItemNotMet = (notEmpty && searchableStringContainsTrimmedItem); | |
if (matchOnTrimmedOrItemNotMet) { | |
matchFound = true; | |
break; | |
} | |
} | |
return matchFound; | |
} | |
function andSearchHasMatch(searchableString) { | |
var filterCriteriaMet = true; | |
var searchStringItems = _searchString.split(" "); | |
for (var index = 0; index < searchStringItems.length; index++) { | |
var trimmedItem = searchStringItems[index].trim(); | |
var notEmpty = trimmedItem !== ""; | |
var searchableStringDoesnotContainTrimmedItem = (searchableString.indexOf(trimmedItem) === -1); | |
var matchOnTrimmedAndItemNotMet = (notEmpty && searchableStringDoesnotContainTrimmedItem); | |
if (matchOnTrimmedAndItemNotMet) { | |
filterCriteriaMet = false; | |
break; | |
} | |
} | |
return filterCriteriaMet; | |
} | |
return { // public interface | |
clearColumns: clearColumns, | |
buildGrid: buildGrid, | |
getGrid: getGrid, | |
withColumn: withColumn, | |
withAutoColumns: withAutoColumns | |
} | |
} | |
function Guard() { | |
var argumentNotNullOrUndefined = function (value, argumentName) { | |
if (value === undefined || value === null) | |
throw new Error("[" + argumentName + "] must not be null or undefined! "); | |
} | |
var argumentNotNullUndefinedOrEmpty = function (value, argumentName) { | |
if (value === undefined || value === null || | |
(value.length && value.length === 0)) | |
throw new Error("[" + argumentName + "] must not be null, undefined or empty! "); | |
} | |
return { // public interface | |
argumentNotNullOrUndefined: argumentNotNullOrUndefined, | |
argumentNotNullUndefinedOrEmpty: argumentNotNullUndefinedOrEmpty | |
}; | |
} | |
})(jQuery); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<!-- SlickGrid, JQuery and form scripts here --> | |
</head> | |
<body> | |
<div> | |
<input id="GridSearch" type="text"> | |
</div> | |
<div> | |
<div id="GridContainer"></div> | |
</div> | |
</body> | |
<html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var gridBuilderOptions = { | |
data: myFunkyJsonData, | |
gridSelector: "#GridContainer", | |
searchTextFieldSelector: "#GridSearch", | |
searchableColumnName: "SearchField" | |
}; | |
var gridBuilder = new Slick.SimpleFilteredGridBuilder(gridBuilderOptions); | |
gridBuilder.withColumn({ name: "Field 1", field: "Field1", minWidth: 100, maxWidth: 200 }); | |
gridBuilder.withColumn({ name: "Field 2", field: "Field2"); | |
gridBuilder.withColumn({ name: "Field 3", field: "Field3", formatter: Slick.Formatters.YesNo); | |
gridBuilder.withColumn({ name: "SearchField", field: "SearchField", maxWidth: 1); | |
gridBuilder.buildGrid(); | |
this.grid = gridBuilder.getGrid(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment