<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <title>SlickGrid example 4: Model</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="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css"/> <link rel="stylesheet" href="examples.css" type="text/css"/> <link rel="stylesheet" href="../controls/slick.columnpicker.css" type="text/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" class="ui-icon ui-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;"> <div style="width:100px;display:inline-block;" id="pcSlider"></div> </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/> <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/mleibman/SlickGrid/blob/gh-pages/examples/example4-model.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;padding:3px;color:black;"> Show tasks with title including <input type="text" id="txtSearch2"> and % at least <div style="width:100px;display:inline-block;" id="pcSlider2"></div> </div> <script src="../lib/firebugx.js"></script> <script src="../lib/jquery-1.7.min.js"></script> <script src="../lib/jquery-ui-1.8.16.custom.min.js"></script> <script src="../lib/jquery.event.drag-2.2.js"></script> <script src="../slick.core.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> 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 }, {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.Date, sortable: true}, {id: "finish", name: "Finish", field: "finish", minWidth: 60, editor: Slick.Editors.Date, sortable: true}, {id: "effort-driven", name: "Effort Driven", width: 80, minWidth: 20, maxWidth: 80, cssClass: "cell-effort-driven", field: "effortDriven", formatter: Slick.Formatters.Checkmark, editor: Slick.Editors.Checkbox, cannotTriggerInsert: true, sortable: true} ]; var options = { 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 ($.browser.msie && $.browser.version <= 8) { // 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 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) { var isLastPage = pagingInfo.pageNum == pagingInfo.totalPages - 1; var enableAddRow = isLastPage || pagingInfo.pageSize == 0; var options = grid.getOptions(); if (options.enableAddRow != enableAddRow) { grid.setOptions({enableAddRow: enableAddRow}); } }); var h_runfilters = null; // wire up the slider to apply the filter to the model $("#pcSlider,#pcSlider2").slider({ "range": "min", "slide": function (event, ui) { Slick.GlobalEditorLock.cancelCurrentEdit(); if (percentCompleteThreshold != ui.value) { window.clearTimeout(h_runfilters); h_runfilters = window.setTimeout(updateFilter, 10); percentCompleteThreshold = ui.value; } } }); // 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); }); // 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); $("#gridContainer").resizable(); }) </script> </body> </html>