summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--controls/slick.columnpicker.css32
-rw-r--r--controls/slick.columnpicker.js209
-rw-r--r--controls/slick.pager.css63
-rw-r--r--controls/slick.pager.js261
-rw-r--r--examples/example-checkbox-row-select.html110
-rw-r--r--examples/example-colspan.html154
-rw-r--r--examples/example-composite-editor-item-details.html457
-rw-r--r--examples/example-custom-column-value-extractor.html126
-rw-r--r--examples/example-grouping.html699
-rw-r--r--examples/example-header-row.html269
-rw-r--r--examples/example-optimizing-dataview.html297
-rw-r--r--examples/example-spreadsheet.html330
-rw-r--r--examples/example1-simple.html113
-rw-r--r--examples/example10-async-post-render.html254
-rw-r--r--examples/example11-autoheight.html131
-rw-r--r--examples/example12-fillbrowser.html183
-rw-r--r--examples/example13-getItem-sorting.html197
-rw-r--r--examples/example14-highlighting.html299
-rw-r--r--examples/example2-formatters.html140
-rw-r--r--examples/example3-editing.html185
-rw-r--r--examples/example3a-compound-editors.html281
-rw-r--r--examples/example3b-editing-with-undo.html213
-rw-r--r--examples/example4-model.html745
-rw-r--r--examples/example5-collapsing.html531
-rw-r--r--examples/example6-ajax-loading.html296
-rw-r--r--examples/example7-events.html17
-rw-r--r--examples/example8-alternative-display.html344
-rw-r--r--examples/example9-row-reordering.html611
-rw-r--r--examples/examples.css253
-rw-r--r--examples/slick-default-theme.css73
-rw-r--r--examples/slick.compositeeditor.js404
-rw-r--r--plugins/slick.autotooltips.js81
-rw-r--r--plugins/slick.cellcopymanager.js144
-rw-r--r--plugins/slick.cellrangedecorator.js109
-rw-r--r--plugins/slick.cellrangeselector.js196
-rw-r--r--plugins/slick.cellselectionmodel.js154
-rw-r--r--plugins/slick.checkboxselectcolumn.js231
-rw-r--r--plugins/slick.rowmovemanager.js227
-rw-r--r--plugins/slick.rowselectionmodel.js319
-rw-r--r--slick.core.js756
-rw-r--r--slick.dataview.js1349
-rw-r--r--slick.editors.js1228
-rw-r--r--slick.grid.css163
-rw-r--r--slick.grid.js4582
-rw-r--r--slick.groupitemmetadataprovider.js245
-rw-r--r--slick.remotemodel.js281
46 files changed, 9268 insertions, 9074 deletions
diff --git a/controls/slick.columnpicker.css b/controls/slick.columnpicker.css
index aaf5fbe..a2845cc 100644
--- a/controls/slick.columnpicker.css
+++ b/controls/slick.columnpicker.css
@@ -1,30 +1,30 @@
.slick-columnpicker {
- border: 1px solid #718BB7;
- background: #f0f0f0;
- padding: 6px;
- -moz-box-shadow: 2px 2px 2px silver;
- -webkit-box-shadow: 2px 2px 2px silver;
- min-width: 100px;
- cursor: default;
+ border: 1px solid #718BB7;
+ background: #f0f0f0;
+ padding: 6px;
+ -moz-box-shadow: 2px 2px 2px silver;
+ -webkit-box-shadow: 2px 2px 2px silver;
+ min-width: 100px;
+ cursor: default;
}
.slick-columnpicker li {
- list-style: none;
- margin: 0;
- padding: 0;
- background: none;
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ background: none;
}
.slick-columnpicker input {
- margin: 4px;
+ margin: 4px;
}
.slick-columnpicker li a {
- display: block;
- padding: 4px;
- font-weight: bold;
+ display: block;
+ padding: 4px;
+ font-weight: bold;
}
.slick-columnpicker li a:hover {
- background: white;
+ background: white;
} \ No newline at end of file
diff --git a/controls/slick.columnpicker.js b/controls/slick.columnpicker.js
index 4b84e0d..ca95211 100644
--- a/controls/slick.columnpicker.js
+++ b/controls/slick.columnpicker.js
@@ -1,105 +1,106 @@
-(function($) {
- function SlickColumnPicker(columns,grid,options)
- {
- var $menu;
-
- var defaults = {
- fadeSpeed: 250
- };
-
- function init() {
- grid.onHeaderContextMenu.subscribe(handleHeaderContextMenu);
- options = $.extend({}, defaults, options);
-
- $menu = $("<span class='slick-columnpicker' style='display:none;position:absolute;z-index:20;' />").appendTo(document.body);
-
- $menu.bind("mouseleave", function(e) { $(this).fadeOut(options.fadeSpeed) });
- $menu.bind("click", updateColumn);
-
- }
-
- function handleHeaderContextMenu(e, args)
- {
- e.preventDefault();
- $menu.empty();
-
- var $li, $input;
- for (var i=0; i<columns.length; i++) {
- $li = $("<li />").appendTo($menu);
-
- $input = $("<input type='checkbox' />")
- .attr("id", "columnpicker_" + i)
- .data("id", columns[i].id)
- .appendTo($li);
-
- if (grid.getColumnIndex(columns[i].id) != null)
- $input.attr("checked","checked");
-
- $("<label for='columnpicker_" + i + "' />")
- .text(columns[i].name)
- .appendTo($li);
- }
-
- $("<hr/>").appendTo($menu);
- $li = $("<li />").appendTo($menu);
- $input = $("<input type='checkbox' id='autoresize' />").appendTo($li);
- $("<label for='autoresize'>Force Fit Columns</label>").appendTo($li);
- if (grid.getOptions().forceFitColumns)
- $input.attr("checked", "checked");
-
- $li = $("<li />").appendTo($menu);
- $input = $("<input type='checkbox' id='syncresize' />").appendTo($li);
- $("<label for='syncresize'>Synchronous Resizing</label>").appendTo($li);
- if (grid.getOptions().syncColumnCellResize)
- $input.attr("checked", "checked");
-
- $menu
- .css("top", e.pageY - 10)
- .css("left", e.pageX - 10)
- .fadeIn(options.fadeSpeed);
- }
-
- function updateColumn(e)
- {
- if (e.target.id == 'autoresize') {
- if (e.target.checked) {
- grid.setOptions({forceFitColumns: true});
- grid.autosizeColumns();
- } else {
- grid.setOptions({forceFitColumns: false});
- }
- return;
- }
-
- if (e.target.id == 'syncresize') {
- if (e.target.checked) {
- grid.setOptions({syncColumnCellResize: true});
- } else {
- grid.setOptions({syncColumnCellResize: false});
- }
- return;
- }
-
- if ($(e.target).is(":checkbox")) {
- if ($menu.find(":checkbox:checked").length == 0) {
- $(e.target).attr("checked","checked");
- return;
- }
-
- var visibleColumns = [];
- $menu.find(":checkbox[id^=columnpicker]").each(function(i,e) {
- if ($(this).is(":checked")) {
- visibleColumns.push(columns[i]);
- }
- });
- grid.setColumns(visibleColumns);
- }
- }
-
-
- init();
- }
-
- // Slick.Controls.ColumnPicker
- $.extend(true, window, { Slick: { Controls: { ColumnPicker: SlickColumnPicker }}});
+(function ($) {
+ function SlickColumnPicker(columns, grid, options) {
+ var $menu;
+
+ var defaults = {
+ fadeSpeed:250
+ };
+
+ function init() {
+ grid.onHeaderContextMenu.subscribe(handleHeaderContextMenu);
+ options = $.extend({}, defaults, options);
+
+ $menu = $("<span class='slick-columnpicker' style='display:none;position:absolute;z-index:20;' />").appendTo(document.body);
+
+ $menu.bind("mouseleave", function (e) {
+ $(this).fadeOut(options.fadeSpeed)
+ });
+ $menu.bind("click", updateColumn);
+
+ }
+
+ function handleHeaderContextMenu(e, args) {
+ e.preventDefault();
+ $menu.empty();
+
+ var $li, $input;
+ for (var i = 0; i < columns.length; i++) {
+ $li = $("<li />").appendTo($menu);
+
+ $input = $("<input type='checkbox' />")
+ .attr("id", "columnpicker_" + i)
+ .data("id", columns[i].id)
+ .appendTo($li);
+
+ if (grid.getColumnIndex(columns[i].id) != null) {
+ $input.attr("checked", "checked");
+ }
+
+ $("<label for='columnpicker_" + i + "' />")
+ .text(columns[i].name)
+ .appendTo($li);
+ }
+
+ $("<hr/>").appendTo($menu);
+ $li = $("<li />").appendTo($menu);
+ $input = $("<input type='checkbox' id='autoresize' />").appendTo($li);
+ $("<label for='autoresize'>Force Fit Columns</label>").appendTo($li);
+ if (grid.getOptions().forceFitColumns) {
+ $input.attr("checked", "checked");
+ }
+
+ $li = $("<li />").appendTo($menu);
+ $input = $("<input type='checkbox' id='syncresize' />").appendTo($li);
+ $("<label for='syncresize'>Synchronous Resizing</label>").appendTo($li);
+ if (grid.getOptions().syncColumnCellResize) {
+ $input.attr("checked", "checked");
+ }
+
+ $menu
+ .css("top", e.pageY - 10)
+ .css("left", e.pageX - 10)
+ .fadeIn(options.fadeSpeed);
+ }
+
+ function updateColumn(e) {
+ if (e.target.id == 'autoresize') {
+ if (e.target.checked) {
+ grid.setOptions({forceFitColumns:true});
+ grid.autosizeColumns();
+ } else {
+ grid.setOptions({forceFitColumns:false});
+ }
+ return;
+ }
+
+ if (e.target.id == 'syncresize') {
+ if (e.target.checked) {
+ grid.setOptions({syncColumnCellResize:true});
+ } else {
+ grid.setOptions({syncColumnCellResize:false});
+ }
+ return;
+ }
+
+ if ($(e.target).is(":checkbox")) {
+ if ($menu.find(":checkbox:checked").length == 0) {
+ $(e.target).attr("checked", "checked");
+ return;
+ }
+
+ var visibleColumns = [];
+ $menu.find(":checkbox[id^=columnpicker]").each(function (i, e) {
+ if ($(this).is(":checked")) {
+ visibleColumns.push(columns[i]);
+ }
+ });
+ grid.setColumns(visibleColumns);
+ }
+ }
+
+ init();
+ }
+
+ // Slick.Controls.ColumnPicker
+ $.extend(true, window, { Slick:{ Controls:{ ColumnPicker:SlickColumnPicker }}});
})(jQuery);
diff --git a/controls/slick.pager.css b/controls/slick.pager.css
index ec40122..e360ec6 100644
--- a/controls/slick.pager.css
+++ b/controls/slick.pager.css
@@ -1,48 +1,41 @@
-.slick-pager
-{
- width: 100%;
- height: 26px;
- border: 1px solid gray;
- border-top: 0;
- background: url('../images/header-columns-bg.gif') repeat-x center bottom;
- vertical-align: middle;
+.slick-pager {
+ width: 100%;
+ height: 26px;
+ border: 1px solid gray;
+ border-top: 0;
+ background: url('../images/header-columns-bg.gif') repeat-x center bottom;
+ vertical-align: middle;
}
-.slick-pager .slick-pager-status
-{
- display: inline-block;
- padding: 6px;
+.slick-pager .slick-pager-status {
+ display: inline-block;
+ padding: 6px;
}
-.slick-pager .ui-icon-container
-{
- display: inline-block;
- margin: 2px;
- border-color: gray;
+.slick-pager .ui-icon-container {
+ display: inline-block;
+ margin: 2px;
+ border-color: gray;
}
-.slick-pager .slick-pager-nav
-{
- display: inline-block;
- float: left;
- padding: 2px;
+.slick-pager .slick-pager-nav {
+ display: inline-block;
+ float: left;
+ padding: 2px;
}
-.slick-pager .slick-pager-settings
-{
- display: block;
- float: right;
- padding: 2px;
+.slick-pager .slick-pager-settings {
+ display: block;
+ float: right;
+ padding: 2px;
}
-.slick-pager .slick-pager-settings *
-{
- vertical-align: middle;
+.slick-pager .slick-pager-settings * {
+ vertical-align: middle;
}
-.slick-pager .slick-pager-settings a
-{
- padding: 2px;
- text-decoration: underline;
- cursor: pointer;
+.slick-pager .slick-pager-settings a {
+ padding: 2px;
+ text-decoration: underline;
+ cursor: pointer;
}
diff --git a/controls/slick.pager.js b/controls/slick.pager.js
index ce1921d..5da5c25 100644
--- a/controls/slick.pager.js
+++ b/controls/slick.pager.js
@@ -1,148 +1,151 @@
-(function($) {
- function SlickGridPager(dataView, grid, $container)
- {
- var $status;
-
- function init()
- {
- dataView.onPagingInfoChanged.subscribe(function(e,pagingInfo) {
- updatePager(pagingInfo);
- });
-
- constructPagerUI();
- updatePager(dataView.getPagingInfo());
- }
+(function ($) {
+ function SlickGridPager(dataView, grid, $container) {
+ var $status;
- function getNavState()
- {
- var cannotLeaveEditMode = !Slick.GlobalEditorLock.commitCurrentEdit();
- var pagingInfo = dataView.getPagingInfo();
- var lastPage = Math.floor(pagingInfo.totalRows/pagingInfo.pageSize);
-
- return {
- canGotoFirst: !cannotLeaveEditMode && pagingInfo.pageSize != 0 && pagingInfo.pageNum > 0,
- canGotoLast: !cannotLeaveEditMode && pagingInfo.pageSize != 0 && pagingInfo.pageNum != lastPage,
- canGotoPrev: !cannotLeaveEditMode && pagingInfo.pageSize != 0 && pagingInfo.pageNum > 0,
- canGotoNext: !cannotLeaveEditMode && pagingInfo.pageSize != 0 && pagingInfo.pageNum < lastPage,
- pagingInfo: pagingInfo,
- lastPage: lastPage
- }
- }
+ function init() {
+ dataView.onPagingInfoChanged.subscribe(function (e, pagingInfo) {
+ updatePager(pagingInfo);
+ });
- function setPageSize(n)
- {
- dataView.setRefreshHints({
- isFilterUnchanged: true
- });
- dataView.setPagingOptions({pageSize:n});
- }
+ constructPagerUI();
+ updatePager(dataView.getPagingInfo());
+ }
- function gotoFirst()
- {
- if (getNavState().canGotoFirst)
- dataView.setPagingOptions({pageNum: 0});
- }
+ function getNavState() {
+ var cannotLeaveEditMode = !Slick.GlobalEditorLock.commitCurrentEdit();
+ var pagingInfo = dataView.getPagingInfo();
+ var lastPage = Math.floor(pagingInfo.totalRows / pagingInfo.pageSize);
+
+ return {
+ canGotoFirst:!cannotLeaveEditMode && pagingInfo.pageSize != 0 && pagingInfo.pageNum > 0,
+ canGotoLast:!cannotLeaveEditMode && pagingInfo.pageSize != 0 && pagingInfo.pageNum != lastPage,
+ canGotoPrev:!cannotLeaveEditMode && pagingInfo.pageSize != 0 && pagingInfo.pageNum > 0,
+ canGotoNext:!cannotLeaveEditMode && pagingInfo.pageSize != 0 && pagingInfo.pageNum < lastPage,
+ pagingInfo:pagingInfo,
+ lastPage:lastPage
+ }
+ }
- function gotoLast()
- {
- var state = getNavState();
- if (state.canGotoLast)
- dataView.setPagingOptions({pageNum: state.lastPage});
- }
+ function setPageSize(n) {
+ dataView.setRefreshHints({
+ isFilterUnchanged:true
+ });
+ dataView.setPagingOptions({pageSize:n});
+ }
- function gotoPrev()
- {
- var state = getNavState();
- if (state.canGotoPrev)
- dataView.setPagingOptions({pageNum: state.pagingInfo.pageNum-1});
- }
+ function gotoFirst() {
+ if (getNavState().canGotoFirst) {
+ dataView.setPagingOptions({pageNum:0});
+ }
+ }
- function gotoNext()
- {
- var state = getNavState();
- if (state.canGotoNext)
- dataView.setPagingOptions({pageNum: state.pagingInfo.pageNum+1});
- }
+ function gotoLast() {
+ var state = getNavState();
+ if (state.canGotoLast) {
+ dataView.setPagingOptions({pageNum:state.lastPage});
+ }
+ }
+
+ function gotoPrev() {
+ var state = getNavState();
+ if (state.canGotoPrev) {
+ dataView.setPagingOptions({pageNum:state.pagingInfo.pageNum - 1});
+ }
+ }
+
+ function gotoNext() {
+ var state = getNavState();
+ if (state.canGotoNext) {
+ dataView.setPagingOptions({pageNum:state.pagingInfo.pageNum + 1});
+ }
+ }
- function constructPagerUI()
- {
- $container.empty();
-
- var $nav = $("<span class='slick-pager-nav' />").appendTo($container);
- var $settings = $("<span class='slick-pager-settings' />").appendTo($container);
- $status = $("<span class='slick-pager-status' />").appendTo($container);
-
- $settings
- .append("<span class='slick-pager-settings-expanded' style='display:none'>Show: <a data=0>All</a><a data='-1'>Auto</a><a data=25>25</a><a data=50>50</a><a data=100>100</a></span>");
-
- $settings.find("a[data]").click(function(e) {
- var pagesize = $(e.target).attr("data");
- if (pagesize != undefined)
- {
- if (pagesize == -1)
- {
- var vp = grid.getViewport();
- setPageSize(vp.bottom-vp.top);
- }
- else
- setPageSize(parseInt(pagesize));
- }
- });
-
- var icon_prefix = "<span class='ui-state-default ui-corner-all ui-icon-container'><span class='ui-icon ";
- var icon_suffix = "' /></span>";
-
- $(icon_prefix + "ui-icon-lightbulb" + icon_suffix)
- .click(function() { $(".slick-pager-settings-expanded").toggle() })
- .appendTo($settings);
-
- $(icon_prefix + "ui-icon-seek-first" + icon_suffix)
- .click(gotoFirst)
- .appendTo($nav);
-
- $(icon_prefix + "ui-icon-seek-prev" + icon_suffix)
- .click(gotoPrev)
- .appendTo($nav);
-
- $(icon_prefix + "ui-icon-seek-next" + icon_suffix)
- .click(gotoNext)
- .appendTo($nav);
-
- $(icon_prefix + "ui-icon-seek-end" + icon_suffix)
- .click(gotoLast)
- .appendTo($nav);
-
- $container.find(".ui-icon-container")
- .hover(function() {
- $(this).toggleClass("ui-state-hover");
- });
-
- $container.children().wrapAll("<div class='slick-pager' />");
+ function constructPagerUI() {
+ $container.empty();
+
+ var $nav = $("<span class='slick-pager-nav' />").appendTo($container);
+ var $settings = $("<span class='slick-pager-settings' />").appendTo($container);
+ $status = $("<span class='slick-pager-status' />").appendTo($container);
+
+ $settings
+ .append("<span class='slick-pager-settings-expanded' style='display:none'>Show: <a data=0>All</a><a data='-1'>Auto</a><a data=25>25</a><a data=50>50</a><a data=100>100</a></span>");
+
+ $settings.find("a[data]").click(function (e) {
+ var pagesize = $(e.target).attr("data");
+ if (pagesize != undefined) {
+ if (pagesize == -1) {
+ var vp = grid.getViewport();
+ setPageSize(vp.bottom - vp.top);
+ }
+ else {
+ setPageSize(parseInt(pagesize));
+ }
}
+ });
+ var icon_prefix = "<span class='ui-state-default ui-corner-all ui-icon-container'><span class='ui-icon ";
+ var icon_suffix = "' /></span>";
- function updatePager(pagingInfo)
- {
- var state = getNavState();
+ $(icon_prefix + "ui-icon-lightbulb" + icon_suffix)
+ .click(function () {
+ $(".slick-pager-settings-expanded").toggle()
+ })
+ .appendTo($settings);
- $container.find(".slick-pager-nav span").removeClass("ui-state-disabled");
- if (!state.canGotoFirst) $container.find(".ui-icon-seek-first").addClass("ui-state-disabled");
- if (!state.canGotoLast) $container.find(".ui-icon-seek-end").addClass("ui-state-disabled");
- if (!state.canGotoNext) $container.find(".ui-icon-seek-next").addClass("ui-state-disabled");
- if (!state.canGotoPrev) $container.find(".ui-icon-seek-prev").addClass("ui-state-disabled");
+ $(icon_prefix + "ui-icon-seek-first" + icon_suffix)
+ .click(gotoFirst)
+ .appendTo($nav);
+ $(icon_prefix + "ui-icon-seek-prev" + icon_suffix)
+ .click(gotoPrev)
+ .appendTo($nav);
- if (pagingInfo.pageSize == 0)
- $status.text("Showing all " + pagingInfo.totalRows + " rows");
- else
- $status.text("Showing page " + (pagingInfo.pageNum+1) + " of " + (Math.floor(pagingInfo.totalRows/pagingInfo.pageSize)+1));
- }
+ $(icon_prefix + "ui-icon-seek-next" + icon_suffix)
+ .click(gotoNext)
+ .appendTo($nav);
+ $(icon_prefix + "ui-icon-seek-end" + icon_suffix)
+ .click(gotoLast)
+ .appendTo($nav);
+ $container.find(".ui-icon-container")
+ .hover(function () {
+ $(this).toggleClass("ui-state-hover");
+ });
- init();
+ $container.children().wrapAll("<div class='slick-pager' />");
}
- // Slick.Controls.Pager
- $.extend(true, window, { Slick: { Controls: { Pager: SlickGridPager }}});
+
+ function updatePager(pagingInfo) {
+ var state = getNavState();
+
+ $container.find(".slick-pager-nav span").removeClass("ui-state-disabled");
+ if (!state.canGotoFirst) {
+ $container.find(".ui-icon-seek-first").addClass("ui-state-disabled");
+ }
+ if (!state.canGotoLast) {
+ $container.find(".ui-icon-seek-end").addClass("ui-state-disabled");
+ }
+ if (!state.canGotoNext) {
+ $container.find(".ui-icon-seek-next").addClass("ui-state-disabled");
+ }
+ if (!state.canGotoPrev) {
+ $container.find(".ui-icon-seek-prev").addClass("ui-state-disabled");
+ }
+
+
+ if (pagingInfo.pageSize == 0) {
+ $status.text("Showing all " + pagingInfo.totalRows + " rows");
+ }
+ else {
+ $status.text("Showing page " + (pagingInfo.pageNum + 1) + " of " + (Math.floor(pagingInfo.totalRows / pagingInfo.pageSize) + 1));
+ }
+ }
+
+ init();
+ }
+
+ // Slick.Controls.Pager
+ $.extend(true, window, { Slick:{ Controls:{ Pager:SlickGridPager }}});
})(jQuery);
diff --git a/examples/example-checkbox-row-select.html b/examples/example-checkbox-row-select.html
index 99b78d1..e1d0124 100644
--- a/examples/example-checkbox-row-select.html
+++ b/examples/example-checkbox-row-select.html
@@ -1,31 +1,31 @@
<!DOCTYPE HTML>
<html>
<head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- <style>
- .slick-cell-checkboxsel {
- background: #f0f0f0;
- border-right-color: silver;
- border-right-style: solid;
- }
- </style>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <link rel="stylesheet" href="../slick.grid.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" />
+ <style>
+ .slick-cell-checkboxsel {
+ background: #f0f0f0;
+ border-right-color: silver;
+ border-right-style: solid;
+ }
+ </style>
</head>
<body>
- <div style="position:relative">
- <div style="width:600px;">
- <div id="myGrid" style="width:100%;height:500px;"></div>
- </div>
+<div style="position:relative">
+ <div style="width:600px;">
+ <div id="myGrid" style="width:100%;height:500px;"></div>
+ </div>
- <div class="options-panel">
- <h2>Demonstrates:</h2>
- <ul>
- <li>Checkbox row select column</li>
- </ul>
- </div>
- </div>
+ <div class="options-panel">
+ <h2>Demonstrates:</h2>
+ <ul>
+ <li>Checkbox row select column</li>
+ </ul>
+ </div>
+</div>
<script src="../lib/firebugx.js"></script>
@@ -45,46 +45,42 @@
<script src="../slick.grid.js"></script>
<script>
- var grid;
- var data = [];
- var options = {
- editable: true,
- enableCellNavigation: true,
- asyncEditorLoading: false,
- autoEdit: false
- };
- var columns = [];
+ var grid;
+ var data = [];
+ var options = {
+ editable:true,
+ enableCellNavigation:true,
+ asyncEditorLoading:false,
+ autoEdit:false
+ };
+ var columns = [];
+ $(function () {
+ for (var i = 0; i < 100; i++) {
+ var d = (data[i] = {});
+ d[0] = "Row " + i;
+ }
- $(function()
- {
- for (var i=0; i<100; i++) {
- var d = (data[i] = {});
- d[0] = "Row " + i;
- }
+ var checkboxSelector = new Slick.CheckboxSelectColumn({
+ cssClass:"slick-cell-checkboxsel"
+ });
- var checkboxSelector = new Slick.CheckboxSelectColumn({
- cssClass: "slick-cell-checkboxsel"
- });
+ columns.push(checkboxSelector.getColumnDefinition());
- columns.push(checkboxSelector.getColumnDefinition());
+ for (var i = 0; i < 5; i++) {
+ columns.push({
+ id:i,
+ name:String.fromCharCode("A".charCodeAt(0) + i),
+ field:i,
+ width:100,
+ editor:TextCellEditor
+ });
+ }
- for (var i = 0; i < 5; i++) {
- columns.push({
- id: i,
- name: String.fromCharCode("A".charCodeAt(0) + i),
- field: i,
- width: 100,
- editor: TextCellEditor
- });
- }
-
-
- grid = new Slick.Grid("#myGrid", data, columns, options);
- grid.setSelectionModel(new Slick.RowSelectionModel({selectActiveRow:false}));
- grid.registerPlugin(checkboxSelector);
-
- })
+ grid = new Slick.Grid("#myGrid", data, columns, options);
+ grid.setSelectionModel(new Slick.RowSelectionModel({selectActiveRow:false}));
+ grid.registerPlugin(checkboxSelector);
+ })
</script>
</body>
</html>
diff --git a/examples/example-colspan.html b/examples/example-colspan.html
index c6a2c81..4f17f47 100644
--- a/examples/example-colspan.html
+++ b/examples/example-colspan.html
@@ -1,89 +1,89 @@
<!DOCTYPE HTML>
<html>
- <head>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- </head>
- <body>
- <table width="100%">
- <tr>
- <td valign="top" width="50%">
- <div id="myGrid" style="width:600px;height:500px;"></div>
- </td>
- <td valign="top">
- <h2>Demonstrates:</h2>
- <ul>
- <li>column span</li>
- </ul>
- </td>
- </tr>
- </table>
+<head>
+ <link rel="stylesheet" href="../slick.grid.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" />
+</head>
+<body>
+<table width="100%">
+ <tr>
+ <td valign="top" width="50%">
+ <div id="myGrid" style="width:600px;height:500px;"></div>
+ </td>
+ <td valign="top">
+ <h2>Demonstrates:</h2>
+ <ul>
+ <li>column span</li>
+ </ul>
+ </td>
+ </tr>
+</table>
- <script src="../lib/jquery-1.7.min.js"></script>
- <script src="../lib/jquery.event.drag-2.0.min.js"></script>
+<script src="../lib/jquery-1.7.min.js"></script>
+<script src="../lib/jquery.event.drag-2.0.min.js"></script>
- <script src="../slick.core.js"></script>
- <script src="../plugins/slick.cellrangedecorator.js"></script>
- <script src="../plugins/slick.cellrangeselector.js"></script>
- <script src="../plugins/slick.cellselectionmodel.js"></script>
- <script src="../slick.grid.js"></script>
+<script src="../slick.core.js"></script>
+<script src="../plugins/slick.cellrangedecorator.js"></script>
+<script src="../plugins/slick.cellrangeselector.js"></script>
+<script src="../plugins/slick.cellselectionmodel.js"></script>
+<script src="../slick.grid.js"></script>
- <script>
- var grid;
+<script>
+ var grid;
- var columns = [
- {id:"title", name:"Title", field:"title"},
- {id:"duration", name:"Duration", field:"duration"},
- {id:"%", name:"% Complete", field:"percentComplete", selectable:false},
- {id:"start", name:"Start", field:"start"},
- {id:"finish", name:"Finish", field:"finish"},
- {id:"effort-driven", name:"Effort Driven", field:"effortDriven"}
- ];
+ var columns = [
+ {id:"title", name:"Title", field:"title"},
+ {id:"duration", name:"Duration", field:"duration"},
+ {id:"%", name:"% Complete", field:"percentComplete", selectable:false},
+ {id:"start", name:"Start", field:"start"},
+ {id:"finish", name:"Finish", field:"finish"},
+ {id:"effort-driven", name:"Effort Driven", field:"effortDriven"}
+ ];
- var options = {
- enableCellNavigation: true,
- enableColumnReorder: false
- };
+ var options = {
+ enableCellNavigation:true,
+ enableColumnReorder:false
+ };
- $(function() {
- var data = [];
- for (var i = 0; i < 10; i++) {
- data[i] = {
- title: "Task " + i,
- duration: "5 days",
- percentComplete: Math.round(Math.random() * 100),
- start: "01/01/2009",
- finish: "01/05/2009",
- effortDriven: (i % 5 == 0)
- };
- }
+ $(function () {
+ var data = [];
+ for (var i = 0; i < 10; i++) {
+ data[i] = {
+ title:"Task " + i,
+ duration:"5 days",
+ percentComplete:Math.round(Math.random() * 100),
+ start:"01/01/2009",
+ finish:"01/05/2009",
+ effortDriven:(i % 5 == 0)
+ };
+ }
- data.getItemMetadata = function (row) {
- if (row % 2 === 1) {
- return {
- "columns": {
- "duration": {
- "colspan": 3
- }
- }
- };
- }
- else {
- return {
- "columns": {
- 0: {
- "colspan": "*"
- }
- }
- };
- }
- };
+ data.getItemMetadata = function (row) {
+ if (row % 2 === 1) {
+ return {
+ "columns":{
+ "duration":{
+ "colspan":3
+ }
+ }
+ };
+ }
+ else {
+ return {
+ "columns":{
+ 0:{
+ "colspan":"*"
+ }
+ }
+ };
+ }
+ };
- grid = new Slick.Grid("#myGrid", data, columns, options);
+ grid = new Slick.Grid("#myGrid", data, columns, options);
- grid.setSelectionModel(new Slick.CellSelectionModel());
- })
- </script>
- </body>
+ grid.setSelectionModel(new Slick.CellSelectionModel());
+ })
+</script>
+</body>
</html>
diff --git a/examples/example-composite-editor-item-details.html b/examples/example-composite-editor-item-details.html
index 4b07f8d..b27399c 100644
--- a/examples/example-composite-editor-item-details.html
+++ b/examples/example-composite-editor-item-details.html
@@ -1,233 +1,236 @@
<!DOCTYPE HTML>
<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <title>SlickGrid example: CompositeEditor</title>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- <style>
- .cell-title {
- font-weight: bold;
- }
-
- .cell-effort-driven {
- text-align: center;
- }
-
- .item-details-form {
- z-index: 10000;
- display:inline-block;
- border:1px solid black;
- margin:8px;
- padding:10px;
- background: #efefef;
- -moz-box-shadow: 0px 0px 15px black;
- -webkit-box-shadow: 0px 0px 15px black;
- box-shadow: 0px 0px 15px black;
-
- position:absolute;
- top: 10px;
- left: 150px;
- }
-
- .item-details-form-buttons {
- float: right;
- }
-
- .item-details-row {
-
- }
-
- .item-details-label {
- margin-left:10px;
- margin-top:20px;
- display:block;
- font-weight:bold;
- }
-
- .item-details-editor-container {
- width:200px;
- height:20px;
- border:1px solid silver;
- background:white;
- display:block;
- margin:10px;
- margin-top:4px;
- padding:0;
- padding-left:4px;
- padding-right:4px;
- }
- </style>
- </head>
- <body>
- <div style="position:relative">
- <div style="width:600px;">
- <div id="myGrid" style="width:100%;height:500px;"></div>
- </div>
-
- <div class="options-panel">
- <h2>Demonstrates:</h2>
- <ul>
- <li>using a CompositeEditor to implement detached item edit form</li>
- </ul>
-
- <h2>Options:</h2>
- <button onclick="openDetails()">Open Item Edit for active row</button>
- </div>
- </div>
-
- <script id="itemDetailsTemplate" type="text/x-jquery-tmpl">
- <div class='item-details-form'>
- {{each columns}}
- <div class='item-details-label'>
- ${name}
- </div>
- <div class='item-details-editor-container' data-editorid='${id}'></div>
- {{/each}}
-
- <hr/>
- <div class='item-details-form-buttons'>
- <button data-action='save'>Save</button>
- <button data-action='cancel'>Cancel</button>
- </div>
- </div>
- </script>
-
-
-
- <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.0.min.js"></script>
- <script src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>
-
- <script src="../slick.core.js"></script>
- <script src="../plugins/slick.cellrangeselector.js"></script>
- <script src="../plugins/slick.cellselectionmodel.js"></script>
- <script src="../slick.editors.js"></script>
- <script src="../slick.grid.js"></script>
- <script src="slick.compositeeditor.js"></script>
-
- <script>
- 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};
- }
-
- var grid;
- var data = [];
- var columns = [
- {id:"title", name:"Title", field:"title", width:120, cssClass:"cell-title", editor:TextCellEditor, validator:requiredFieldValidator},
- {id:"desc", name:"Description", field:"description", width:100, editor:TextCellEditor},
- {id:"duration", name:"Duration", field:"duration", editor:TextCellEditor},
- {id:"%", name:"% Complete", field:"percentComplete", width:80, resizable:false, formatter:GraphicalPercentCompleteCellFormatter, editor:PercentCompleteCellEditor},
- {id:"start", name:"Start", field:"start", minWidth:60, editor:DateCellEditor},
- {id:"finish", name:"Finish", field:"finish", minWidth:60, editor:DateCellEditor},
- {id:"effort-driven", name:"Effort Driven", width:80, minWidth:20, maxWidth:80, cssClass:"cell-effort-driven", field:"effortDriven", formatter:BoolCellFormatter, editor:YesNoCheckboxCellEditor}
- ];
- var options = {
- editable: true,
- enableAddRow: true,
- enableCellNavigation: true,
- asyncEditorLoading: false,
- autoEdit: false
- };
-
-
-
- function openDetails() {
- if (grid.getEditorLock().isActive() && !grid.getEditorLock().commitCurrentEdit()) {
- return;
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>SlickGrid example: CompositeEditor</title>
+ <link rel="stylesheet" href="../slick.grid.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" />
+ <style>
+ .cell-title {
+ font-weight: bold;
+ }
+
+ .cell-effort-driven {
+ text-align: center;
+ }
+
+ .item-details-form {
+ z-index: 10000;
+ display: inline-block;
+ border: 1px solid black;
+ margin: 8px;
+ padding: 10px;
+ background: #efefef;
+ -moz-box-shadow: 0px 0px 15px black;
+ -webkit-box-shadow: 0px 0px 15px black;
+ box-shadow: 0px 0px 15px black;
+
+ position: absolute;
+ top: 10px;
+ left: 150px;
+ }
+
+ .item-details-form-buttons {
+ float: right;
+ }
+
+ .item-details-row {
+
+ }
+
+ .item-details-label {
+ margin-left: 10px;
+ margin-top: 20px;
+ display: block;
+ font-weight: bold;
+ }
+
+ .item-details-editor-container {
+ width: 200px;
+ height: 20px;
+ border: 1px solid silver;
+ background: white;
+ display: block;
+ margin: 10px;
+ margin-top: 4px;
+ padding: 0;
+ padding-left: 4px;
+ padding-right: 4px;
+ }
+ </style>
+</head>
+<body>
+<div style="position:relative">
+ <div style="width:600px;">
+ <div id="myGrid" style="width:100%;height:500px;"></div>
+ </div>
+
+ <div class="options-panel">
+ <h2>Demonstrates:</h2>
+ <ul>
+ <li>using a CompositeEditor to implement detached item edit form</li>
+ </ul>
+
+ <h2>Options:</h2>
+ <button onclick="openDetails()">Open Item Edit for active row</button>
+ </div>
+</div>
+
+<script id="itemDetailsTemplate" type="text/x-jquery-tmpl">
+ <div class='item-details-form'>
+ {{each columns}}
+ <div class='item-details-label'>
+ ${name}
+ </div>
+ <div class='item-details-editor-container' data-editorid='${id}'></div>
+ {{/each}}
+
+ <hr/>
+ <div class='item-details-form-buttons'>
+ <button data-action='save'>Save</button>
+ <button data-action='cancel'>Cancel</button>
+ </div>
+ </div>
+</script>
+
+
+<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.0.min.js"></script>
+<script src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>
+
+<script src="../slick.core.js"></script>
+<script src="../plugins/slick.cellrangeselector.js"></script>
+<script src="../plugins/slick.cellselectionmodel.js"></script>
+<script src="../slick.editors.js"></script>
+<script src="../slick.grid.js"></script>
+<script src="slick.compositeeditor.js"></script>
+
+<script>
+ 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};
+ }
+ }
+
+ var grid;
+ var data = [];
+ var columns = [
+ {id:"title", name:"Title", field:"title", width:120, cssClass:"cell-title", editor:TextCellEditor, validator:requiredFieldValidator},
+ {id:"desc", name:"Description", field:"description", width:100, editor:TextCellEditor},
+ {id:"duration", name:"Duration", field:"duration", editor:TextCellEditor},
+ {id:"%", name:"% Complete", field:"percentComplete", width:80, resizable:false, formatter:GraphicalPercentCompleteCellFormatter, editor:PercentCompleteCellEditor},
+ {id:"start", name:"Start", field:"start", minWidth:60, editor:DateCellEditor},
+ {id:"finish", name:"Finish", field:"finish", minWidth:60, editor:DateCellEditor},
+ {id:"effort-driven", name:"Effort Driven", width:80, minWidth:20, maxWidth:80, cssClass:"cell-effort-driven", field:"effortDriven", formatter:BoolCellFormatter, editor:YesNoCheckboxCellEditor}
+ ];
+ var options = {
+ editable:true,
+ enableAddRow:true,
+ enableCellNavigation:true,
+ asyncEditorLoading:false,
+ autoEdit:false
+ };
+
+
+ function openDetails() {
+ if (grid.getEditorLock().isActive() && !grid.getEditorLock().commitCurrentEdit()) {
+ return;
+ }
+
+ var $modal = $("<div class='item-details-form'></div>");
+
+ $modal = $("#itemDetailsTemplate")
+ .tmpl({
+ context:grid.getDataItem(grid.getActiveCell().row),
+ columns:columns
+ })
+ .appendTo("body");
+
+ $modal.keydown(function (e) {
+ if (e.which == $.ui.keyCode.ENTER) {
+ grid.getEditController().commitCurrentEdit();
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ else if (e.which == $.ui.keyCode.ESCAPE) {
+ grid.getEditController().cancelCurrentEdit();
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ });
+
+ $modal.find("[data-action=save]").click(function () {
+ grid.getEditController().commitCurrentEdit();
+ });
+
+ $modal.find("[data-action=cancel]").click(function () {
+ grid.getEditController().cancelCurrentEdit();
+ });
+
+
+ var containers = $.map(columns, function (c) {
+ return $modal.find("[data-editorid=" + c.id + "]");
+ });
+
+ var compositeEditor = new Slick.CompositeEditor(
+ columns,
+ containers,
+ {
+ destroy:function () {
+ $modal.remove();
+ }
}
-
- var $modal = $("<div class='item-details-form'></div>");
-
- $modal = $("#itemDetailsTemplate")
- .tmpl({
- context: grid.getDataItem(grid.getActiveCell().row),
- columns: columns
- })
- .appendTo("body");
-
- $modal.keydown(function(e) {
- if (e.which == $.ui.keyCode.ENTER) {
- grid.getEditController().commitCurrentEdit();
- e.stopPropagation();
- e.preventDefault();
- }
- else if (e.which == $.ui.keyCode.ESCAPE) {
- grid.getEditController().cancelCurrentEdit();
- e.stopPropagation();
- e.preventDefault();
- }
- });
-
- $modal.find("[data-action=save]").click(function() {
- grid.getEditController().commitCurrentEdit();
- });
-
- $modal.find("[data-action=cancel]").click(function() {
- grid.getEditController().cancelCurrentEdit();
- });
-
-
- var containers = $.map(columns, function(c) { return $modal.find("[data-editorid=" + c.id + "]"); });
-
- var compositeEditor = new Slick.CompositeEditor(
- columns,
- containers,
- {
- destroy: function () { $modal.remove(); }
- }
- );
-
- grid.editActiveCell(compositeEditor);
+ );
+
+ grid.editActiveCell(compositeEditor);
+ }
+
+ $(function () {
+ for (var i = 0; i < 500; i++) {
+ var d = (data[i] = {});
+
+ d["title"] = "Task " + i;
+ d["description"] = "This is a sample task description.\n It can be multiline";
+ 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);
+ }
+
+ grid = new Slick.Grid("#myGrid", data, columns, options);
+
+ grid.onAddNewRow.subscribe(function (e, args) {
+ var item = args.item;
+ var column = args.column;
+ grid.invalidateRow(data.length);
+ data.push(item);
+ grid.updateRowCount();
+ grid.render();
+ });
+
+
+ grid.onValidationError.subscribe(function (e, args) {
+ // handle validation errors originating from the CompositeEditor
+ if (args.editor && (args.editor instanceof Slick.CompositeEditor)) {
+ var err;
+ var idx = args.validationResults.errors.length;
+ while (idx--) {
+ err = args.validationResults.errors[idx];
+ $(err.container).stop(true, true).effect("highlight", {color:"red"});
}
+ }
+ });
- $(function()
- {
- for (var i=0; i<500; i++) {
- var d = (data[i] = {});
-
- d["title"] = "Task " + i;
- d["description"] = "This is a sample task description.\n It can be multiline";
- 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);
- }
-
- grid = new Slick.Grid("#myGrid", data, columns, options);
-
- grid.onAddNewRow.subscribe(function(e, args) {
- var item = args.item;
- var column = args.column;
- grid.invalidateRow(data.length);
- data.push(item);
- grid.updateRowCount();
- grid.render();
- });
-
-
- grid.onValidationError.subscribe(function(e, args) {
- // handle validation errors originating from the CompositeEditor
- if (args.editor && (args.editor instanceof Slick.CompositeEditor)) {
- var err;
- var idx = args.validationResults.errors.length;
- while (idx--) {
- err = args.validationResults.errors[idx];
- $(err.container).stop(true,true).effect("highlight", {color:"red"});
- }
- }
- });
-
- grid.setActiveCell(0, 0);
- })
- </script>
- </body>
+ grid.setActiveCell(0, 0);
+ })
+</script>
+</body>
</html>
diff --git a/examples/example-custom-column-value-extractor.html b/examples/example-custom-column-value-extractor.html
index 934a822..53f64bd 100644
--- a/examples/example-custom-column-value-extractor.html
+++ b/examples/example-custom-column-value-extractor.html
@@ -1,76 +1,76 @@
<!DOCTYPE HTML>
<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <title>SlickGrid example: Custom column value extractor</title>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- </head>
- <body>
- <table width="100%">
- <tr>
- <td valign="top" width="50%">
- <div id="myGrid" style="width:600px;height:500px;"></div>
- </td>
- <td valign="top">
- <h2>Demonstrates:</h2>
- <ul>
- <li>using <u>dataItemColumnValueExtractor</u> option to specify a custom column value extractor</li>
- </ul>
- </td>
- </tr>
- </table>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>SlickGrid example: Custom column value extractor</title>
+ <link rel="stylesheet" href="../slick.grid.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" />
+</head>
+<body>
+<table width="100%">
+ <tr>
+ <td valign="top" width="50%">
+ <div id="myGrid" style="width:600px;height:500px;"></div>
+ </td>
+ <td valign="top">
+ <h2>Demonstrates:</h2>
+ <ul>
+ <li>using <u>dataItemColumnValueExtractor</u> option to specify a custom column value extractor</li>
+ </ul>
+ </td>
+ </tr>
+</table>
- <script src="../lib/jquery-1.7.min.js"></script>
- <script src="../lib/jquery.event.drag-2.0.min.js"></script>
+<script src="../lib/jquery-1.7.min.js"></script>
+<script src="../lib/jquery.event.drag-2.0.min.js"></script>
- <script src="../slick.core.js"></script>
- <script src="../slick.grid.js"></script>
+<script src="../slick.core.js"></script>
+<script src="../slick.grid.js"></script>
- <script>
+<script>
- var grid;
+ var grid;
- var columns = [
- {id:"title", name:"Name", field:"name"},
- {id:"field1", name:"Field1", field:"values", fieldIdx: 0},
- {id:"field2", name:"Field2", field:"values", fieldIdx: 1},
- {id:"field3", name:"Field3", field:"values", fieldIdx: 2}
- ];
+ var columns = [
+ {id:"title", name:"Name", field:"name"},
+ {id:"field1", name:"Field1", field:"values", fieldIdx:0},
+ {id:"field2", name:"Field2", field:"values", fieldIdx:1},
+ {id:"field3", name:"Field3", field:"values", fieldIdx:2}
+ ];
- var options = {
- enableCellNavigation: true,
- enableColumnReorder: false,
- dataItemColumnValueExtractor: getItemColumnValue
- };
+ var options = {
+ enableCellNavigation:true,
+ enableColumnReorder:false,
+ dataItemColumnValueExtractor:getItemColumnValue
+ };
- // Get the item column value using a custom 'fieldIdx' column param
- function getItemColumnValue(item, column) {
- var values = item[column.field];
- if (column.fieldIdx !== undefined) {
- return values && values[column.fieldIdx];
- } else {
- return values;
- }
- }
+ // Get the item column value using a custom 'fieldIdx' column param
+ function getItemColumnValue(item, column) {
+ var values = item[column.field];
+ if (column.fieldIdx !== undefined) {
+ return values && values[column.fieldIdx];
+ } else {
+ return values;
+ }
+ }
- $(function() {
- var data = [];
- for (var i = 0; i < 500; i++) {
- data[i] = {
- name: "Item " + i,
- values: [
- Math.round(Math.random() * 100),
- Math.round(Math.random() * 100),
- Math.round(Math.random() * 100)
- ]
- };
- }
+ $(function () {
+ var data = [];
+ for (var i = 0; i < 500; i++) {
+ data[i] = {
+ name:"Item " + i,
+ values:[
+ Math.round(Math.random() * 100),
+ Math.round(Math.random() * 100),
+ Math.round(Math.random() * 100)
+ ]
+ };
+ }
- grid = new Slick.Grid("#myGrid", data, columns, options);
- })
+ grid = new Slick.Grid("#myGrid", data, columns, options);
+ })
- </script>
- </body>
+</script>
+</body>
</html>
diff --git a/examples/example-grouping.html b/examples/example-grouping.html
index 3e3c883..132f6a8 100644
--- a/examples/example-grouping.html
+++ b/examples/example-grouping.html
@@ -1,350 +1,361 @@
<!DOCTYPE HTML>
<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <title>SlickGrid example: Grouping</title>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../controls/slick.pager.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../controls/slick.columnpicker.css" type="text/css" media="screen" charset="utf-8" />
- <style>
- .cell-title {
- font-weight: bold;
- }
-
- .cell-effort-driven {
- text-align: center;
- }
- </style>
- </head>
- <body>
- <div style="position:relative">
- <div style="width:600px;">
- <div class="grid-header" style="width:100%">
- <label>SlickGrid</label>
- </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>Options:</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/>
- <hr/>
- <button onclick="clearGrouping()">Clear grouping</button><br/>
- <button onclick="groupByDuration()">Group by duration & sort groups by value</button><br/>
- <button onclick="groupByDurationOrderByCount()">Group by duration & sort groups by count</button><br/>
- <button onclick="groupByDurationOrderByCountGroupCollapsed()">Group by duration & sort groups by count, group collapsed</button><br/>
- <br/>
- <button onclick="collapseAllGroups()">Collapse all groups</button><br/>
- <button onclick="expandAllGroups()">Expand all groups</button><br/>
- </div>
- <hr/>
- <h2>Demonstrates:</h2>
- <ul>
- <li>
- Fully dynamic and interactive grouping with filtering and aggregates over <b>50'000</b> items<br>
- Personally, this is just the coolest slickest thing I've ever seen done with DHTML grids!
- </li>
- </ul>
- </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.0.min.js"></script>
-
- <script src="../slick.core.js"></script>
- <script src="../slick.editors.js"></script>
- <script src="../plugins/slick.cellrangedecorator.js"></script>
- <script src="../plugins/slick.cellrangeselector.js"></script>
- <script src="../plugins/slick.cellselectionmodel.js"></script>
- <script src="../slick.grid.js"></script>
- <script src="../slick.groupitemmetadataprovider.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", cssClass:"cell-selection", width:40, resizable:false, selectable:false, focusable:false },
- {id:"title", name:"Title", field:"title", width:120, minWidth:120, cssClass:"cell-title", sortable:true, editor:TextCellEditor},
- {id:"duration", name:"Duration", field:"duration", sortable:true},
- {id:"%", name:"% Complete", field:"percentComplete", width:80, formatter:GraphicalPercentCompleteCellFormatter, sortable:true, groupTotalsFormatter:avgTotalsFormatter},
- {id:"start", name:"Start", field:"start", minWidth:60, sortable:true},
- {id:"finish", name:"Finish", field:"finish", minWidth:60, sortable:true},
- {id:"effort-driven", name:"Effort Driven", width:80, minWidth:20, maxWidth:80, cssClass:"cell-effort-driven", field:"effortDriven", formatter:BoolCellFormatter, sortable:true}
- ];
-
- var options = {
- enableCellNavigation: true,
- editable: true
- };
-
- var sortcol = "title";
- var sortdir = 1;
- var percentCompleteThreshold = 0;
- var prevPercentCompleteThreshold = 0;
- var searchString = "";
-
- function avgTotalsFormatter(totals, columnDef) {
- return "avg: " + Math.round(totals.avg[columnDef.field]) + "%";
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>SlickGrid example: Grouping</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;
+ }
+ </style>
+</head>
+<body>
+<div style="position:relative">
+ <div style="width:600px;">
+ <div class="grid-header" style="width:100%">
+ <label>SlickGrid</label>
+ </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>Options:</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/>
+ <hr/>
+ <button onclick="clearGrouping()">Clear grouping</button>
+ <br/>
+ <button onclick="groupByDuration()">Group by duration & sort groups by value</button>
+ <br/>
+ <button onclick="groupByDurationOrderByCount()">Group by duration & sort groups by count</button>
+ <br/>
+ <button onclick="groupByDurationOrderByCountGroupCollapsed()">Group by duration & sort groups by count, group
+ collapsed
+ </button>
+ <br/>
+ <br/>
+ <button onclick="collapseAllGroups()">Collapse all groups</button>
+ <br/>
+ <button onclick="expandAllGroups()">Expand all groups</button>
+ <br/>
+ </div>
+ <hr/>
+ <h2>Demonstrates:</h2>
+ <ul>
+ <li>
+ Fully dynamic and interactive grouping with filtering and aggregates over <b>50'000</b> items<br>
+ Personally, this is just the coolest slickest thing I've ever seen done with DHTML grids!
+ </li>
+ </ul>
+ </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.0.min.js"></script>
+
+<script src="../slick.core.js"></script>
+<script src="../slick.editors.js"></script>
+<script src="../plugins/slick.cellrangedecorator.js"></script>
+<script src="../plugins/slick.cellrangeselector.js"></script>
+<script src="../plugins/slick.cellselectionmodel.js"></script>
+<script src="../slick.grid.js"></script>
+<script src="../slick.groupitemmetadataprovider.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", cssClass:"cell-selection", width:40, resizable:false, selectable:false, focusable:false },
+ {id:"title", name:"Title", field:"title", width:120, minWidth:120, cssClass:"cell-title", sortable:true, editor:TextCellEditor},
+ {id:"duration", name:"Duration", field:"duration", sortable:true},
+ {id:"%", name:"% Complete", field:"percentComplete", width:80, formatter:GraphicalPercentCompleteCellFormatter, sortable:true, groupTotalsFormatter:avgTotalsFormatter},
+ {id:"start", name:"Start", field:"start", minWidth:60, sortable:true},
+ {id:"finish", name:"Finish", field:"finish", minWidth:60, sortable:true},
+ {id:"effort-driven", name:"Effort Driven", width:80, minWidth:20, maxWidth:80, cssClass:"cell-effort-driven", field:"effortDriven", formatter:BoolCellFormatter, sortable:true}
+];
+
+var options = {
+ enableCellNavigation:true,
+ editable:true
+};
+
+var sortcol = "title";
+var sortdir = 1;
+var percentCompleteThreshold = 0;
+var prevPercentCompleteThreshold = 0;
+var searchString = "";
+
+function avgTotalsFormatter(totals, columnDef) {
+ return "avg: " + Math.round(totals.avg[columnDef.field]) + "%";
+}
+
+function myFilter(item, args) {
+ return item["percentComplete"] >= args.percentComplete &&
+ (args.searchString == "" ||
+ item["title"].indexOf(args.searchString) == -1);
+}
+
+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 collapseAllGroups() {
+ dataView.beginUpdate();
+ for (var i = 0; i < dataView.getGroups().length; i++) {
+ dataView.collapseGroup(dataView.getGroups()[i].value);
+ }
+ dataView.endUpdate();
+}
+
+function expandAllGroups() {
+ dataView.beginUpdate();
+ for (var i = 0; i < dataView.getGroups().length; i++) {
+ dataView.expandGroup(dataView.getGroups()[i].value);
+ }
+ dataView.endUpdate();
+}
+
+function clearGrouping() {
+ dataView.groupBy(null);
+}
+
+function groupByDuration() {
+ dataView.groupBy(
+ "duration",
+ function (g) {
+ return "Duration: " + g.value + " <span style='color:green'>(" + g.count + " items)</span>";
+ },
+ function (a, b) {
+ return a.value - b.value;
+ }
+ );
+ dataView.setAggregators([
+ new Slick.Data.Aggregators.Avg("percentComplete")
+ ], false);
+}
+
+function groupByDurationOrderByCount() {
+ dataView.groupBy(
+ "duration",
+ function (g) {
+ return "Duration: " + g.value + " <span style='color:green'>(" + g.count + " items)</span>";
+ },
+ function (a, b) {
+ return a.count - b.count;
+ }
+ );
+ dataView.setAggregators([
+ new Slick.Data.Aggregators.Avg("percentComplete")
+ ], false);
+}
+
+function groupByDurationOrderByCountGroupCollapsed() {
+ dataView.groupBy(
+ "duration",
+ function (g) {
+ return "Duration: " + g.value + " <span style='color:green'>(" + g.count + " items)</span>";
+ },
+ function (a, b) {
+ return a.count - b.count;
+ }
+ );
+ dataView.setAggregators([
+ new Slick.Data.Aggregators.Avg("percentComplete")
+ ], true);
+}
+
+$(".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"] = Math.round(Math.random() * 14);
+ d["percentComplete"] = Math.round(Math.random() * 100);
+ d["start"] = "01/01/2009";
+ d["finish"] = "01/05/2009";
+ d["effortDriven"] = (i % 5 == 0);
+ }
+
+ var groupItemMetadataProvider = new Slick.Data.GroupItemMetadataProvider();
+ dataView = new Slick.Data.DataView({
+ groupItemMetadataProvider:groupItemMetadataProvider
+ });
+ grid = new Slick.Grid("#myGrid", dataView, columns, options);
+
+ // register the group item metadata provider to add expand/collapse group handlers
+ grid.registerPlugin(groupItemMetadataProvider);
+ grid.setSelectionModel(new Slick.CellSelectionModel());
+
+ var pager = new Slick.Controls.Pager(dataView, grid, $("#pager"));
+ var columnpicker = new Slick.Controls.ColumnPicker(columns, grid, options);
+
+
+ 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;
}
-
- function myFilter(item, args) {
- return item["percentComplete"] >= args.percentComplete &&
- (args.searchString == "" ||
- item["title"].indexOf(args.searchString) == -1);
- }
-
- 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 collapseAllGroups() {
- dataView.beginUpdate();
- for (var i = 0; i < dataView.getGroups().length; i++) {
- dataView.collapseGroup(dataView.getGroups()[i].value);
- }
- dataView.endUpdate();
+ else if (val < 100) {
+ return "0" + val;
}
-
- function expandAllGroups() {
- dataView.beginUpdate();
- for (var i = 0; i < dataView.getGroups().length; i++) {
- dataView.expandGroup(dataView.getGroups()[i].value);
- }
- dataView.endUpdate();
+ else {
+ return val;
}
-
- function clearGrouping() {
- dataView.groupBy(null);
- }
-
- function groupByDuration() {
- dataView.groupBy(
- "duration",
- function (g) {
- return "Duration: " + g.value + " <span style='color:green'>(" + g.count + " items)</span>";
- },
- function (a, b) {
- return a.value - b.value;
- }
- );
- dataView.setAggregators([
- new Slick.Data.Aggregators.Avg("percentComplete")
- ], false);
- }
-
- function groupByDurationOrderByCount() {
- dataView.groupBy(
- "duration",
- function (g) {
- return "Duration: " + g.value + " <span style='color:green'>(" + g.count + " items)</span>";
- },
- function (a, b) {
- return a.count - b.count;
- }
- );
- dataView.setAggregators([
- new Slick.Data.Aggregators.Avg("percentComplete")
- ], false);
- }
-
- function groupByDurationOrderByCountGroupCollapsed() {
- dataView.groupBy(
- "duration",
- function (g) {
- return "Duration: " + g.value + " <span style='color:green'>(" + g.count + " items)</span>";
- },
- function (a, b) {
- return a.count - b.count;
- }
- );
- dataView.setAggregators([
- new Slick.Data.Aggregators.Avg("percentComplete")
- ], true);
- }
-
- $(".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"] = Math.round(Math.random() * 14);
- d["percentComplete"] = Math.round(Math.random() * 100);
- d["start"] = "01/01/2009";
- d["finish"] = "01/05/2009";
- d["effortDriven"] = (i % 5 == 0);
- }
-
- var groupItemMetadataProvider = new Slick.Data.GroupItemMetadataProvider();
- dataView = new Slick.Data.DataView({
- groupItemMetadataProvider: groupItemMetadataProvider
- });
- grid = new Slick.Grid("#myGrid", dataView, columns, options);
-
- // register the group item metadata provider to add expand/collapse group handlers
- grid.registerPlugin(groupItemMetadataProvider);
- grid.setSelectionModel(new Slick.CellSelectionModel());
-
- var pager = new Slick.Controls.Pager(dataView, grid, $("#pager"));
- var columnpicker = new Slick.Controls.ColumnPicker(columns, grid, options);
-
-
- 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();
- });
-
-
- 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(filterAndUpdate, 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;
- dataView.refresh();
- });
-
-
- function filterAndUpdate() {
- var isNarrowing = percentCompleteThreshold > prevPercentCompleteThreshold;
- var isExpanding = percentCompleteThreshold < prevPercentCompleteThreshold;
- var renderedRange = grid.getRenderedRange();
-
- dataView.setFilterArgs({
- percentComplete: percentCompleteThreshold,
- searchString: searchString
- });
- dataView.setRefreshHints({
- ignoreDiffsBefore:renderedRange.top,
- ignoreDiffsAfter:renderedRange.bottom + 1,
- isFilterNarrowing:isNarrowing,
- isFilterExpanding:isExpanding
- });
- dataView.refresh();
-
- prevPercentCompleteThreshold = percentCompleteThreshold;
- }
-
- // initialize the model after all the events have been hooked up
- dataView.beginUpdate();
- dataView.setItems(data);
- dataView.setFilter(myFilter);
- dataView.setFilterArgs({
- percentComplete: percentCompleteThreshold,
- searchString: searchString
- });
- dataView.groupBy(
- "duration",
- function (g) {
- return "Duration: " + g.value + " <span style='color:green'>(" + g.count + " items)</span>";
- },
- function (a, b) {
- return a.value - b.value;
- }
- );
- dataView.setAggregators([
- new Slick.Data.Aggregators.Avg("percentComplete")
- ], false);
- dataView.collapseGroup(0);
- dataView.endUpdate();
-
- $("#gridContainer").resizable();
- })
-
- </script>
-
- </body>
+ };
+
+ // 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();
+ });
+
+
+ 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(filterAndUpdate, 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;
+ dataView.refresh();
+ });
+
+
+ function filterAndUpdate() {
+ var isNarrowing = percentCompleteThreshold > prevPercentCompleteThreshold;
+ var isExpanding = percentCompleteThreshold < prevPercentCompleteThreshold;
+ var renderedRange = grid.getRenderedRange();
+
+ dataView.setFilterArgs({
+ percentComplete:percentCompleteThreshold,
+ searchString:searchString
+ });
+ dataView.setRefreshHints({
+ ignoreDiffsBefore:renderedRange.top,
+ ignoreDiffsAfter:renderedRange.bottom + 1,
+ isFilterNarrowing:isNarrowing,
+ isFilterExpanding:isExpanding
+ });
+ dataView.refresh();
+
+ prevPercentCompleteThreshold = percentCompleteThreshold;
+ }
+
+ // initialize the model after all the events have been hooked up
+ dataView.beginUpdate();
+ dataView.setItems(data);
+ dataView.setFilter(myFilter);
+ dataView.setFilterArgs({
+ percentComplete:percentCompleteThreshold,
+ searchString:searchString
+ });
+ dataView.groupBy(
+ "duration",
+ function (g) {
+ return "Duration: " + g.value + " <span style='color:green'>(" + g.count + " items)</span>";
+ },
+ function (a, b) {
+ return a.value - b.value;
+ }
+ );
+ dataView.setAggregators([
+ new Slick.Data.Aggregators.Avg("percentComplete")
+ ], false);
+ dataView.collapseGroup(0);
+ dataView.endUpdate();
+
+ $("#gridContainer").resizable();
+})
+
+</script>
+
+</body>
</html>
diff --git a/examples/example-header-row.html b/examples/example-header-row.html
index 9f03a4f..ba3532a 100644
--- a/examples/example-header-row.html
+++ b/examples/example-header-row.html
@@ -1,139 +1,138 @@
<!DOCTYPE HTML>
<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- <style>
- .slick-headerrow-column {
- background: #87ceeb;
- }
-
- .slick-headerrow-column input {
- margin: 0;
- padding: 0;
- }
- </style>
- </head>
- <body>
- <div style="position:relative">
- <div style="width:600px;">
- <div id="myGrid" style="width:100%;height:500px;"></div>
- </div>
-
- <div class="options-panel">
- <h2>Demonstrates:</h2>
- <ul>
- <li>Using a fixed header row to implement column-level filters</li>
- <li>Type numbers in textboxes to filter grid data</li>
- </ul>
- </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.0.min.js"></script>
-
- <script src="../slick.core.js"></script>
- <script src="../slick.dataview.js"></script>
- <script src="../slick.grid.js"></script>
-
- <script>
- var dataView;
- var grid;
- var data = [];
- var options = {
- enableCellNavigation: true,
- showHeaderRow: true
- };
- var columns = [];
- var columnFilters = {};
-
- for (var i = 0; i < 10; i++) {
- columns.push({
- id: i,
- name: String.fromCharCode("A".charCodeAt(0) + i),
- field: i,
- width: 60
- });
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" />
+ <link rel="stylesheet" href="../slick.grid.css" type="text/css" />
+ <link rel="stylesheet" href="examples.css" type="text/css" />
+ <style>
+ .slick-headerrow-column {
+ background: #87ceeb;
+ }
+
+ .slick-headerrow-column input {
+ margin: 0;
+ padding: 0;
+ }
+ </style>
+</head>
+<body>
+<div style="position:relative">
+ <div style="width:600px;">
+ <div id="myGrid" style="width:100%;height:500px;"></div>
+ </div>
+
+ <div class="options-panel">
+ <h2>Demonstrates:</h2>
+ <ul>
+ <li>Using a fixed header row to implement column-level filters</li>
+ <li>Type numbers in textboxes to filter grid data</li>
+ </ul>
+ </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.0.min.js"></script>
+
+<script src="../slick.core.js"></script>
+<script src="../slick.dataview.js"></script>
+<script src="../slick.grid.js"></script>
+
+<script>
+ var dataView;
+ var grid;
+ var data = [];
+ var options = {
+ enableCellNavigation:true,
+ showHeaderRow:true
+ };
+ var columns = [];
+ var columnFilters = {};
+
+ for (var i = 0; i < 10; i++) {
+ columns.push({
+ id:i,
+ name:String.fromCharCode("A".charCodeAt(0) + i),
+ field:i,
+ width:60
+ });
+ }
+
+
+ function updateHeaderRow() {
+ for (var i = 0; i < columns.length; i++) {
+ if (columns[i].id !== "selector") {
+ var header = grid.getHeaderRowColumn(columns[i].id);
+ $(header).empty();
+ $("<input type='text'>")
+ .data("columnId", columns[i].id)
+ .width($(header).width() - 4)
+ .val(columnFilters[columns[i].id])
+ .appendTo(header);
+ }
+ }
+ }
+
+ function filter(item) {
+ for (var columnId in columnFilters) {
+ if (columnId !== undefined && columnFilters[columnId] !== "") {
+ var c = grid.getColumns()[grid.getColumnIndex(columnId)];
+ if (item[c.field] != columnFilters[columnId]) {
+ return false;
}
-
-
- function updateHeaderRow() {
- for (var i = 0; i < columns.length; i++) {
- if (columns[i].id !== "selector") {
- var header = grid.getHeaderRowColumn(columns[i].id);
- $(header).empty();
- $("<input type='text'>")
- .data("columnId", columns[i].id)
- .width($(header).width() - 4)
- .val(columnFilters[columns[i].id])
- .appendTo(header);
- }
- }
- }
-
- function filter(item) {
- for (var columnId in columnFilters) {
- if (columnId !== undefined && columnFilters[columnId] !== "") {
- var c = grid.getColumns()[grid.getColumnIndex(columnId)];
- if (item[c.field] != columnFilters[columnId]) {
- return false;
- }
- }
- }
- return true;
- }
-
- $(function()
- {
- for (var i=0; i<100; i++) {
- var d = (data[i] = {});
- d["id"] = i;
- for (var j=0; j<columns.length; j++) {
- d[j] = Math.round(Math.random() * 10);
- }
- }
-
- dataView = new Slick.Data.DataView();
- grid = new Slick.Grid("#myGrid", dataView, columns, options);
-
-
- dataView.onRowCountChanged.subscribe(function(e,args) {
- grid.updateRowCount();
- grid.render();
- });
-
- dataView.onRowsChanged.subscribe(function(e,args) {
- grid.invalidateRows(args.rows);
- grid.render();
- });
-
- $(grid.getHeaderRow()).delegate(":input", "change keyup", function(e) {
- columnFilters[$(this).data("columnId")] = $.trim($(this).val());
- dataView.refresh();
- });
-
-
- grid.onColumnsReordered.subscribe(function(e, args) {
- updateHeaderRow();
- });
-
- grid.onColumnsResized.subscribe(function(e, args) {
- updateHeaderRow();
- });
-
- dataView.beginUpdate();
- dataView.setItems(data);
- dataView.setFilter(filter);
- dataView.endUpdate();
-
- updateHeaderRow();
-
- })
- </script>
- </body>
+ }
+ }
+ return true;
+ }
+
+ $(function () {
+ for (var i = 0; i < 100; i++) {
+ var d = (data[i] = {});
+ d["id"] = i;
+ for (var j = 0; j < columns.length; j++) {
+ d[j] = Math.round(Math.random() * 10);
+ }
+ }
+
+ dataView = new Slick.Data.DataView();
+ grid = new Slick.Grid("#myGrid", dataView, columns, options);
+
+
+ dataView.onRowCountChanged.subscribe(function (e, args) {
+ grid.updateRowCount();
+ grid.render();
+ });
+
+ dataView.onRowsChanged.subscribe(function (e, args) {
+ grid.invalidateRows(args.rows);
+ grid.render();
+ });
+
+ $(grid.getHeaderRow()).delegate(":input", "change keyup", function (e) {
+ columnFilters[$(this).data("columnId")] = $.trim($(this).val());
+ dataView.refresh();
+ });
+
+
+ grid.onColumnsReordered.subscribe(function (e, args) {
+ updateHeaderRow();
+ });
+
+ grid.onColumnsResized.subscribe(function (e, args) {
+ updateHeaderRow();
+ });
+
+ dataView.beginUpdate();
+ dataView.setItems(data);
+ dataView.setFilter(filter);
+ dataView.endUpdate();
+
+ updateHeaderRow();
+
+ })
+</script>
+</body>
</html>
diff --git a/examples/example-optimizing-dataview.html b/examples/example-optimizing-dataview.html
index 864c1d2..740781b 100644
--- a/examples/example-optimizing-dataview.html
+++ b/examples/example-optimizing-dataview.html
@@ -1,66 +1,67 @@
<!DOCTYPE HTML>
<html>
<head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <title>SlickGrid example: Optimizing DataView</title>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8"/>
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen"
- charset="utf-8"/>
- <link rel="stylesheet" href="../controls/slick.pager.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8"/>
- <style>
- .cell-title {
- font-weight: bold;
- }
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>SlickGrid example: Optimizing DataView</title>
+ <link rel="stylesheet" href="../slick.grid.css" type="text/css" />
+ <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" />
+ <link rel="stylesheet" href="../controls/slick.pager.css" type="text/css" />
+ <link rel="stylesheet" href="examples.css" type="text/css" />
+ <style>
+ .cell-title {
+ font-weight: bold;
+ }
- .cell-effort-driven {
- text-align: center;
- }
+ .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;
- }
- </style>
+ .cell-selection {
+ border-right-color: silver;
+ border-right-style: solid;
+ background: #f5f5f5;
+ color: gray;
+ text-align: right;
+ font-size: 10px;
+ }
+ </style>
</head>
<body>
<div style="position:relative">
- <div style="width:600px;">
- <div class="grid-header" style="width:100%">
- <label>SlickGrid</label>
- </div>
- <div id="myGrid" style="width:100%;height:500px;"></div>
- <div id="pager" style="width:100%;height:20px;"></div>
+ <div style="width:600px;">
+ <div class="grid-header" style="width:100%">
+ <label>SlickGrid</label>
</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>
- </div>
- <br/>
-
- <p>
- This page demonstrates various techniques for optimizing DataView performance
- for large client-side datasets. This page displays an interactive grid with
- 500'000 rows with real-time filtering.<br/>
- This is achieved by:
- <ul>
- <li>Using a batch filtering function to cut down on the cost of function calls.</li>
- <li>Providing hints to indicate whether a filtering operation will result in
- narrowing or expanding scope or whether the scope is unchanged.</li>
- <li>Providing a range of rows for which onRowsChanged even should be fired.</li>
- </ul>
- </p>
+ <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>
</div>
+ <br/>
+
+ <p>
+ This page demonstrates various techniques for optimizing DataView performance
+ for large client-side datasets. This page displays an interactive grid with
+ 500'000 rows with real-time filtering.<br/>
+ This is achieved by:
+ <ul>
+ <li>Using a batch filtering function to cut down on the cost of function calls.</li>
+ <li>Providing hints to indicate whether a filtering operation will result in
+ narrowing or expanding scope or whether the scope is unchanged.
+ </li>
+ <li>Providing a range of rows for which onRowsChanged even should be fired.</li>
+ </ul>
+ </p>
+ </div>
</div>
@@ -75,105 +76,105 @@
<script src="../controls/slick.pager.js"></script>
<script>
- var dataView;
- var grid;
- var data = [];
-
- var columns = [
- {id:"sel", name:"#", field:"num", behavior:"select", cssClass:"cell-selection", width:40, resizable:false, selectable:false },
- {id:"title", name:"Title", field:"title", width:120, minWidth:120, cssClass:"cell-title"},
- {id:"duration", name:"Duration", field:"duration"},
- {id:"%", name:"% Complete", field:"percentComplete", width:80, resizable:false, formatter:GraphicalPercentCompleteCellFormatter},
- {id:"start", name:"Start", field:"start", minWidth:60},
- {id:"finish", name:"Finish", field:"finish", minWidth:60},
- {id:"effort-driven", name:"Effort Driven", width:80, minWidth:20, maxWidth:80, cssClass:"cell-effort-driven", field:"effortDriven", formatter:BoolCellFormatter}
- ];
-
- var options = {
- editable:false,
- enableAddRow:false,
- enableCellNavigation:true
- };
-
- var percentCompleteThreshold = 0;
- var prevPercentCompleteThreshold = 0;
- var searchString = "";
- var h_runfilters = null;
-
- function myFilter(item, args) {
- return item["percentComplete"] >= args;
+ var dataView;
+ var grid;
+ var data = [];
+
+ var columns = [
+ {id:"sel", name:"#", field:"num", behavior:"select", cssClass:"cell-selection", width:40, resizable:false, selectable:false },
+ {id:"title", name:"Title", field:"title", width:120, minWidth:120, cssClass:"cell-title"},
+ {id:"duration", name:"Duration", field:"duration"},
+ {id:"%", name:"% Complete", field:"percentComplete", width:80, resizable:false, formatter:GraphicalPercentCompleteCellFormatter},
+ {id:"start", name:"Start", field:"start", minWidth:60},
+ {id:"finish", name:"Finish", field:"finish", minWidth:60},
+ {id:"effort-driven", name:"Effort Driven", width:80, minWidth:20, maxWidth:80, cssClass:"cell-effort-driven", field:"effortDriven", formatter:BoolCellFormatter}
+ ];
+
+ var options = {
+ editable:false,
+ enableAddRow:false,
+ enableCellNavigation:true
+ };
+
+ var percentCompleteThreshold = 0;
+ var prevPercentCompleteThreshold = 0;
+ var searchString = "";
+ var h_runfilters = null;
+
+ function myFilter(item, args) {
+ return item["percentComplete"] >= args;
+ }
+
+ function DataItem(i) {
+ this.num = i;
+ this.id = "id_" + i;
+ this.percentComplete = Math.round(Math.random() * 100);
+ this.effortDriven = (i % 5 == 0);
+ this.start = "01/01/2009";
+ this.finish = "01/05/2009";
+ this.title = "Task " + i;
+ this.duration = "5 days";
+ }
+
+
+ $(function () {
+ // prepare the data
+ for (var i = 0; i < 500000; i++) {
+ data[i] = new DataItem(i);
}
- function DataItem(i) {
- this.num = i;
- this.id = "id_" + i;
- this.percentComplete = Math.round(Math.random() * 100);
- this.effortDriven = (i % 5 == 0);
- this.start = "01/01/2009";
- this.finish = "01/05/2009";
- this.title = "Task " + i;
- this.duration = "5 days";
- }
-
-
- $(function() {
- // prepare the data
- for (var i = 0; i < 500000; i++) {
- data[i] = new DataItem(i);
- }
-
- dataView = new Slick.Data.DataView();
- grid = new Slick.Grid("#myGrid", dataView, columns, options);
- var pager = new Slick.Controls.Pager(dataView, grid, $("#pager"));
-
- // 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();
- });
-
-
- // wire up the slider to apply the filter to the model
- $("#pcSlider").slider({
- "range":"min",
- "slide":function(event, ui) {
- if (percentCompleteThreshold != ui.value) {
- window.clearTimeout(h_runfilters);
- h_runfilters = window.setTimeout(filterAndUpdate, 10);
- percentCompleteThreshold = ui.value;
- }
- }
- });
-
- function filterAndUpdate() {
- var isNarrowing = percentCompleteThreshold > prevPercentCompleteThreshold;
- var isExpanding = percentCompleteThreshold < prevPercentCompleteThreshold;
- var renderedRange = grid.getRenderedRange();
-
- dataView.setFilterArgs(percentCompleteThreshold);
- dataView.setRefreshHints({
- ignoreDiffsBefore:renderedRange.top,
- ignoreDiffsAfter:renderedRange.bottom + 1,
- isFilterNarrowing:isNarrowing,
- isFilterExpanding:isExpanding
- });
- dataView.refresh();
-
- prevPercentCompleteThreshold = percentCompleteThreshold;
+ dataView = new Slick.Data.DataView();
+ grid = new Slick.Grid("#myGrid", dataView, columns, options);
+ var pager = new Slick.Controls.Pager(dataView, grid, $("#pager"));
+
+ // 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();
+ });
+
+
+ // wire up the slider to apply the filter to the model
+ $("#pcSlider").slider({
+ "range": "min",
+ "slide": function (event, ui) {
+ if (percentCompleteThreshold != ui.value) {
+ window.clearTimeout(h_runfilters);
+ h_runfilters = window.setTimeout(filterAndUpdate, 10);
+ percentCompleteThreshold = ui.value;
}
+ }
+ });
+
+ function filterAndUpdate() {
+ var isNarrowing = percentCompleteThreshold > prevPercentCompleteThreshold;
+ var isExpanding = percentCompleteThreshold < prevPercentCompleteThreshold;
+ var renderedRange = grid.getRenderedRange();
+
+ dataView.setFilterArgs(percentCompleteThreshold);
+ dataView.setRefreshHints({
+ ignoreDiffsBefore:renderedRange.top,
+ ignoreDiffsAfter:renderedRange.bottom + 1,
+ isFilterNarrowing:isNarrowing,
+ isFilterExpanding:isExpanding
+ });
+ dataView.refresh();
+
+ prevPercentCompleteThreshold = percentCompleteThreshold;
+ }
- // initialize the model after all the events have been hooked up
- dataView.beginUpdate();
- dataView.setItems(data);
- dataView.setFilter(myFilter);
- dataView.setFilterArgs(0);
- dataView.endUpdate();
- })
+ // initialize the model after all the events have been hooked up
+ dataView.beginUpdate();
+ dataView.setItems(data);
+ dataView.setFilter(myFilter);
+ dataView.setFilterArgs(0);
+ dataView.endUpdate();
+ })
</script>
</body>
</html>
diff --git a/examples/example-spreadsheet.html b/examples/example-spreadsheet.html
index 01f51a0..d1054b2 100644
--- a/examples/example-spreadsheet.html
+++ b/examples/example-spreadsheet.html
@@ -1,169 +1,169 @@
<!DOCTYPE HTML>
<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <title>SlickGrid example 3: Editing</title>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- <style>
- .slick-cell.copied {
- background: blue;
- background: rgba(0,0,255,0.2);
- -webkit-transition: 0.5s background;
- }
- </style>
- </head>
- <body>
- <div style="position:relative">
- <div style="width:600px;">
- <div id="myGrid" style="width:100%;height:500px;"></div>
- </div>
-
- <div class="options-panel">
- <h2>Demonstrates:</h2>
- <ul>
- <li>Select a range of cells with a mouse</li>
- <li>Use Ctrl-C and Ctrl-V keyboard shortcuts to cut and paste cells</li>
- <li>Use Esc to cancel a copy and paste operation</li>
- <li>Edit the cell and select a cell range to paste the range</li>
- </ul>
- </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.0.min.js"></script>
-
- <script src="../slick.core.js"></script>
- <script src="../plugins/slick.autotooltips.js"></script>
- <script src="../plugins/slick.cellrangedecorator.js"></script>
- <script src="../plugins/slick.cellrangeselector.js"></script>
- <script src="../plugins/slick.cellcopymanager.js"></script>
- <script src="../plugins/slick.cellselectionmodel.js"></script>
- <script src="../slick.editors.js"></script>
- <script src="../slick.grid.js"></script>
-
- <script>
- var grid;
- var data = [];
- var options = {
- editable: true,
- enableAddRow: true,
- enableCellNavigation: true,
- asyncEditorLoading: false,
- autoEdit: false
- };
-
- var columns = [{
- id: "selector",
- name: "",
- field: "num",
- width: 30
- }];
-
- for (var i = 0; i < 26; i++) {
- columns.push({
- id: i,
- name: String.fromCharCode("A".charCodeAt(0) + i),
- field: i,
- width: 60,
- editor: FormulaEditor
- });
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>SlickGrid example 3: Editing</title>
+ <link rel="stylesheet" href="../slick.grid.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" />
+ <style>
+ .slick-cell.copied {
+ background: blue;
+ background: rgba(0, 0, 255, 0.2);
+ -webkit-transition: 0.5s background;
+ }
+ </style>
+</head>
+<body>
+<div style="position:relative">
+ <div style="width:600px;">
+ <div id="myGrid" style="width:100%;height:500px;"></div>
+ </div>
+
+ <div class="options-panel">
+ <h2>Demonstrates:</h2>
+ <ul>
+ <li>Select a range of cells with a mouse</li>
+ <li>Use Ctrl-C and Ctrl-V keyboard shortcuts to cut and paste cells</li>
+ <li>Use Esc to cancel a copy and paste operation</li>
+ <li>Edit the cell and select a cell range to paste the range</li>
+ </ul>
+ </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.0.min.js"></script>
+
+<script src="../slick.core.js"></script>
+<script src="../plugins/slick.autotooltips.js"></script>
+<script src="../plugins/slick.cellrangedecorator.js"></script>
+<script src="../plugins/slick.cellrangeselector.js"></script>
+<script src="../plugins/slick.cellcopymanager.js"></script>
+<script src="../plugins/slick.cellselectionmodel.js"></script>
+<script src="../slick.editors.js"></script>
+<script src="../slick.grid.js"></script>
+
+<script>
+ var grid;
+ var data = [];
+ var options = {
+ editable:true,
+ enableAddRow:true,
+ enableCellNavigation:true,
+ asyncEditorLoading:false,
+ autoEdit:false
+ };
+
+ var columns = [
+ {
+ id:"selector",
+ name:"",
+ field:"num",
+ width:30
+ }
+ ];
+
+ for (var i = 0; i < 26; i++) {
+ columns.push({
+ id:i,
+ name:String.fromCharCode("A".charCodeAt(0) + i),
+ field:i,
+ width:60,
+ editor:FormulaEditor
+ });
+ }
+
+ /***
+ * A proof-of-concept cell editor with Excel-like range selection and insertion.
+ */
+ function FormulaEditor(args) {
+ var _self = this;
+ var _editor = new TextCellEditor(args);
+ var _selector;
+
+ $.extend(this, _editor);
+
+ function init() {
+ // register a plugin to select a range and append it to the textbox
+ // since events are fired in reverse order (most recently added are executed first),
+ // this will override other plugins like moverows or selection model and will
+ // not require the grid to not be in the edit mode
+ _selector = new Slick.CellRangeSelector();
+ _selector.onCellRangeSelected.subscribe(_self.handleCellRangeSelected);
+ args.grid.registerPlugin(_selector);
+ }
+
+ this.destroy = function () {
+ _selector.onCellRangeSelected.unsubscribe(_self.handleCellRangeSelected);
+ grid.unregisterPlugin(_selector);
+ _editor.destroy();
+ };
+
+ this.handleCellRangeSelected = function (e, args) {
+ _editor.setValue(
+ _editor.getValue() +
+ grid.getColumns()[args.range.fromCell].name +
+ args.range.fromRow +
+ ":" +
+ grid.getColumns()[args.range.toCell].name +
+ args.range.toRow
+ );
+ };
+
+
+ init();
+ }
+
+
+ $(function () {
+ for (var i = 0; i < 100; i++) {
+ var d = (data[i] = {});
+ d["num"] = i;
+ }
+
+ grid = new Slick.Grid("#myGrid", data, columns, options);
+
+ grid.setSelectionModel(new Slick.CellSelectionModel());
+ grid.registerPlugin(new Slick.AutoTooltips());
+
+ // set keyboard focus on the grid
+ grid.getCanvasNode().focus();
+
+ var copyManager = new Slick.CellCopyManager();
+ grid.registerPlugin(copyManager);
+
+ copyManager.onPasteCells.subscribe(function (e, args) {
+ if (args.from.length !== 1 || args.to.length !== 1) {
+ throw "This implementation only supports single range copy and paste operations";
+ }
+
+ var from = args.from[0];
+ var to = args.to[0];
+ var val;
+ for (var i = 0; i <= from.toRow - from.fromRow; i++) {
+ for (var j = 0; j <= from.toCell - from.fromCell; j++) {
+ if (i <= to.toRow - to.fromRow && j <= to.toCell - to.fromCell) {
+ val = data[from.fromRow + i][columns[from.fromCell + j].field];
+ data[to.fromRow + i][columns[to.fromCell + j].field] = val;
+ grid.invalidateRow(to.fromRow + i);
+ }
}
-
- /***
- * A proof-of-concept cell editor with Excel-like range selection and insertion.
- */
- function FormulaEditor(args) {
- var _self = this;
- var _editor = new TextCellEditor(args);
- var _selector;
-
- $.extend(this, _editor);
-
- function init() {
- // register a plugin to select a range and append it to the textbox
- // since events are fired in reverse order (most recently added are executed first),
- // this will override other plugins like moverows or selection model and will
- // not require the grid to not be in the edit mode
- _selector = new Slick.CellRangeSelector();
- _selector.onCellRangeSelected.subscribe(_self.handleCellRangeSelected);
- args.grid.registerPlugin(_selector);
- }
-
- this.destroy = function() {
- _selector.onCellRangeSelected.unsubscribe(_self.handleCellRangeSelected);
- grid.unregisterPlugin(_selector);
- _editor.destroy();
- };
-
- this.handleCellRangeSelected = function(e, args) {
- _editor.setValue(
- _editor.getValue() +
- grid.getColumns()[args.range.fromCell].name +
- args.range.fromRow +
- ":" +
- grid.getColumns()[args.range.toCell].name +
- args.range.toRow
- );
- };
-
-
- init();
- }
-
-
-
- $(function()
- {
- for (var i=0; i<100; i++) {
- var d = (data[i] = {});
- d["num"] = i;
- }
-
- grid = new Slick.Grid("#myGrid", data, columns, options);
-
- grid.setSelectionModel(new Slick.CellSelectionModel());
- grid.registerPlugin(new Slick.AutoTooltips());
-
- // set keyboard focus on the grid
- grid.getCanvasNode().focus();
-
- var copyManager = new Slick.CellCopyManager();
- grid.registerPlugin(copyManager);
-
- copyManager.onPasteCells.subscribe(function(e,args) {
- if (args.from.length !== 1 || args.to.length !== 1) {
- throw "This implementation only supports single range copy and paste operations";
- }
-
- var from = args.from[0];
- var to = args.to[0];
- var val;
- for (var i = 0; i <= from.toRow - from.fromRow; i++) {
- for (var j = 0; j <= from.toCell - from.fromCell; j++) {
- if (i <= to.toRow - to.fromRow && j <= to.toCell - to.fromCell) {
- val = data[from.fromRow + i][columns[from.fromCell + j].field];
- data[to.fromRow + i][columns[to.fromCell + j].field] = val;
- grid.invalidateRow(to.fromRow + i);
- }
- }
- }
- grid.render();
- });
-
- grid.onAddNewRow.subscribe(function(e, args) {
- var item = args.item;
- var column = args.column;
- grid.invalidateRow(data.length);
- data.push(item);
- grid.updateRowCount();
- grid.render();
- });
- })
- </script>
- </body>
+ }
+ grid.render();
+ });
+
+ grid.onAddNewRow.subscribe(function (e, args) {
+ var item = args.item;
+ var column = args.column;
+ grid.invalidateRow(data.length);
+ data.push(item);
+ grid.updateRowCount();
+ grid.render();
+ });
+ })
+</script>
+</body>
</html>
diff --git a/examples/example1-simple.html b/examples/example1-simple.html
index 768f4f0..dfa7697 100644
--- a/examples/example1-simple.html
+++ b/examples/example1-simple.html
@@ -1,69 +1,68 @@
<!DOCTYPE HTML>
<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <title>SlickGrid example 1: Basic grid</title>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- </head>
- <body>
- <table width="100%">
- <tr>
- <td valign="top" width="50%">
- <div id="myGrid" style="width:600px;height:500px;display:none;"></div>
- </td>
- <td valign="top">
- <h2>Demonstrates:</h2>
- <ul>
- <li>basic grid with minimal configuration</li>
- </ul>
- </td>
- </tr>
- </table>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>SlickGrid example 1: Basic grid</title>
+ <link rel="stylesheet" href="../slick.grid.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" />
+</head>
+<body>
+<table width="100%">
+ <tr>
+ <td valign="top" width="50%">
+ <div id="myGrid" style="width:600px;height:500px;display:none;"></div>
+ </td>
+ <td valign="top">
+ <h2>Demonstrates:</h2>
+ <ul>
+ <li>basic grid with minimal configuration</li>
+ </ul>
+ </td>
+ </tr>
+</table>
- <script src="../lib/jquery-1.7.min.js"></script>
- <script src="../lib/jquery.event.drag-2.0.min.js"></script>
+<script src="../lib/jquery-1.7.min.js"></script>
+<script src="../lib/jquery.event.drag-2.0.min.js"></script>
- <script src="../slick.core.js"></script>
- <script src="../slick.grid.js"></script>
+<script src="../slick.core.js"></script>
+<script src="../slick.grid.js"></script>
- <script>
+<script>
- var grid;
+ var grid;
- var columns = [
- {id:"title", name:"Title", field:"title"},
- {id:"duration", name:"Duration", field:"duration"},
- {id:"%", name:"% Complete", field:"percentComplete"},
- {id:"start", name:"Start", field:"start"},
- {id:"finish", name:"Finish", field:"finish"},
- {id:"effort-driven", name:"Effort Driven", field:"effortDriven"}
- ];
+ var columns = [
+ {id:"title", name:"Title", field:"title"},
+ {id:"duration", name:"Duration", field:"duration"},
+ {id:"%", name:"% Complete", field:"percentComplete"},
+ {id:"start", name:"Start", field:"start"},
+ {id:"finish", name:"Finish", field:"finish"},
+ {id:"effort-driven", name:"Effort Driven", field:"effortDriven"}
+ ];
- var options = {
- enableCellNavigation: true,
- enableColumnReorder: false
- };
+ var options = {
+ enableCellNavigation:true,
+ enableColumnReorder:false
+ };
- $(function() {
- var data = [];
- for (var i = 0; i < 500; i++) {
- data[i] = {
- title: "Task " + i,
- duration: "5 days",
- percentComplete: Math.round(Math.random() * 100),
- start: "01/01/2009",
- finish: "01/05/2009",
- effortDriven: (i % 5 == 0)
- };
- }
+ $(function () {
+ var data = [];
+ for (var i = 0; i < 500; i++) {
+ data[i] = {
+ title: "Task " + i,
+ duration: "5 days",
+ percentComplete: Math.round(Math.random() * 100),
+ start: "01/01/2009",
+ finish: "01/05/2009",
+ effortDriven: (i % 5 == 0)
+ };
+ }
- grid = new Slick.Grid("#myGrid", data, columns, options);
+ grid = new Slick.Grid("#myGrid", data, columns, options);
- $("#myGrid").show();
- })
-
- </script>
- </body>
+ $("#myGrid").show();
+ })
+</script>
+</body>
</html>
diff --git a/examples/example10-async-post-render.html b/examples/example10-async-post-render.html
index 74b4a05..0b275e0 100644
--- a/examples/example10-async-post-render.html
+++ b/examples/example10-async-post-render.html
@@ -1,126 +1,134 @@
<!DOCTYPE HTML>
<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <title>SlickGrid example 10: Async post render</title>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- <style>
- .cell-title {
- font-weight: bold;
- }
-
- .cell-effort-driven {
- text-align: center;
- }
-
- .description * {
- font-size: 11pt;
- }
- </style>
- </head>
- <body>
- <div style="width:600px;float:left;">
- <div class="grid-header" style="width:100%">
- <label>Scores:</label>
- </div>
- <div id="myGrid" style="width:100%;height:500px;"></div>
- </div>
-
- <div style="margin-left:650px;margin-top:40px;" class="description">
- <h2>Demonstrates:</h2>
- <p>
- With SlickGrid, you can still have rich, complex cells rendered against the actual DOM nodes while still preserving the speed and responsiveness.
- This is achieved through async background post-rendering.
- SlickGrid exposes a <u>asyncPostRender</u> property on a column which you can use to set your own function that will manipulate the cell DOM node directly.
- The event is fired one by one for all visible rows in the viewport on a timer so it doesn't impact the UI responsiveness.
- You should still make sure that post-processing one row doesn't take too long though.
- SlickGrid will figure out what and when needs to be updated for you.
- </p>
- <p>
- The example below is a list of 500 rows with a title and 5 integer cells followed by graphical representation of these integers.
- The graph is drawn using a CANVAS element in the background.
- The grid is editable, so you can edit the numbers and see the changes reflected (almost) immediately in the graph.
- The graph cell behaves just like an ordinary cell and can be resized/reordered.
- The graphs themselves are created using the excellent <a href="http://www.omnipotent.net/jquery.sparkline/" target="_blank">jQuery Sparklines</a> library.
- </p>
- </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.0.min.js"></script>
- <script src="../lib/jquery.sparkline.min.js"></script>
-
- <script src="../slick.core.js"></script>
- <script src="../slick.editors.js"></script>
- <script src="../slick.grid.js"></script>
-
- <script>
- 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 waitingFormatter(value) {
- return "wait...";
- }
-
- function renderSparkline(cellNode, row, dataContext, colDef) {
- var vals = [
- dataContext["n1"],
- dataContext["n2"],
- dataContext["n3"],
- dataContext["n4"],
- dataContext["n5"]
- ];
-
- $(cellNode).empty().sparkline(vals, {width:"100%"});
- }
-
- var grid;
-
- var data = [];
-
- var columns = [
- {id:"title", name:"Title", field:"title", sortable:false, width:120, cssClass:"cell-title"},
- {id:"n1", name:"1", field:"n1", sortable:false, editor:IntegerCellEditor, width:40, validator:requiredFieldValidator},
- {id:"n2", name:"2", field:"n2", sortable:false, editor:IntegerCellEditor, width:40, validator:requiredFieldValidator},
- {id:"n3", name:"3", field:"n3", sortable:false, editor:IntegerCellEditor, width:40, validator:requiredFieldValidator},
- {id:"n4", name:"4", field:"n4", sortable:false, editor:IntegerCellEditor, width:40, validator:requiredFieldValidator},
- {id:"n5", name:"5", field:"n5", sortable:false, editor:IntegerCellEditor, width:40, validator:requiredFieldValidator},
- {id:"chart", name:"Chart", sortable:false, width:60, formatter:waitingFormatter, rerenderOnResize:true, asyncPostRender:renderSparkline}
- ];
-
- var options = {
- editable: true,
- enableAddRow: false,
- enableCellNavigation: true,
- asyncEditorLoading: false,
- enableAsyncPostRender: true
- };
-
-
- $(function()
- {
- for (var i=0; i<500; i++) {
- var d = (data[i] = {});
-
- d["title"] = "Record " + i;
- d["n1"] = Math.round(Math.random() * 10);
- d["n2"] = Math.round(Math.random() * 10);
- d["n3"] = Math.round(Math.random() * 10);
- d["n4"] = Math.round(Math.random() * 10);
- d["n5"] = Math.round(Math.random() * 10);
- }
-
-
- grid = new Slick.Grid("#myGrid", data, columns, options);
- })
- </script>
- </body>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>SlickGrid example 10: Async post render</title>
+ <link rel="stylesheet" href="../slick.grid.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" />
+ <style>
+ .cell-title {
+ font-weight: bold;
+ }
+
+ .cell-effort-driven {
+ text-align: center;
+ }
+
+ .description * {
+ font-size: 11pt;
+ }
+ </style>
+</head>
+<body>
+<div style="width:600px;float:left;">
+ <div class="grid-header" style="width:100%">
+ <label>Scores:</label>
+ </div>
+ <div id="myGrid" style="width:100%;height:500px;"></div>
+</div>
+
+<div style="margin-left:650px;margin-top:40px;" class="description">
+ <h2>Demonstrates:</h2>
+
+ <p>
+ With SlickGrid, you can still have rich, complex cells rendered against the actual DOM nodes while still preserving
+ the speed and responsiveness.
+ This is achieved through async background post-rendering.
+ SlickGrid exposes a <u>asyncPostRender</u> property on a column which you can use to set your own function that will
+ manipulate the cell DOM node directly.
+ The event is fired one by one for all visible rows in the viewport on a timer so it doesn't impact the UI
+ responsiveness.
+ You should still make sure that post-processing one row doesn't take too long though.
+ SlickGrid will figure out what and when needs to be updated for you.
+ </p>
+
+ <p>
+ The example below is a list of 500 rows with a title and 5 integer cells followed by graphical representation of
+ these integers.
+ The graph is drawn using a CANVAS element in the background.
+ The grid is editable, so you can edit the numbers and see the changes reflected (almost) immediately in the graph.
+ The graph cell behaves just like an ordinary cell and can be resized/reordered.
+ The graphs themselves are created using the excellent <a href="http://www.omnipotent.net/jquery.sparkline/"
+ target="_blank">jQuery Sparklines</a> library.
+ </p>
+</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.0.min.js"></script>
+<script src="../lib/jquery.sparkline.min.js"></script>
+
+<script src="../slick.core.js"></script>
+<script src="../slick.editors.js"></script>
+<script src="../slick.grid.js"></script>
+
+<script>
+ 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 waitingFormatter(value) {
+ return "wait...";
+ }
+
+ function renderSparkline(cellNode, row, dataContext, colDef) {
+ var vals = [
+ dataContext["n1"],
+ dataContext["n2"],
+ dataContext["n3"],
+ dataContext["n4"],
+ dataContext["n5"]
+ ];
+
+ $(cellNode).empty().sparkline(vals, {width:"100%"});
+ }
+
+ var grid;
+
+ var data = [];
+
+ var columns = [
+ {id:"title", name:"Title", field:"title", sortable:false, width:120, cssClass:"cell-title"},
+ {id:"n1", name:"1", field:"n1", sortable:false, editor:IntegerCellEditor, width:40, validator:requiredFieldValidator},
+ {id:"n2", name:"2", field:"n2", sortable:false, editor:IntegerCellEditor, width:40, validator:requiredFieldValidator},
+ {id:"n3", name:"3", field:"n3", sortable:false, editor:IntegerCellEditor, width:40, validator:requiredFieldValidator},
+ {id:"n4", name:"4", field:"n4", sortable:false, editor:IntegerCellEditor, width:40, validator:requiredFieldValidator},
+ {id:"n5", name:"5", field:"n5", sortable:false, editor:IntegerCellEditor, width:40, validator:requiredFieldValidator},
+ {id:"chart", name:"Chart", sortable:false, width:60, formatter:waitingFormatter, rerenderOnResize:true, asyncPostRender:renderSparkline}
+ ];
+
+ var options = {
+ editable:true,
+ enableAddRow:false,
+ enableCellNavigation:true,
+ asyncEditorLoading:false,
+ enableAsyncPostRender:true
+ };
+
+
+ $(function () {
+ for (var i = 0; i < 500; i++) {
+ var d = (data[i] = {});
+
+ d["title"] = "Record " + i;
+ d["n1"] = Math.round(Math.random() * 10);
+ d["n2"] = Math.round(Math.random() * 10);
+ d["n3"] = Math.round(Math.random() * 10);
+ d["n4"] = Math.round(Math.random() * 10);
+ d["n5"] = Math.round(Math.random() * 10);
+ }
+
+
+ grid = new Slick.Grid("#myGrid", data, columns, options);
+ })
+</script>
+</body>
</html>
diff --git a/examples/example11-autoheight.html b/examples/example11-autoheight.html
index 885d60e..072bd60 100644
--- a/examples/example11-autoheight.html
+++ b/examples/example11-autoheight.html
@@ -1,65 +1,84 @@
<!DOCTYPE html>
<html lang="en">
- <head>
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>SlickGrid example 11: No vertical scrolling (autoHeight)</title>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- <style>
- html,body { margin:0; padding:0; overflow:auto; }
- body { font:11px Helvetica,Arial,sans-serif; }
- #container { margin:10px; border:solid 1px gray; width:480px; background:white;}
- #description { position:fixed; top:30px; right:30px; width:25em; }
- </style>
- </head>
- <body>
- <div id="container"></div>
- <div id="description">
- <h2>Demonstrates:</h2>
- <ul>
- <li>autoHeight:true grid option</li>
- </ul>
- </div>
+<head>
+ <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title>SlickGrid example 11: No vertical scrolling (autoHeight)</title>
+ <link rel="stylesheet" href="../slick.grid.css" type="text/css" />
+ <link rel="stylesheet" href="examples.css" type="text/css" />
+ <style>
+ html, body {
+ margin: 0;
+ padding: 0;
+ overflow: auto;
+ }
- <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.0.min.js"></script>
+ body {
+ font: 11px Helvetica, Arial, sans-serif;
+ }
- <script src="../slick.core.js"></script>
- <script src="../slick.grid.js"></script>
+ #container {
+ margin: 10px;
+ border: solid 1px gray;
+ width: 480px;
+ background: white;
+ }
- <script>
- var grid,
- data = [],
- columns = [
- { id:"title", name:"Title", field:"title" },
- { id:"duration", name:"Duration", field:"duration" },
- { id:"%", name:"% Complete", field:"percentComplete" },
- { id:"start", name:"Start", field:"start" },
- { id:"finish", name:"Finish", field:"finish" },
- { id:"effort-driven", name:"Effort Driven", field:"effortDriven" }
- ],
- options = {
- editable: false,
- enableAddRow: false,
- enableCellNavigation: false,
- autoHeight: true
- };
+ #description {
+ position: fixed;
+ top: 30px;
+ right: 30px;
+ width: 25em;
+ }
+ </style>
+</head>
+<body>
+<div id="container"></div>
+<div id="description">
+ <h2>Demonstrates:</h2>
+ <ul>
+ <li>autoHeight:true grid option</li>
+ </ul>
+</div>
- for (var i = 100; i-- > 0;) {
- data[i] = {
- title: "Task " + i,
- duration: "5 days",
- percentComplete: Math.round(Math.random() * 100),
- start: "01/01/2009",
- finish: "01/05/2009",
- effortDriven: (i % 5 == 0)
- };
- }
+<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.0.min.js"></script>
- grid = new Slick.Grid("#container", data, columns, options);
- </script>
+<script src="../slick.core.js"></script>
+<script src="../slick.grid.js"></script>
- </body>
+<script>
+ var grid,
+ data = [],
+ columns = [
+ { id:"title", name:"Title", field:"title" },
+ { id:"duration", name:"Duration", field:"duration" },
+ { id:"%", name:"% Complete", field:"percentComplete" },
+ { id:"start", name:"Start", field:"start" },
+ { id:"finish", name:"Finish", field:"finish" },
+ { id:"effort-driven", name:"Effort Driven", field:"effortDriven" }
+ ],
+ options = {
+ editable:false,
+ enableAddRow:false,
+ enableCellNavigation:false,
+ autoHeight:true
+ };
+
+ for (var i = 100; i-- > 0;) {
+ data[i] = {
+ title:"Task " + i,
+ duration:"5 days",
+ percentComplete:Math.round(Math.random() * 100),
+ start:"01/01/2009",
+ finish:"01/05/2009",
+ effortDriven:(i % 5 == 0)
+ };
+ }
+
+ grid = new Slick.Grid("#container", data, columns, options);
+</script>
+
+</body>
</html> \ No newline at end of file
diff --git a/examples/example12-fillbrowser.html b/examples/example12-fillbrowser.html
index 5c728eb..464cda6 100644
--- a/examples/example12-fillbrowser.html
+++ b/examples/example12-fillbrowser.html
@@ -1,86 +1,113 @@
<!DOCTYPE html>
<html lang="en">
- <head>
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>SlickGrid example 12: Fill browser</title>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- <style>
- html,body { margin:0; padding:0; background-color:White; overflow:auto; }
- body { font:11px Helvetica,Arial,sans-serif; }
- #container { position:absolute; top:0; left:0; right:0; bottom:0; }
- #description { position:fixed; top:30px; right:30px; width:25em; background:beige; border:solid 1px gray; z-index:1000; }
- #description h2 { padding-left:0.5em; }
- </style>
- </head>
- <body>
- <div id="container"></div>
- <div id="description">
- <h2>Demonstrates:</h2>
- <ul>
- <li>Grid filling browser window completely (using absolute positioning)</li>
- <li>Grid resizing when browser window changes size</li>
- <li>Overall performance of the grid when displaying large tabular data (17 columns x 10,000 rows)</li>
- </ul>
- </div>
+<head>
+ <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title>SlickGrid example 12: Fill browser</title>
+ <link rel="stylesheet" href="../slick.grid.css" type="text/css" />
+ <link rel="stylesheet" href="examples.css" type="text/css" />
+ <style>
+ html, body {
+ margin: 0;
+ padding: 0;
+ background-color: White;
+ overflow: auto;
+ }
- <script src="../lib/jquery-1.7.min.js"></script>
- <script src="../lib/jquery.event.drag-2.0.min.js"></script>
+ body {
+ font: 11px Helvetica, Arial, sans-serif;
+ }
- <script src="../slick.core.js"></script>
- <script src="../slick.grid.js"></script>
- <script>
- var grid,
- data = [],
- columns = [
- { id:"title", name:"Title", field:"title", width:120 },
- { id:"duration", name:"Duration", field:"duration", width:120 },
- { id:"%", name:"% Complete", field:"percentComplete", width:120 },
- { id:"start", name:"Start", field:"start", width:120 },
- { id:"finish", name:"Finish", field:"finish", width:120 },
- { id:"effort-driven", name:"Effort Driven", field:"effortDriven", width:120 },
- { id:"c7", name:"C7", field:"c7", width:120 },
- { id:"c8", name:"C8", field:"c8", width:120 },
- { id:"c9", name:"C9", field:"c9", width:120 },
- { id:"c10", name:"C10", field:"c10", width:120 },
- { id:"c11", name:"C11", field:"c11", width:120 },
- { id:"c12", name:"C12", field:"c12", width:120 },
- { id:"c13", name:"C13", field:"c13", width:120 },
- { id:"c14", name:"C14", field:"c14", width:120 },
- { id:"c15", name:"C15", field:"c15", width:120 },
- { id:"c16", name:"C16", field:"c16", width:120 },
- { id:"c17", name:"C17", field:"c17", width:120 }
- ],
- options = {
- enableCellNavigation: false,
- enableColumnReorder: false
- };
+ #container {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ }
- for (var i = 10000; i-- > 0;) {
- data[i] = {
- title: "Task " + i,
- duration: "5 days",
- percentComplete: Math.round(Math.random() * 100),
- start: "01/01/2009",
- finish: "01/05/2009",
- effortDriven: (i % 5 == 0),
- c7: "C7-" + i,
- c8: "C8-" + i,
- c9: "C9-" + i,
- c10: "C10-" + i,
- c11: "C11-" + i,
- c12: "C12-" + i,
- c13: "C13-" + i,
- c14: "C14-" + i,
- c15: "C15-" + i,
- c16: "C16-" + i,
- c17: "C17-" + i
- };
- }
+ #description {
+ position: fixed;
+ top: 30px;
+ right: 30px;
+ width: 25em;
+ background: beige;
+ border: solid 1px gray;
+ z-index: 1000;
+ }
- grid = new Slick.Grid("#container", data, columns, options);
- </script>
+ #description h2 {
+ padding-left: 0.5em;
+ }
+ </style>
+</head>
+<body>
+<div id="container"></div>
+<div id="description">
+ <h2>Demonstrates:</h2>
+ <ul>
+ <li>Grid filling browser window completely (using absolute positioning)</li>
+ <li>Grid resizing when browser window changes size</li>
+ <li>Overall performance of the grid when displaying large tabular data (17 columns x 10,000 rows)</li>
+ </ul>
+</div>
- </body>
+<script src="../lib/jquery-1.7.min.js"></script>
+<script src="../lib/jquery.event.drag-2.0.min.js"></script>
+
+<script src="../slick.core.js"></script>
+<script src="../slick.grid.js"></script>
+<script>
+ var grid,
+ data = [],
+ columns = [
+ { id:"title", name:"Title", field:"title", width:120 },
+ { id:"duration", name:"Duration", field:"duration", width:120 },
+ { id:"%", name:"% Complete", field:"percentComplete", width:120 },
+ { id:"start", name:"Start", field:"start", width:120 },
+ { id:"finish", name:"Finish", field:"finish", width:120 },
+ { id:"effort-driven", name:"Effort Driven", field:"effortDriven", width:120 },
+ { id:"c7", name:"C7", field:"c7", width:120 },
+ { id:"c8", name:"C8", field:"c8", width:120 },
+ { id:"c9", name:"C9", field:"c9", width:120 },
+ { id:"c10", name:"C10", field:"c10", width:120 },
+ { id:"c11", name:"C11", field:"c11", width:120 },
+ { id:"c12", name:"C12", field:"c12", width:120 },
+ { id:"c13", name:"C13", field:"c13", width:120 },
+ { id:"c14", name:"C14", field:"c14", width:120 },
+ { id:"c15", name:"C15", field:"c15", width:120 },
+ { id:"c16", name:"C16", field:"c16", width:120 },
+ { id:"c17", name:"C17", field:"c17", width:120 }
+ ],
+ options = {
+ enableCellNavigation:false,
+ enableColumnReorder:false
+ };
+
+ for (var i = 10000; i-- > 0;) {
+ data[i] = {
+ title:"Task " + i,
+ duration:"5 days",
+ percentComplete:Math.round(Math.random() * 100),
+ start:"01/01/2009",
+ finish:"01/05/2009",
+ effortDriven:(i % 5 == 0),
+ c7:"C7-" + i,
+ c8:"C8-" + i,
+ c9:"C9-" + i,
+ c10:"C10-" + i,
+ c11:"C11-" + i,
+ c12:"C12-" + i,
+ c13:"C13-" + i,
+ c14:"C14-" + i,
+ c15:"C15-" + i,
+ c16:"C16-" + i,
+ c17:"C17-" + i
+ };
+ }
+
+ grid = new Slick.Grid("#container", data, columns, options);
+</script>
+
+</body>
</html> \ No newline at end of file
diff --git a/examples/example13-getItem-sorting.html b/examples/example13-getItem-sorting.html
index 1fb2656..bf693f8 100644
--- a/examples/example13-getItem-sorting.html
+++ b/examples/example13-getItem-sorting.html
@@ -1,97 +1,124 @@
<!DOCTYPE html>
<html lang="en">
- <head>
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>SlickGrid example 13: Indexed Sorting using Functional Data Provider</title>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- <style>
- html,body { margin:0; padding:0; background-color:White; overflow:auto; }
- body { font:11px Helvetica,Arial,sans-serif; }
- #container { position:absolute; top:0; left:0; right:0; bottom:0; }
- #description { position:fixed; top:30px; right:30px; width:25em; background-color:beige; border:solid 1px gray; z-index:1000; }
- #description h2 { padding-left:0.5em; }
- </style>
- </head>
- <body>
- <div id="container"></div>
- <div id="description">
- <h2>Demonstrates:</h2>
- <ul>
- <li>Sorting grid items by an index</li>
- <li>Using the getItem method to provide data</li>
- </ul>
- </div>
+<head>
+ <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title>SlickGrid example 13: Indexed Sorting using Functional Data Provider</title>
+ <link rel="stylesheet" href="../slick.grid.css" type="text/css" />
+ <link rel="stylesheet" href="examples.css" type="text/css" />
+ <style>
+ html, body {
+ margin: 0;
+ padding: 0;
+ background-color: White;
+ overflow: auto;
+ }
- <script src="../lib/jquery-1.7.min.js"></script>
- <script src="../lib/jquery.event.drag-2.0.min.js"></script>
- <script src="../slick.core.js"></script>
- <script src="../slick.grid.js"></script>
+ body {
+ font: 11px Helvetica, Arial, sans-serif;
+ }
- <script>
- var grid,
- data = [],
- columns = [
- { id: "title", name: "Title", field: "title", width: 240, sortable: true },
- { id: "c1", name: "Sort 1", field: "c1", width: 240, sortable: true },
- { id: "c2", name: "Sort 2", field: "c2", width: 240, sortable: true },
- { id: "c3", name: "Sort 3", field: "c3", width: 240, sortable: true }
- ],
- options = {
- enableCellNavigation: false,
- enableColumnReorder: false
- }, numberOfItems = 25000, items = [], indices, isAsc = true, currentSortCol = { id: "title" }, i;
+ #container {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ }
+ #description {
+ position: fixed;
+ top: 30px;
+ right: 30px;
+ width: 25em;
+ background-color: beige;
+ border: solid 1px gray;
+ z-index: 1000;
+ }
- function randomize(items) {
- /// <summary>
- /// Copies and shuffles the specified array and returns a new shuffled array.
- /// </summary>
- var randomItems = $.extend(true, null, items), randomIndex, temp, index;
- for (index = items.length; index-- > 0;) {
- randomIndex = Math.round(Math.random() * items.length - 1);
- if (randomIndex > -1) {
- temp = randomItems[randomIndex];
- randomItems[randomIndex] = randomItems[index];
- randomItems[index] = temp;
- }
- }
- return randomItems;
- }
+ #description h2 {
+ padding-left: 0.5em;
+ }
+ </style>
+</head>
+<body>
+<div id="container"></div>
+<div id="description">
+ <h2>Demonstrates:</h2>
+ <ul>
+ <li>Sorting grid items by an index</li>
+ <li>Using the getItem method to provide data</li>
+ </ul>
+</div>
- /// Build the items and indices.
- for (i = numberOfItems; i-- > 0;) {
- items[i] = i;
- data[i] = {
- title: "Task ".concat(i + 1)
- };
- }
- indices = { title: items, c1: randomize(items), c2: randomize(items), c3: randomize(items) };
+<script src="../lib/jquery-1.7.min.js"></script>
+<script src="../lib/jquery.event.drag-2.0.min.js"></script>
+<script src="../slick.core.js"></script>
+<script src="../slick.grid.js"></script>
- // Assign values to the data.
- for (i = numberOfItems; i-- > 0;) {
- data[indices.c1[i]].c1 = "Value ".concat(i + 1);
- data[indices.c2[i]].c2 = "Value ".concat(i + 1);
- data[indices.c3[i]].c3 = "Value ".concat(i + 1);
- }
+<script>
+ var grid,
+ data = [],
+ columns = [
+ { id:"title", name:"Title", field:"title", width:240, sortable:true },
+ { id:"c1", name:"Sort 1", field:"c1", width:240, sortable:true },
+ { id:"c2", name:"Sort 2", field:"c2", width:240, sortable:true },
+ { id:"c3", name:"Sort 3", field:"c3", width:240, sortable:true }
+ ],
+ options = {
+ enableCellNavigation:false,
+ enableColumnReorder:false
+ }, numberOfItems = 25000, items = [], indices, isAsc = true, currentSortCol = { id:"title" }, i;
- // Define function used to get the data and sort it.
- function getItem(index) {
- return isAsc ? data[indices[currentSortCol.id][index]] : data[indices[currentSortCol.id][(data.length - 1) - index]];
- }
- function getLength() {
- return data.length;
- }
- grid = new Slick.Grid("#container", {getLength: getLength, getItem: getItem}, columns, options);
- grid.onSort.subscribe(function(e,args) {
- currentSortCol = args.sortCol;
- isAsc = args.sortAsc;
- grid.invalidateAllRows();
- grid.render();
- });
- </script>
+ function randomize(items) {
+ /// <summary>
+ /// Copies and shuffles the specified array and returns a new shuffled array.
+ /// </summary>
+ var randomItems = $.extend(true, null, items), randomIndex, temp, index;
+ for (index = items.length; index-- > 0;) {
+ randomIndex = Math.round(Math.random() * items.length - 1);
+ if (randomIndex > -1) {
+ temp = randomItems[randomIndex];
+ randomItems[randomIndex] = randomItems[index];
+ randomItems[index] = temp;
+ }
+ }
+ return randomItems;
+ }
- </body>
+ /// Build the items and indices.
+ for (i = numberOfItems; i-- > 0;) {
+ items[i] = i;
+ data[i] = {
+ title:"Task ".concat(i + 1)
+ };
+ }
+ indices = { title:items, c1:randomize(items), c2:randomize(items), c3:randomize(items) };
+
+ // Assign values to the data.
+ for (i = numberOfItems; i-- > 0;) {
+ data[indices.c1[i]].c1 = "Value ".concat(i + 1);
+ data[indices.c2[i]].c2 = "Value ".concat(i + 1);
+ data[indices.c3[i]].c3 = "Value ".concat(i + 1);
+ }
+
+ // Define function used to get the data and sort it.
+ function getItem(index) {
+ return isAsc ? data[indices[currentSortCol.id][index]] : data[indices[currentSortCol.id][(data.length - 1) - index]];
+ }
+ function getLength() {
+ return data.length;
+ }
+
+ grid = new Slick.Grid("#container", {getLength:getLength, getItem:getItem}, columns, options);
+ grid.onSort.subscribe(function (e, args) {
+ currentSortCol = args.sortCol;
+ isAsc = args.sortAsc;
+ grid.invalidateAllRows();
+ grid.render();
+ });
+</script>
+
+</body>
</html> \ No newline at end of file
diff --git a/examples/example14-highlighting.html b/examples/example14-highlighting.html
index 3ac061f..928feae 100644
--- a/examples/example14-highlighting.html
+++ b/examples/example14-highlighting.html
@@ -1,149 +1,156 @@
<!DOCTYPE HTML>
<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <title>SlickGrid example 14: Highlighting and Flashing cells</title>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- <style>
- .load-medium {
- color: orange;
- font-weight: bold;
- }
- .load-hi {
- color: red;
- font-weight: bold;
- }
- .changed {
- background: pink;
- }
- .current-server {
- border: 1px solid black;
- background: orange;
- }
- </style>
- </head>
- <body>
- <div style="position:relative">
- <div style="width:520px;">
- <div id="myGrid" style="width:100%;height:500px;"></div>
- </div>
-
- <div class="options-panel">
- <h2>About</h2>
- This example simulates a real-time display of CPU utilization in a web farm.
- Data is updated in real-time, and cells with changed data are highlighted.
- You can also click "Find current server" to scroll the row displaying data for the current
- server into view and flash it.
- <h2>Demonstrates</h2>
- <ul>
- <li>setHighlightedCells()</li>
- <li>flashCell()</li>
- </ul>
- <h2>Controls</h2>
- <button onclick="simulateRealTimeUpdates()">Start simulation</button>
- <button onclick="findCurrentServer()">Find current server</button>
- </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.0.min.js"></script>
-
- <script src="../slick.core.js"></script>
- <script src="../plugins/slick.cellselectionmodel.js"></script>
- <script src="../plugins/slick.rowmovemanager.js"></script>
- <script src="../slick.editors.js"></script>
- <script src="../slick.grid.js"></script>
-
- <script>
- var grid;
- var data = [];
- var columns = [{id:"server", name:"Server", field:"server", width:180}];
- var currentServer;
-
- function cpuUtilizationFormatter(row, cell, value, columnDef, dataContext) {
- if (value > 90)
- return "<span class='load-hi'>" + value + "%</span>";
- else if (value > 70)
- return "<span class='load-medium'>" + value + "%</span>";
- else
- return value + "%";
- }
-
- for (var i=0; i<4; i++) {
- columns.push({
- id: "cpu" + i,
- name: "CPU" + i,
- field: i,
- width: 80,
- formatter: cpuUtilizationFormatter
- });
- }
-
- var options = {
- editable: false,
- enableAddRow: false,
- enableCellNavigation: true,
- cellHighlightCssClass: "changed",
- cellFlashingCssClass: "current-server"
- };
-
-
-
- $(function()
- {
- for (var i=0; i<500; i++) {
- var d = (data[i] = {});
- d.server = "Server " + i;
- for (var j=0; j<columns.length; j++) {
- d[j] = Math.round(Math.random()*100);
- }
- }
-
- grid = new Slick.Grid("#myGrid", data, columns, options);
-
- currentServer = Math.round(Math.random()*(data.length-1));
- });
-
-
- function simulateRealTimeUpdates() {
- var changes = {};
- var numberOfUpdates = Math.round(Math.random()*(data.length/10));
- for (var i=0; i<numberOfUpdates; i++) {
- var server = Math.round(Math.random()*(data.length-1));
- var cpu = Math.round(Math.random()*(columns.length-1));
- var delta = Math.round(Math.random()*50)-25;
- var col = grid.getColumnIndex("cpu" + cpu);
- var val = data[server][col] + delta;
- val = Math.max(0,val);
- val = Math.min(100,val);
-
- data[server][col] = val;
-
- if (!changes[server])
- changes[server] = {};
-
- changes[server]["cpu" + cpu] = "changed";
-
- grid.invalidateRow(server);
- }
-
- grid.setCellCssStyles("highlight", changes);
- grid.render();
-
- setTimeout(simulateRealTimeUpdates, 500);
- }
-
- function findCurrentServer() {
- grid.scrollRowIntoView(currentServer);
- grid.flashCell(currentServer,grid.getColumnIndex("server"),100);
- }
-
- </script>
-
- </body>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>SlickGrid example 14: Highlighting and Flashing cells</title>
+ <link rel="stylesheet" href="../slick.grid.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" />
+ <style>
+ .load-medium {
+ color: orange;
+ font-weight: bold;
+ }
+
+ .load-hi {
+ color: red;
+ font-weight: bold;
+ }
+
+ .changed {
+ background: pink;
+ }
+
+ .current-server {
+ border: 1px solid black;
+ background: orange;
+ }
+ </style>
+</head>
+<body>
+<div style="position:relative">
+ <div style="width:520px;">
+ <div id="myGrid" style="width:100%;height:500px;"></div>
+ </div>
+
+ <div class="options-panel">
+ <h2>About</h2>
+ This example simulates a real-time display of CPU utilization in a web farm.
+ Data is updated in real-time, and cells with changed data are highlighted.
+ You can also click "Find current server" to scroll the row displaying data for the current
+ server into view and flash it.
+ <h2>Demonstrates</h2>
+ <ul>
+ <li>setHighlightedCells()</li>
+ <li>flashCell()</li>
+ </ul>
+ <h2>Controls</h2>
+ <button onclick="simulateRealTimeUpdates()">Start simulation</button>
+ <button onclick="findCurrentServer()">Find current server</button>
+ </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.0.min.js"></script>
+
+<script src="../slick.core.js"></script>
+<script src="../plugins/slick.cellselectionmodel.js"></script>
+<script src="../plugins/slick.rowmovemanager.js"></script>
+<script src="../slick.editors.js"></script>
+<script src="../slick.grid.js"></script>
+
+<script>
+ var grid;
+ var data = [];
+ var columns = [
+ {id:"server", name:"Server", field:"server", width:180}
+ ];
+ var currentServer;
+
+ function cpuUtilizationFormatter(row, cell, value, columnDef, dataContext) {
+ if (value > 90) {
+ return "<span class='load-hi'>" + value + "%</span>";
+ }
+ else if (value > 70) {
+ return "<span class='load-medium'>" + value + "%</span>";
+ }
+ else {
+ return value + "%";
+ }
+ }
+
+ for (var i = 0; i < 4; i++) {
+ columns.push({
+ id:"cpu" + i,
+ name:"CPU" + i,
+ field:i,
+ width:80,
+ formatter:cpuUtilizationFormatter
+ });
+ }
+
+ var options = {
+ editable:false,
+ enableAddRow:false,
+ enableCellNavigation:true,
+ cellHighlightCssClass:"changed",
+ cellFlashingCssClass:"current-server"
+ };
+
+
+ $(function () {
+ for (var i = 0; i < 500; i++) {
+ var d = (data[i] = {});
+ d.server = "Server " + i;
+ for (var j = 0; j < columns.length; j++) {
+ d[j] = Math.round(Math.random() * 100);
+ }
+ }
+
+ grid = new Slick.Grid("#myGrid", data, columns, options);
+
+ currentServer = Math.round(Math.random() * (data.length - 1));
+ });
+
+
+ function simulateRealTimeUpdates() {
+ var changes = {};
+ var numberOfUpdates = Math.round(Math.random() * (data.length / 10));
+ for (var i = 0; i < numberOfUpdates; i++) {
+ var server = Math.round(Math.random() * (data.length - 1));
+ var cpu = Math.round(Math.random() * (columns.length - 1));
+ var delta = Math.round(Math.random() * 50) - 25;
+ var col = grid.getColumnIndex("cpu" + cpu);
+ var val = data[server][col] + delta;
+ val = Math.max(0, val);
+ val = Math.min(100, val);
+
+ data[server][col] = val;
+
+ if (!changes[server]) {
+ changes[server] = {};
+ }
+
+ changes[server]["cpu" + cpu] = "changed";
+
+ grid.invalidateRow(server);
+ }
+
+ grid.setCellCssStyles("highlight", changes);
+ grid.render();
+
+ setTimeout(simulateRealTimeUpdates, 500);
+ }
+
+ function findCurrentServer() {
+ grid.scrollRowIntoView(currentServer);
+ grid.flashCell(currentServer, grid.getColumnIndex("server"), 100);
+ }
+
+</script>
+
+</body>
</html>
diff --git a/examples/example2-formatters.html b/examples/example2-formatters.html
index d7f77e3..e260535 100644
--- a/examples/example2-formatters.html
+++ b/examples/example2-formatters.html
@@ -1,85 +1,79 @@
<!DOCTYPE HTML>
<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <title>SlickGrid example 2: Formatters</title>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- <style>
- .cell-title {
- font-weight: bold;
- }
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>SlickGrid example 2: Formatters</title>
+ <link rel="stylesheet" href="../slick.grid.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" />
+ <style>
+ .cell-title {
+ font-weight: bold;
+ }
- .cell-effort-driven {
- text-align: center;
- }
- </style>
- </head>
- <body>
- <table width="100%">
- <tr>
- <td valign="top" width="50%">
- <div id="myGrid" style="width:600px;height:500px;"></div>
- </td>
- <td valign="top">
- <h2>Demonstrates:</h2>
- <ul>
- <li>width, minWidth, maxWidth, resizable, cssClass column attributes</li>
- <li>custom column formatters</li>
- </ul>
- </td>
- </tr>
- </table>
+ .cell-effort-driven {
+ text-align: center;
+ }
+ </style>
+</head>
+<body>
+<table width="100%">
+ <tr>
+ <td valign="top" width="50%">
+ <div id="myGrid" style="width:600px;height:500px;"></div>
+ </td>
+ <td valign="top">
+ <h2>Demonstrates:</h2>
+ <ul>
+ <li>width, minWidth, maxWidth, resizable, cssClass column attributes</li>
+ <li>custom column formatters</li>
+ </ul>
+ </td>
+ </tr>
+</table>
- <script src="../lib/firebugx.js"></script>
+<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.0.min.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.0.min.js"></script>
- <script src="../slick.core.js"></script>
- <script src="../slick.editors.js"></script>
- <script src="../slick.grid.js"></script>
+<script src="../slick.core.js"></script>
+<script src="../slick.editors.js"></script>
+<script src="../slick.grid.js"></script>
- <script>
- var grid;
+<script>
+ var grid;
+ var data = [];
+ var columns = [
+ {id:"title", name:"Title", field:"title", width:120, cssClass:"cell-title"},
+ {id:"duration", name:"Duration", field:"duration"},
+ {id:"%", name:"% Complete", field:"percentComplete", width:80, resizable:false, formatter:GraphicalPercentCompleteCellFormatter},
+ {id:"start", name:"Start", field:"start", minWidth:60},
+ {id:"finish", name:"Finish", field:"finish", minWidth:60},
+ {id:"effort-driven", name:"Effort Driven", sortable:false, width:80, minWidth:20, maxWidth:80, cssClass:"cell-effort-driven", field:"effortDriven", formatter:BoolCellFormatter}
+ ];
- var data = [];
+ var options = {
+ editable:false,
+ enableAddRow:false,
+ enableCellNavigation:true
+ };
- var columns = [
- {id:"title", name:"Title", field:"title", width:120, cssClass:"cell-title"},
- {id:"duration", name:"Duration", field:"duration"},
- {id:"%", name:"% Complete", field:"percentComplete", width:80, resizable:false, formatter:GraphicalPercentCompleteCellFormatter},
- {id:"start", name:"Start", field:"start", minWidth:60},
- {id:"finish", name:"Finish", field:"finish", minWidth:60},
- {id:"effort-driven", name:"Effort Driven", sortable:false, width:80, minWidth:20, maxWidth:80, cssClass:"cell-effort-driven", field:"effortDriven", formatter:BoolCellFormatter}
- ];
+ $(function () {
+ for (var i = 0; i < 500; i++) {
+ var d = (data[i] = {});
- var options = {
- editable: false,
- enableAddRow: false,
- enableCellNavigation: true
- };
+ d["title"] = "Task " + i;
+ d["duration"] = "5 days";
+ d["percentComplete"] = Math.min(100, Math.round(Math.random() * 110));
+ d["start"] = "01/01/2009";
+ d["finish"] = "01/05/2009";
+ d["effortDriven"] = (i % 5 == 0);
+ }
-
- $(function()
- {
- for (var i=0; i<500; i++) {
- var d = (data[i] = {});
-
- d["title"] = "Task " + i;
- d["duration"] = "5 days";
- d["percentComplete"] = Math.min(100, Math.round(Math.random() * 110));
- d["start"] = "01/01/2009";
- d["finish"] = "01/05/2009";
- d["effortDriven"] = (i % 5 == 0);
- }
-
- grid = new Slick.Grid("#myGrid", data, columns, options);
- })
-
- </script>
-
- </body>
+ grid = new Slick.Grid("#myGrid", data, columns, options);
+ })
+</script>
+</body>
</html>
diff --git a/examples/example3-editing.html b/examples/example3-editing.html
index 154a6e5..d0c79f6 100644
--- a/examples/example3-editing.html
+++ b/examples/example3-editing.html
@@ -1,111 +1,106 @@
<!DOCTYPE HTML>
<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <title>SlickGrid example 3: Editing</title>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- <style>
- .cell-title {
- font-weight: bold;
- }
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>SlickGrid example 3: Editing</title>
+ <link rel="stylesheet" href="../slick.grid.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" />
+ <style>
+ .cell-title {
+ font-weight: bold;
+ }
- .cell-effort-driven {
- text-align: center;
- }
- </style>
- </head>
- <body>
- <div style="position:relative">
- <div style="width:600px;">
- <div id="myGrid" style="width:100%;height:500px;"></div>
- </div>
+ .cell-effort-driven {
+ text-align: center;
+ }
+ </style>
+</head>
+<body>
+<div style="position:relative">
+ <div style="width:600px;">
+ <div id="myGrid" style="width:100%;height:500px;"></div>
+ </div>
- <div class="options-panel">
- <h2>Demonstrates:</h2>
- <ul>
- <li>adding basic keyboard navigation and editing</li>
- <li>custom editors and validators</li>
- <li>auto-edit settings</li>
- </ul>
+ <div class="options-panel">
+ <h2>Demonstrates:</h2>
+ <ul>
+ <li>adding basic keyboard navigation and editing</li>
+ <li>custom editors and validators</li>
+ <li>auto-edit settings</li>
+ </ul>
- <h2>Options:</h2>
- <button onclick="grid.setOptions({autoEdit:true})">Auto-edit ON</button>
- &nbsp;
- <button onclick="grid.setOptions({autoEdit:false})">Auto-edit OFF</button>
- </div>
- </div>
+ <h2>Options:</h2>
+ <button onclick="grid.setOptions({autoEdit:true})">Auto-edit ON</button>
+ &nbsp;
+ <button onclick="grid.setOptions({autoEdit:false})">Auto-edit OFF</button>
+ </div>
+</div>
- <script src="../lib/firebugx.js"></script>
+<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.0.min.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.0.min.js"></script>
- <script src="../slick.core.js"></script>
- <script src="../plugins/slick.cellrangedecorator.js"></script>
- <script src="../plugins/slick.cellrangeselector.js"></script>
- <script src="../plugins/slick.cellselectionmodel.js"></script>
- <script src="../slick.editors.js"></script>
- <script src="../slick.grid.js"></script>
+<script src="../slick.core.js"></script>
+<script src="../plugins/slick.cellselectionmodel.js"></script>
+<script src="../slick.editors.js"></script>
+<script src="../slick.grid.js"></script>
- <script>
- 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};
- }
+<script>
+ 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};
+ }
+ }
- var grid;
- var data = [];
- var columns = [
- {id:"title", name:"Title", field:"title", width:120, cssClass:"cell-title", editor:TextCellEditor, validator:requiredFieldValidator},
- {id:"desc", name:"Description", field:"description", width:100, editor:LongTextCellEditor},
- {id:"duration", name:"Duration", field:"duration", editor:TextCellEditor},
- {id:"%", name:"% Complete", field:"percentComplete", width:80, resizable:false, formatter:GraphicalPercentCompleteCellFormatter, editor:PercentCompleteCellEditor},
- {id:"start", name:"Start", field:"start", minWidth:60, editor:DateCellEditor},
- {id:"finish", name:"Finish", field:"finish", minWidth:60, editor:DateCellEditor},
- {id:"effort-driven", name:"Effort Driven", width:80, minWidth:20, maxWidth:80, cssClass:"cell-effort-driven", field:"effortDriven", formatter:BoolCellFormatter, editor:YesNoCheckboxCellEditor}
- ];
- var options = {
- editable: true,
- enableAddRow: true,
- enableCellNavigation: true,
- asyncEditorLoading: false,
- autoEdit: false
- };
+ var grid;
+ var data = [];
+ var columns = [
+ {id:"title", name:"Title", field:"title", width:120, cssClass:"cell-title", editor:TextCellEditor, validator:requiredFieldValidator},
+ {id:"desc", name:"Description", field:"description", width:100, editor:LongTextCellEditor},
+ {id:"duration", name:"Duration", field:"duration", editor:TextCellEditor},
+ {id:"%", name:"% Complete", field:"percentComplete", width:80, resizable:false, formatter:GraphicalPercentCompleteCellFormatter, editor:PercentCompleteCellEditor},
+ {id:"start", name:"Start", field:"start", minWidth:60, editor:DateCellEditor},
+ {id:"finish", name:"Finish", field:"finish", minWidth:60, editor:DateCellEditor},
+ {id:"effort-driven", name:"Effort Driven", width:80, minWidth:20, maxWidth:80, cssClass:"cell-effort-driven", field:"effortDriven", formatter:BoolCellFormatter, editor:YesNoCheckboxCellEditor}
+ ];
+ var options = {
+ editable:true,
+ enableAddRow:true,
+ enableCellNavigation:true,
+ asyncEditorLoading:false,
+ autoEdit:false
+ };
- $(function()
- {
- for (var i=0; i<500; i++) {
- var d = (data[i] = {});
+ $(function () {
+ for (var i = 0; i < 500; i++) {
+ var d = (data[i] = {});
- d["title"] = "Task " + i;
- d["description"] = "This is a sample task description.\n It can be multiline";
- 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);
- }
+ d["title"] = "Task " + i;
+ d["description"] = "This is a sample task description.\n It can be multiline";
+ 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);
+ }
- grid = new Slick.Grid("#myGrid", data, columns, options);
+ grid = new Slick.Grid("#myGrid", data, columns, options);
- //grid.registerPlugin(new Slick.CellRangeSelector());
+ grid.setSelectionModel(new Slick.CellSelectionModel());
- grid.setSelectionModel(new Slick.CellSelectionModel());
-
- grid.onAddNewRow.subscribe(function(e, args) {
- var item = args.item;
- var column = args.column;
- grid.invalidateRow(data.length);
- data.push(item);
- grid.updateRowCount();
- grid.render();
- });
- })
- </script>
- </body>
+ grid.onAddNewRow.subscribe(function (e, args) {
+ var item = args.item;
+ grid.invalidateRow(data.length);
+ data.push(item);
+ grid.updateRowCount();
+ grid.render();
+ });
+ })
+</script>
+</body>
</html>
diff --git a/examples/example3a-compound-editors.html b/examples/example3a-compound-editors.html
index b80b306..c5bcfbe 100644
--- a/examples/example3a-compound-editors.html
+++ b/examples/example3a-compound-editors.html
@@ -1,143 +1,144 @@
<!DOCTYPE HTML>
<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <title>SlickGrid example 3a: Advanced Editing</title>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- <style>
- .cell-title {
- font-weight: bold;
- }
- </style>
- </head>
- <body>
-
- <div style="position:relative">
- <div style="width:600px;">
- <div id="myGrid" style="width:100%;height:500px;"></div>
- </div>
-
- <div class="options-panel">
- <h2>Demonstrates:</h2>
- <ul>
- <li>compound cell editors driving multiple fields from one cell</li>
- <li>providing validation from the editor</li>
- <li>hooking into validation events</li>
- </ul>
- </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.0.min.js"></script>
-
- <script src="../slick.core.js"></script>
- <script src="../slick.editors.js"></script>
- <script src="../slick.grid.js"></script>
-
- <script>
- var grid;
- var data = [];
-
- var columns = [
- {id:"title", name:"Title", field:"title", width:120, cssClass:"cell-title", editor:TextCellEditor},
- {id:"range", name:"Range", width:120, formatter:NumericRangeFormatter, editor:NumericRangeEditor}
- ];
-
- var options = {
- editable: true,
- enableAddRow: false,
- enableCellNavigation: true,
- asyncEditorLoading: false
- };
-
- function NumericRangeFormatter(row, cell, value, columnDef, dataContext) {
- return dataContext.from + " - " + dataContext.to;
- }
-
- function NumericRangeEditor(args) {
- var $from, $to;
- var scope = this;
-
- this.init = function() {
- $from = $("<INPUT type=text style='width:40px' />")
- .appendTo(args.container)
- .bind("keydown", scope.handleKeyDown);
-
- $(args.container).append("&nbsp; to &nbsp;");
-
- $to = $("<INPUT type=text style='width:40px' />")
- .appendTo(args.container)
- .bind("keydown", scope.handleKeyDown);
-
- scope.focus();
- };
-
- this.handleKeyDown = function(e) {
- if (e.keyCode == $.ui.keyCode.LEFT || e.keyCode == $.ui.keyCode.RIGHT || e.keyCode == $.ui.keyCode.TAB) {
- e.stopImmediatePropagation();
- }
- };
-
- this.destroy = function() {
- $(args.container).empty();
- };
-
- this.focus = function() {
- $from.focus();
- };
-
- this.serializeValue = function() {
- return {from:parseInt($from.val(),10), to:parseInt($to.val(),10)};
- };
-
- this.applyValue = function(item,state) {
- item.from = state.from;
- item.to = state.to;
- };
-
- this.loadValue = function(item) {
- $from.val(item.from);
- $to.val(item.to);
- };
-
- this.isValueChanged = function() {
- return args.item.from != parseInt($from.val(),10) || args.item.to != parseInt($from.val(),10);
- };
-
- this.validate = function() {
- if (isNaN(parseInt($from.val(),10)) || isNaN(parseInt($to.val(),10)))
- return {valid: false, msg: "Please type in valid numbers."};
-
- if (parseInt($from.val(),10) > parseInt($to.val(),10))
- return {valid: false, msg: "'from' cannot be greater than 'to'"};
-
- return {valid: true, msg: null};
- };
-
- this.init();
- }
-
- $(function()
- {
- for (var i=0; i<500; i++) {
- var d = (data[i] = {});
-
- d["title"] = "Task " + i;
- d["from"] = Math.round(Math.random() * 100);
- d["to"] = d["from"] + Math.round(Math.random() * 100);
- }
-
- grid = new Slick.Grid("#myGrid", data, columns, options);
-
- grid.onValidationError.subscribe(function(e,args) {
- alert(args.validationResults.msg);
- });
- })
- </script>
- </body>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>SlickGrid example 3a: Advanced Editing</title>
+ <link rel="stylesheet" href="../slick.grid.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" />
+ <style>
+ .cell-title {
+ font-weight: bold;
+ }
+ </style>
+</head>
+<body>
+
+<div style="position:relative">
+ <div style="width:600px;">
+ <div id="myGrid" style="width:100%;height:500px;"></div>
+ </div>
+
+ <div class="options-panel">
+ <h2>Demonstrates:</h2>
+ <ul>
+ <li>compound cell editors driving multiple fields from one cell</li>
+ <li>providing validation from the editor</li>
+ <li>hooking into validation events</li>
+ </ul>
+ </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.0.min.js"></script>
+
+<script src="../slick.core.js"></script>
+<script src="../slick.editors.js"></script>
+<script src="../slick.grid.js"></script>
+
+<script>
+ var grid;
+ var data = [];
+
+ var columns = [
+ {id:"title", name:"Title", field:"title", width:120, cssClass:"cell-title", editor:TextCellEditor},
+ {id:"range", name:"Range", width:120, formatter:NumericRangeFormatter, editor:NumericRangeEditor}
+ ];
+
+ var options = {
+ editable:true,
+ enableAddRow:false,
+ enableCellNavigation:true,
+ asyncEditorLoading:false
+ };
+
+ function NumericRangeFormatter(row, cell, value, columnDef, dataContext) {
+ return dataContext.from + " - " + dataContext.to;
+ }
+
+ function NumericRangeEditor(args) {
+ var $from, $to;
+ var scope = this;
+
+ this.init = function () {
+ $from = $("<INPUT type=text style='width:40px' />")
+ .appendTo(args.container)
+ .bind("keydown", scope.handleKeyDown);
+
+ $(args.container).append("&nbsp; to &nbsp;");
+
+ $to = $("<INPUT type=text style='width:40px' />")
+ .appendTo(args.container)
+ .bind("keydown", scope.handleKeyDown);
+
+ scope.focus();
+ };
+
+ this.handleKeyDown = function (e) {
+ if (e.keyCode == $.ui.keyCode.LEFT || e.keyCode == $.ui.keyCode.RIGHT || e.keyCode == $.ui.keyCode.TAB) {
+ e.stopImmediatePropagation();
+ }
+ };
+
+ this.destroy = function () {
+ $(args.container).empty();
+ };
+
+ this.focus = function () {
+ $from.focus();
+ };
+
+ this.serializeValue = function () {
+ return {from:parseInt($from.val(), 10), to:parseInt($to.val(), 10)};
+ };
+
+ this.applyValue = function (item, state) {
+ item.from = state.from;
+ item.to = state.to;
+ };
+
+ this.loadValue = function (item) {
+ $from.val(item.from);
+ $to.val(item.to);
+ };
+
+ this.isValueChanged = function () {
+ return args.item.from != parseInt($from.val(), 10) || args.item.to != parseInt($from.val(), 10);
+ };
+
+ this.validate = function () {
+ if (isNaN(parseInt($from.val(), 10)) || isNaN(parseInt($to.val(), 10))) {
+ return {valid:false, msg:"Please type in valid numbers."};
+ }
+
+ if (parseInt($from.val(), 10) > parseInt($to.val(), 10)) {
+ return {valid:false, msg:"'from' cannot be greater than 'to'"};
+ }
+
+ return {valid:true, msg:null};
+ };
+
+ this.init();
+ }
+
+ $(function () {
+ for (var i = 0; i < 500; i++) {
+ var d = (data[i] = {});
+
+ d["title"] = "Task " + i;
+ d["from"] = Math.round(Math.random() * 100);
+ d["to"] = d["from"] + Math.round(Math.random() * 100);
+ }
+
+ grid = new Slick.Grid("#myGrid", data, columns, options);
+
+ grid.onValidationError.subscribe(function (e, args) {
+ alert(args.validationResults.msg);
+ });
+ })
+</script>
+</body>
</html>
diff --git a/examples/example3b-editing-with-undo.html b/examples/example3b-editing-with-undo.html
index b1a318e..1301145 100644
--- a/examples/example3b-editing-with-undo.html
+++ b/examples/example3b-editing-with-undo.html
@@ -1,109 +1,110 @@
<!DOCTYPE HTML>
<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <title>SlickGrid example 3: Editing</title>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- <style>
- .cell-title {
- font-weight: bold;
- }
-
- .cell-effort-driven {
- text-align: center;
- }
- </style>
- </head>
- <body>
- <div style="position:relative">
- <div style="width:600px;">
- <div id="myGrid" style="width:100%;height:500px;"></div>
- </div>
-
- <div class="options-panel">
- <h2>Demonstrates:</h2>
- <ul>
- <li>Using "editCommandHandler" option to intercept edit commands and implement undo support</li>
- </ul>
-
- <h2>Controls:</h2>
- <button onclick="undo()"><img src="../images/arrow_undo.png" align="absmiddle"> Undo</button>
- </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.0.min.js"></script>
-
- <script src="../slick.core.js"></script>
- <script src="../slick.editors.js"></script>
- <script src="../slick.grid.js"></script>
-
- <script>
- 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};
- }
-
- var grid;
- var data = [];
-
- var columns = [
- {id:"title", name:"Title", field:"title", width:120, cssClass:"cell-title", editor:TextCellEditor, validator:requiredFieldValidator},
- {id:"desc", name:"Description", field:"description", width:100, editor:LongTextCellEditor},
- {id:"duration", name:"Duration", field:"duration", editor:TextCellEditor},
- {id:"%", name:"% Complete", field:"percentComplete", width:80, resizable:false, formatter:GraphicalPercentCompleteCellFormatter, editor:PercentCompleteCellEditor},
- {id:"start", name:"Start", field:"start", minWidth:60, editor:DateCellEditor},
- {id:"finish", name:"Finish", field:"finish", minWidth:60, editor:DateCellEditor},
- {id:"effort-driven", name:"Effort Driven", width:80, minWidth:20, maxWidth:80, cssClass:"cell-effort-driven", field:"effortDriven", formatter:BoolCellFormatter, editor:YesNoCheckboxCellEditor}
- ];
-
- var options = {
- editable: true,
- enableAddRow: false,
- enableCellNavigation: true,
- asyncEditorLoading: false,
- autoEdit: false,
- editCommandHandler: queueAndExecuteCommand
- };
-
- var commandQueue = [];
-
- function queueAndExecuteCommand(item,column,editCommand) {
- commandQueue.push(editCommand);
- editCommand.execute();
- }
-
- function undo() {
- var command = commandQueue.pop();
- if (command && Slick.GlobalEditorLock.cancelCurrentEdit()) {
- command.undo();
- grid.gotoCell(command.row,command.cell,false);
- }
- }
-
- $(function()
- {
- for (var i=0; i<500; i++) {
- var d = (data[i] = {});
-
- d["title"] = "Task " + i;
- d["description"] = "This is a sample task description.\n It can be multiline";
- 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);
- }
-
- grid = new Slick.Grid("#myGrid", data, columns, options);
- })
- </script>
- </body>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>SlickGrid example 3: Editing</title>
+ <link rel="stylesheet" href="../slick.grid.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" />
+ <style>
+ .cell-title {
+ font-weight: bold;
+ }
+
+ .cell-effort-driven {
+ text-align: center;
+ }
+ </style>
+</head>
+<body>
+<div style="position:relative">
+ <div style="width:600px;">
+ <div id="myGrid" style="width:100%;height:500px;"></div>
+ </div>
+
+ <div class="options-panel">
+ <h2>Demonstrates:</h2>
+ <ul>
+ <li>Using "editCommandHandler" option to intercept edit commands and implement undo support</li>
+ </ul>
+
+ <h2>Controls:</h2>
+ <button onclick="undo()"><img src="../images/arrow_undo.png" align="absmiddle"> Undo</button>
+ </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.0.min.js"></script>
+
+<script src="../slick.core.js"></script>
+<script src="../slick.editors.js"></script>
+<script src="../slick.grid.js"></script>
+
+<script>
+ 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};
+ }
+ }
+
+ var grid;
+ var data = [];
+
+ var columns = [
+ {id:"title", name:"Title", field:"title", width:120, cssClass:"cell-title", editor:TextCellEditor, validator:requiredFieldValidator},
+ {id:"desc", name:"Description", field:"description", width:100, editor:LongTextCellEditor},
+ {id:"duration", name:"Duration", field:"duration", editor:TextCellEditor},
+ {id:"%", name:"% Complete", field:"percentComplete", width:80, resizable:false, formatter:GraphicalPercentCompleteCellFormatter, editor:PercentCompleteCellEditor},
+ {id:"start", name:"Start", field:"start", minWidth:60, editor:DateCellEditor},
+ {id:"finish", name:"Finish", field:"finish", minWidth:60, editor:DateCellEditor},
+ {id:"effort-driven", name:"Effort Driven", width:80, minWidth:20, maxWidth:80, cssClass:"cell-effort-driven", field:"effortDriven", formatter:BoolCellFormatter, editor:YesNoCheckboxCellEditor}
+ ];
+
+ var options = {
+ editable:true,
+ enableAddRow:false,
+ enableCellNavigation:true,
+ asyncEditorLoading:false,
+ autoEdit:false,
+ editCommandHandler:queueAndExecuteCommand
+ };
+
+ var commandQueue = [];
+
+ function queueAndExecuteCommand(item, column, editCommand) {
+ commandQueue.push(editCommand);
+ editCommand.execute();
+ }
+
+ function undo() {
+ var command = commandQueue.pop();
+ if (command && Slick.GlobalEditorLock.cancelCurrentEdit()) {
+ command.undo();
+ grid.gotoCell(command.row, command.cell, false);
+ }
+ }
+
+ $(function () {
+ for (var i = 0; i < 500; i++) {
+ var d = (data[i] = {});
+
+ d["title"] = "Task " + i;
+ d["description"] = "This is a sample task description.\n It can be multiline";
+ 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);
+ }
+
+ grid = new Slick.Grid("#myGrid", data, columns, options);
+ })
+</script>
+</body>
</html>
diff --git a/examples/example4-model.html b/examples/example4-model.html
index 0ff1fa3..d717fad 100644
--- a/examples/example4-model.html
+++ b/examples/example4-model.html
@@ -1,372 +1,383 @@
<!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" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../controls/slick.pager.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../controls/slick.columnpicker.css" type="text/css" media="screen" charset="utf-8" />
- <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;
+<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>
+ </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 &nbsp;
+ <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.0.min.js"></script>
+
+<script src="../slick.core.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 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:TextCellEditor, validator:requiredFieldValidator, sortable:true},
+ {id:"duration", name:"Duration", field:"duration", editor:TextCellEditor, sortable:true},
+ {id:"%", name:"% Complete", field:"percentComplete", width:80, resizable:false, formatter:GraphicalPercentCompleteCellFormatter, editor:PercentCompleteCellEditor, sortable:true},
+ {id:"start", name:"Start", field:"start", minWidth:60, editor:DateCellEditor, sortable:true},
+ {id:"finish", name:"Finish", field:"finish", minWidth:60, editor:DateCellEditor, sortable:true},
+ {id:"effort-driven", name:"Effort Driven", width:80, minWidth:20, maxWidth:80, cssClass:"cell-effort-driven", field:"effortDriven", formatter:BoolCellFormatter, editor:YesNoCheckboxCellEditor, 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() {
+ if ($(grid.getTopPanel()).is(":visible")) {
+ grid.hideTopPanel();
+ } else {
+ grid.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();
+ 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 = [];
+ 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;
+
+ 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;
}
-
- .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>
- </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 &nbsp; <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.0.min.js"></script>
-
- <script src="../slick.core.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 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:TextCellEditor, validator:requiredFieldValidator, sortable:true},
- {id:"duration", name:"Duration", field:"duration", editor:TextCellEditor, sortable:true},
- {id:"%", name:"% Complete", field:"percentComplete", width:80, resizable:false, formatter:GraphicalPercentCompleteCellFormatter, editor:PercentCompleteCellEditor, sortable:true},
- {id:"start", name:"Start", field:"start", minWidth:60, editor:DateCellEditor, sortable:true},
- {id:"finish", name:"Finish", field:"finish", minWidth:60, editor:DateCellEditor, sortable:true},
- {id:"effort-driven", name:"Effort Driven", width:80, minWidth:20, maxWidth:80, cssClass:"cell-effort-driven", field:"effortDriven", formatter:BoolCellFormatter, editor:YesNoCheckboxCellEditor, 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() {
- if ($(grid.getTopPanel()).is(":visible"))
- grid.hideTopPanel();
- else
- grid.showTopPanel();
+ };
+
+ // 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();
+
+ 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-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();
- 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 = [];
- 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;
-
- 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();
-
- 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) {
- var isLastPage = pagingInfo.pageSize*(pagingInfo.pageNum+1)-1 >= pagingInfo.totalRows;
- 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 = [];
- selectedRowIds = [];
-
- for (var i=0; i<10 && i<dataView.getLength(); i++) {
- rows.push(i);
- selectedRowIds.push(dataView.getItem(i).id);
- }
-
- 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();
-
- $("#gridContainer").resizable();
- })
-
- </script>
-
- </body>
+ }
+
+ grid.setSelectedRows(selRows);
+ }
+ });
+
+ dataView.onPagingInfoChanged.subscribe(function (e, pagingInfo) {
+ var isLastPage = pagingInfo.pageSize * (pagingInfo.pageNum + 1) - 1 >= pagingInfo.totalRows;
+ 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 = [];
+ selectedRowIds = [];
+
+ for (var i = 0; i < 10 && i < dataView.getLength(); i++) {
+ rows.push(i);
+ selectedRowIds.push(dataView.getItem(i).id);
+ }
+
+ 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();
+
+ $("#gridContainer").resizable();
+})
+</script>
+</body>
</html>
diff --git a/examples/example5-collapsing.html b/examples/example5-collapsing.html
index a874dd8..40a7223 100644
--- a/examples/example5-collapsing.html
+++ b/examples/example5-collapsing.html
@@ -1,262 +1,275 @@
<!DOCTYPE HTML>
<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <title>SlickGrid example 5: Collapsing</title>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- <style>
- .cell-title {
- font-weight: bold;
- }
-
- .cell-effort-driven {
- text-align: center;
- }
-
- .toggle {
- height: 9px;
- width: 9px;
- display: inline-block;
- }
-
- .toggle.expand {
- background: url(../images/expand.gif) no-repeat center center;
- }
-
- .toggle.collapse {
- background: url(../images/collapse.gif) no-repeat center center;
- }
-
- </style>
- </head>
- <body>
- <table width="100%">
- <tr>
- <td valign="top" width="50%">
- <div style="border:1px solid gray;background:wheat;padding:6px;">
- <label>Show tasks with % at least: </label>
- <div style="padding:4px;">
- <div style="width:100px;" id="pcSlider"></div>
- </div>
- <br/>
- <label>And title including:</label>
- <input type=text id="txtSearch">
- </div>
- <br/>
- <div id="myGrid" style="width:600px;height:500px;"></div>
- </td>
- <td valign="top">
- <h2>Demonstrates:</h2>
- <ul>
- <li>implementing expand/collapse as a filter for DataView</li>
- </ul>
- </td>
- </tr>
- </table>
-
- <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.0.min.js"></script>
-
- <script src="../slick.core.js"></script>
- <script src="../slick.editors.js"></script>
- <script src="../slick.grid.js"></script>
- <script src="../slick.dataview.js"></script>
-
- <script>
- 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};
- }
-
-
- var TaskNameFormatter = function(row, cell, value, columnDef, dataContext) {
- var spacer = "<span style='display:inline-block;height:1px;width:" + (15 * dataContext["indent"]) + "px'></span>";
- var idx = dataView.getIdxById(dataContext.id);
- if (data[idx+1] && data[idx+1].indent > data[idx].indent) {
- if (dataContext._collapsed)
- return spacer + " <span class='toggle expand'></span>&nbsp;" + value;
- else
- return spacer + " <span class='toggle collapse'></span>&nbsp;" + value;
- }
- else
- return spacer + " <span class='toggle'></span>&nbsp;" + value;
- };
-
- var dataView;
- var grid;
-
- var data = [];
-
- var columns = [
- {id:"title", name:"Title", field:"title", width:220, cssClass:"cell-title", formatter:TaskNameFormatter, editor:TextCellEditor, validator:requiredFieldValidator},
- {id:"duration", name:"Duration", field:"duration", editor:TextCellEditor},
- {id:"%", name:"% Complete", field:"percentComplete", width:80, resizable:false, formatter:GraphicalPercentCompleteCellFormatter, editor:PercentCompleteCellEditor},
- {id:"start", name:"Start", field:"start", minWidth:60, editor:DateCellEditor},
- {id:"finish", name:"Finish", field:"finish", minWidth:60, editor:DateCellEditor},
- {id:"effort-driven", name:"Effort Driven", width:80, minWidth:20, maxWidth:80, cssClass:"cell-effort-driven", field:"effortDriven", formatter:BoolCellFormatter, editor:YesNoCheckboxCellEditor, cannotTriggerInsert:true}
- ];
-
- var options = {
- editable: true,
- enableAddRow: true,
- enableCellNavigation: true,
- asyncEditorLoading: false
- };
-
-
- var percentCompleteThreshold = 0;
- var searchString = "";
-
- function myFilter(item) {
- if (item["percentComplete"] < percentCompleteThreshold)
- return false;
-
- if (searchString != "" && item["title"].indexOf(searchString) == -1)
- return false;
-
- var idx = dataView.getIdxById(item.id);
-
- if (item.parent != null) {
- var parent = data[item.parent];
-
- while (parent) {
- if (parent._collapsed || (parent["percentComplete"] < percentCompleteThreshold) || (searchString != "" && parent["title"].indexOf(searchString) == -1) )
- return false;
-
- parent = data[parent.parent];
- }
- }
-
- return true;
- }
-
- function percentCompleteSort(a,b) {
- return a["percentComplete"] - b["percentComplete"];
- }
-
- $(function()
- {
- var indent = 0;
- var parents = [];
-
- // prepare the data
- for (var i=0; i<1000; i++) {
- var d = (data[i] = {});
- var parent = null;
-
- if (Math.random() > 0.8) {
- indent++;
- parent = i - 1;
- parents.push(parent);
- }
- else if (Math.random() < 0.3 && indent > 0) {
- indent--;
- parent = parents.pop();
- }
- else if (parents.length > 0)
- parent = parents[parents.length-1];
-
- if (indent == 0)
- parent = null;
-
- d["id"] = "id_" + i;
- d["indent"] = indent;
- d["parent"] = parent;
- 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);
- }
-
-
- // initialize the model
- dataView = new Slick.Data.DataView();
- dataView.beginUpdate();
- dataView.setItems(data);
- dataView.setFilter(myFilter);
- dataView.endUpdate();
-
-
- // initialize the grid
- grid = new Slick.Grid("#myGrid", dataView, columns, options);
-
- grid.onCellChange.subscribe(function(e,args) {
- dataView.updateItem(args.item.id,args.item);
- });
-
- grid.onAddNewRow.subscribe(function(e,args) {
- var item = {"id": "new_" + (Math.round(Math.random()*10000)), "indent":0, "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.onClick.subscribe(function(e,args) {
- if ($(e.target).hasClass("toggle")) {
- var item = dataView.getItem(args.row);
- if (item) {
- if (!item._collapsed)
- item._collapsed = true;
- else
- item._collapsed = false;
-
- dataView.updateItem(item.id, item);
- }
- e.stopImmediatePropagation();
- }
- });
-
-
- // 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();
- });
-
-
- var h_runfilters = null;
-
- // wire up the slider to apply the filter to the model
- $("#pcSlider").slider({
- "range": "min",
- "slide": function(event,ui) {
- Slick.GlobalEditorLock.cancelCurrentEdit();
-
- if (percentCompleteThreshold != ui.value)
- {
- window.clearTimeout(h_runfilters);
- h_runfilters = window.setTimeout(dataView.refresh, 10);
- percentCompleteThreshold = ui.value;
- }
- }
- });
-
-
- // wire up the search textbox to apply the filter to the model
- $("#txtSearch").keyup(function(e) {
- Slick.GlobalEditorLock.cancelCurrentEdit();
-
- // clear on Esc
- if (e.which == 27)
- this.value = "";
-
- searchString = this.value;
- dataView.refresh();
- })
- })
- </script>
- </body>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>SlickGrid example 5: Collapsing</title>
+ <link rel="stylesheet" href="../slick.grid.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" />
+ <style>
+ .cell-title {
+ font-weight: bold;
+ }
+
+ .cell-effort-driven {
+ text-align: center;
+ }
+
+ .toggle {
+ height: 9px;
+ width: 9px;
+ display: inline-block;
+ }
+
+ .toggle.expand {
+ background: url(../images/expand.gif) no-repeat center center;
+ }
+
+ .toggle.collapse {
+ background: url(../images/collapse.gif) no-repeat center center;
+ }
+
+ </style>
+</head>
+<body>
+<table width="100%">
+ <tr>
+ <td valign="top" width="50%">
+ <div style="border:1px solid gray;background:wheat;padding:6px;">
+ <label>Show tasks with % at least: </label>
+
+ <div style="padding:4px;">
+ <div style="width:100px;" id="pcSlider"></div>
+ </div>
+ <br/>
+ <label>And title including:</label>
+ <input type=text id="txtSearch">
+ </div>
+ <br/>
+
+ <div id="myGrid" style="width:600px;height:500px;"></div>
+ </td>
+ <td valign="top">
+ <h2>Demonstrates:</h2>
+ <ul>
+ <li>implementing expand/collapse as a filter for DataView</li>
+ </ul>
+ </td>
+ </tr>
+</table>
+
+<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.0.min.js"></script>
+
+<script src="../slick.core.js"></script>
+<script src="../slick.editors.js"></script>
+<script src="../slick.grid.js"></script>
+<script src="../slick.dataview.js"></script>
+
+<script>
+ 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};
+ }
+ }
+
+
+ var TaskNameFormatter = function (row, cell, value, columnDef, dataContext) {
+ var spacer = "<span style='display:inline-block;height:1px;width:" + (15 * dataContext["indent"]) + "px'></span>";
+ var idx = dataView.getIdxById(dataContext.id);
+ if (data[idx + 1] && data[idx + 1].indent > data[idx].indent) {
+ if (dataContext._collapsed) {
+ return spacer + " <span class='toggle expand'></span>&nbsp;" + value;
+ }
+ else {
+ return spacer + " <span class='toggle collapse'></span>&nbsp;" + value;
+ }
+ }
+ else {
+ return spacer + " <span class='toggle'></span>&nbsp;" + value;
+ }
+ };
+
+ var dataView;
+ var grid;
+
+ var data = [];
+
+ var columns = [
+ {id:"title", name:"Title", field:"title", width:220, cssClass:"cell-title", formatter:TaskNameFormatter, editor:TextCellEditor, validator:requiredFieldValidator},
+ {id:"duration", name:"Duration", field:"duration", editor:TextCellEditor},
+ {id:"%", name:"% Complete", field:"percentComplete", width:80, resizable:false, formatter:GraphicalPercentCompleteCellFormatter, editor:PercentCompleteCellEditor},
+ {id:"start", name:"Start", field:"start", minWidth:60, editor:DateCellEditor},
+ {id:"finish", name:"Finish", field:"finish", minWidth:60, editor:DateCellEditor},
+ {id:"effort-driven", name:"Effort Driven", width:80, minWidth:20, maxWidth:80, cssClass:"cell-effort-driven", field:"effortDriven", formatter:BoolCellFormatter, editor:YesNoCheckboxCellEditor, cannotTriggerInsert:true}
+ ];
+
+ var options = {
+ editable:true,
+ enableAddRow:true,
+ enableCellNavigation:true,
+ asyncEditorLoading:false
+ };
+
+
+ var percentCompleteThreshold = 0;
+ var searchString = "";
+
+ function myFilter(item) {
+ if (item["percentComplete"] < percentCompleteThreshold) {
+ return false;
+ }
+
+ if (searchString != "" && item["title"].indexOf(searchString) == -1) {
+ return false;
+ }
+
+ var idx = dataView.getIdxById(item.id);
+
+ if (item.parent != null) {
+ var parent = data[item.parent];
+
+ while (parent) {
+ if (parent._collapsed || (parent["percentComplete"] < percentCompleteThreshold) || (searchString != "" && parent["title"].indexOf(searchString) == -1)) {
+ return false;
+ }
+
+ parent = data[parent.parent];
+ }
+ }
+
+ return true;
+ }
+
+ function percentCompleteSort(a, b) {
+ return a["percentComplete"] - b["percentComplete"];
+ }
+
+ $(function () {
+ var indent = 0;
+ var parents = [];
+
+ // prepare the data
+ for (var i = 0; i < 1000; i++) {
+ var d = (data[i] = {});
+ var parent = null;
+
+ if (Math.random() > 0.8) {
+ indent++;
+ parent = i - 1;
+ parents.push(parent);
+ }
+ else if (Math.random() < 0.3 && indent > 0) {
+ indent--;
+ parent = parents.pop();
+ }
+ else if (parents.length > 0) {
+ parent = parents[parents.length - 1];
+ }
+
+ if (indent == 0) {
+ parent = null;
+ }
+
+ d["id"] = "id_" + i;
+ d["indent"] = indent;
+ d["parent"] = parent;
+ 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);
+ }
+
+
+ // initialize the model
+ dataView = new Slick.Data.DataView();
+ dataView.beginUpdate();
+ dataView.setItems(data);
+ dataView.setFilter(myFilter);
+ dataView.endUpdate();
+
+
+ // initialize the grid
+ grid = new Slick.Grid("#myGrid", dataView, columns, options);
+
+ grid.onCellChange.subscribe(function (e, args) {
+ dataView.updateItem(args.item.id, args.item);
+ });
+
+ grid.onAddNewRow.subscribe(function (e, args) {
+ var item = {"id":"new_" + (Math.round(Math.random() * 10000)), "indent":0, "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.onClick.subscribe(function (e, args) {
+ if ($(e.target).hasClass("toggle")) {
+ var item = dataView.getItem(args.row);
+ if (item) {
+ if (!item._collapsed) {
+ item._collapsed = true;
+ }
+ else {
+ item._collapsed = false;
+ }
+
+ dataView.updateItem(item.id, item);
+ }
+ e.stopImmediatePropagation();
+ }
+ });
+
+
+ // 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();
+ });
+
+
+ var h_runfilters = null;
+
+ // wire up the slider to apply the filter to the model
+ $("#pcSlider").slider({
+ "range":"min",
+ "slide":function (event, ui) {
+ Slick.GlobalEditorLock.cancelCurrentEdit();
+
+ if (percentCompleteThreshold != ui.value) {
+ window.clearTimeout(h_runfilters);
+ h_runfilters = window.setTimeout(dataView.refresh, 10);
+ percentCompleteThreshold = ui.value;
+ }
+ }
+ });
+
+
+ // wire up the search textbox to apply the filter to the model
+ $("#txtSearch").keyup(function (e) {
+ Slick.GlobalEditorLock.cancelCurrentEdit();
+
+ // clear on Esc
+ if (e.which == 27) {
+ this.value = "";
+ }
+
+ searchString = this.value;
+ dataView.refresh();
+ })
+ })
+</script>
+</body>
</html>
diff --git a/examples/example6-ajax-loading.html b/examples/example6-ajax-loading.html
index a2c9624..978ca7e 100644
--- a/examples/example6-ajax-loading.html
+++ b/examples/example6-ajax-loading.html
@@ -1,156 +1,154 @@
<!DOCTYPE HTML>
<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <title>SlickGrid example 6: AJAX Load</title>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- <style>
- .cell-story {
- white-space: normal!important;
- line-height: 19px!important;
- }
-
- .loading-indicator {
- display: inline-block;
- padding: 12px;
- background: white;
- -opacity: 0.5;
- color: black;
- font-weight: bold;
- z-index: 9999;
- border: 1px solid red;
- -moz-border-radius: 10px;
- -webkit-border-radius: 10px;
- -moz-box-shadow: 0 0 5px red;
- -webkit-box-shadow: 0px 0px 5px red;
- -text-shadow: 1px 1px 1px white;
- }
-
- .loading-indicator label {
- padding-left: 20px;
- background: url('../images/ajax-loader-small.gif') no-repeat center left;
- }
- </style>
- </head>
- <body>
- <div style="width:700px;float:left;">
- <div class="grid-header" style="width:100%">
- <label>Digg stories</label>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>SlickGrid example 6: AJAX Load</title>
+ <link rel="stylesheet" href="../slick.grid.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" />
+ <style>
+ .cell-story {
+ white-space: normal !important;
+ line-height: 19px !important;
+ }
+
+ .loading-indicator {
+ display: inline-block;
+ padding: 12px;
+ background: white;
+ -opacity: 0.5;
+ color: black;
+ font-weight: bold;
+ z-index: 9999;
+ border: 1px solid red;
+ -moz-border-radius: 10px;
+ -webkit-border-radius: 10px;
+ -moz-box-shadow: 0 0 5px red;
+ -webkit-box-shadow: 0px 0px 5px red;
+ -text-shadow: 1px 1px 1px white;
+ }
+
+ .loading-indicator label {
+ padding-left: 20px;
+ background: url('../images/ajax-loader-small.gif') no-repeat center left;
+ }
+ </style>
+</head>
+<body>
+<div style="width:700px;float:left;">
+ <div class="grid-header" style="width:100%">
+ <label>Digg stories</label>
<span style="float:right;display:inline-block;">
Search:
<input type="text" id="txtSearch" value="apple">
</span>
- </div>
- <div id="myGrid" style="width:100%;height:600px;"></div>
- <div id="pager" style="width:100%;height:20px;"></div>
- </div>
- <div style="margin-left:750px;margin-top:40px;;">
- <h2>Demonstrates:</h2>
- <ul>
- <li>loading data through AJAX</li>
- <li>custom row height</li>
- </ul>
-
- <h2>WARNING:</h2>
- <ul>
- <li>Digg API uses request rate limiting. You may occasionally get an error if you do a frequent scrolling/resorting/searching.</li>
- </ul>
- </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.0.min.js"></script>
- <script src="../lib/jquery.jsonp-1.1.0.min.js"></script>
-
- <script src="../slick.core.js"></script>
- <script src="../slick.remotemodel.js"></script>
- <script src="../slick.grid.js"></script>
-
- <script>
- var grid;
- var data = [];
- var loader = new Slick.Data.RemoteModel();
-
- var storyTitleFormatter = function(row, cell, value, columnDef, dataContext) {
- return "<b><a href='" + dataContext["link"] + "' target=_blank>" + dataContext["title"] + "</a></b><br/>" + dataContext["description"];
- };
-
-
- var columns = [
- {id:"num", name:"#", field:"index", width:40},
- {id:"story", name:"Story", width:580, formatter:storyTitleFormatter, cssClass:"cell-story"},
- {id:"diggs", name:"Diggs", field:"diggs", width:60, sortable:true}
- ];
-
- var options = {
- rowHeight: 64,
- editable: false,
- enableAddRow: false,
- enableCellNavigation: false
- };
-
- var loadingIndicator = null;
-
-
-
- $(function()
- {
- grid = new Slick.Grid("#myGrid", loader.data, columns, options);
-
- grid.onViewportChanged.subscribe(function(e,args) {
- var vp = grid.getViewport();
- loader.ensureData(vp.top, vp.bottom);
- });
-
- grid.onSort.subscribe(function(e,args) {
- loader.setSort(args.sortCol.field, args.sortAsc ? 1 : -1);
- var vp = grid.getViewport();
- loader.ensureData(vp.top, vp.bottom);
- });
-
- loader.onDataLoading.subscribe(function() {
- if (!loadingIndicator)
- {
- loadingIndicator = $("<span class='loading-indicator'><label>Buffering...</label></span>").appendTo(document.body);
- var $g = $("#myGrid");
-
- loadingIndicator
- .css("position", "absolute")
- .css("top", $g.position().top + $g.height()/2 - loadingIndicator.height()/2)
- .css("left", $g.position().left + $g.width()/2 - loadingIndicator.width()/2)
- }
-
- loadingIndicator.show();
- });
-
- loader.onDataLoaded.subscribe(function(e,args) {
- for (var i = args.from; i <= args.to; i++) {
- grid.invalidateRow(i);
- }
-
- grid.updateRowCount();
- grid.render();
-
- loadingIndicator.fadeOut();
- });
-
- $("#txtSearch").keyup(function(e) {
- if (e.which == 13) {
- loader.setSearch($(this).val());
- var vp = grid.getViewport();
- loader.ensureData(vp.top, vp.bottom);
- }
- });
-
-
-
- // load the first page
- grid.onViewportChanged.notify();
- })
- </script>
- </body>
+ </div>
+ <div id="myGrid" style="width:100%;height:600px;"></div>
+ <div id="pager" style="width:100%;height:20px;"></div>
+</div>
+<div style="margin-left:750px;margin-top:40px;;">
+ <h2>Demonstrates:</h2>
+ <ul>
+ <li>loading data through AJAX</li>
+ <li>custom row height</li>
+ </ul>
+
+ <h2>WARNING:</h2>
+ <ul>
+ <li>Digg API uses request rate limiting. You may occasionally get an error if you do a frequent
+ scrolling/resorting/searching.
+ </li>
+ </ul>
+</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.0.min.js"></script>
+<script src="../lib/jquery.jsonp-1.1.0.min.js"></script>
+
+<script src="../slick.core.js"></script>
+<script src="../slick.remotemodel.js"></script>
+<script src="../slick.grid.js"></script>
+
+<script>
+ var grid;
+ var data = [];
+ var loader = new Slick.Data.RemoteModel();
+
+ var storyTitleFormatter = function (row, cell, value, columnDef, dataContext) {
+ return "<b><a href='" + dataContext["link"] + "' target=_blank>" + dataContext["title"] + "</a></b><br/>" + dataContext["description"];
+ };
+
+
+ var columns = [
+ {id:"num", name:"#", field:"index", width:40},
+ {id:"story", name:"Story", width:580, formatter:storyTitleFormatter, cssClass:"cell-story"},
+ {id:"diggs", name:"Diggs", field:"diggs", width:60, sortable:true}
+ ];
+
+ var options = {
+ rowHeight:64,
+ editable:false,
+ enableAddRow:false,
+ enableCellNavigation:false
+ };
+
+ var loadingIndicator = null;
+
+
+ $(function () {
+ grid = new Slick.Grid("#myGrid", loader.data, columns, options);
+
+ grid.onViewportChanged.subscribe(function (e, args) {
+ var vp = grid.getViewport();
+ loader.ensureData(vp.top, vp.bottom);
+ });
+
+ grid.onSort.subscribe(function (e, args) {
+ loader.setSort(args.sortCol.field, args.sortAsc ? 1 : -1);
+ var vp = grid.getViewport();
+ loader.ensureData(vp.top, vp.bottom);
+ });
+
+ loader.onDataLoading.subscribe(function () {
+ if (!loadingIndicator) {
+ loadingIndicator = $("<span class='loading-indicator'><label>Buffering...</label></span>").appendTo(document.body);
+ var $g = $("#myGrid");
+
+ loadingIndicator
+ .css("position", "absolute")
+ .css("top", $g.position().top + $g.height() / 2 - loadingIndicator.height() / 2)
+ .css("left", $g.position().left + $g.width() / 2 - loadingIndicator.width() / 2)
+ }
+
+ loadingIndicator.show();
+ });
+
+ loader.onDataLoaded.subscribe(function (e, args) {
+ for (var i = args.from; i <= args.to; i++) {
+ grid.invalidateRow(i);
+ }
+
+ grid.updateRowCount();
+ grid.render();
+
+ loadingIndicator.fadeOut();
+ });
+
+ $("#txtSearch").keyup(function (e) {
+ if (e.which == 13) {
+ loader.setSearch($(this).val());
+ var vp = grid.getViewport();
+ loader.ensureData(vp.top, vp.bottom);
+ }
+ });
+
+
+ // load the first page
+ grid.onViewportChanged.notify();
+ })
+</script>
+</body>
</html>
diff --git a/examples/example7-events.html b/examples/example7-events.html
index 4d0b44e..33ccc83 100644
--- a/examples/example7-events.html
+++ b/examples/example7-events.html
@@ -3,9 +3,9 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>SlickGrid example 7: Events</title>
- <link rel="stylesheet" href="../slick.grid.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="../slick.grid.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"/>
<style>
.cell-title {
font-weight: bold;
@@ -97,10 +97,10 @@
e.preventDefault();
var cell = grid.getCellFromEvent(e);
$("#contextMenu")
- .data("row", cell.row)
- .css("top", e.pageY)
- .css("left", e.pageX)
- .show();
+ .data("row", cell.row)
+ .css("top", e.pageY)
+ .css("left", e.pageX)
+ .show();
$("body").one("click", function () {
$("#contextMenu").hide();
@@ -119,8 +119,9 @@
});
$("#contextMenu").click(function (e) {
- if (!$(e.target).is("li"))
+ if (!$(e.target).is("li")) {
return;
+ }
var row = $(this).data("row");
data[row].priority = $(e.target).attr("data");
diff --git a/examples/example8-alternative-display.html b/examples/example8-alternative-display.html
index 8fe622e..acf0f6b 100644
--- a/examples/example8-alternative-display.html
+++ b/examples/example8-alternative-display.html
@@ -1,174 +1,176 @@
<!DOCTYPE HTML>
<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <title>SlickGrid example 8: Alternative display</title>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- <style>
- .slick-cell {
- background: white!important;
- border-color: transparent!important;
- line-height: 19px!important;
- }
-
- /* alternating offsets */
- .slick-row .cell-inner {
- margin-right: 60px;
- }
-
- .slick-row[row$="1"] .cell-inner, .slick-row[row$="3"] .cell-inner, .slick-row[row$="5"] .cell-inner,
- .slick-row[row$="7"] .cell-inner, .slick-row[row$="9"] .cell-inner {
- margin-left: 60px;
- margin-right: 0;
- }
-
- .contact-card-cell {
- border-color: transparent!important;
- }
-
- .cell-inner {
- height: 80px;
- margin: 10px;
- padding: 10px;
- background: #fafafa;
- border: 1px solid gray;
- -moz-border-radius: 10px;
- -webkit-border-radius: 10px;
- -moz-box-shadow: 1px 1px 5px silver;
- -webkit-box-shadow: 1px 1px 5px silver;
- -webkit-transition: all 0.5s;
- }
-
- .cell-inner:hover {
- background: #f0f0f0;
- }
-
- .cell-left {
- width: 40px;
- height: 100%;
- float: left;
- border-right: 1px dotted gray;
- background: url("../images/user_identity.gif") no-repeat top center;
- }
-
- .cell-main {
- margin-left: 50px;
- }
- </style>
- </head>
- <body>
- <table width="100%">
- <tr>
- <td valign="top" width="50%">
- <div id="myGrid" style="width:600px;height:500px;"></div>
- </td>
- <td valign="top">
- <h2>Demonstrates:</h2>
-
- <ul>
- <li>Template-based rendering using John Resig's <a href="http://ejohn.org/blog/javascript-micro-templating/" target=_blank>micro-templates</a> while still using SlickGrid's virtual rendering technology.</li>
- </ul>
- </td>
- </tr>
- </table>
-
- <!-- cell template -->
- <script type="text/html" id="cell_template">
- <div class="cell-inner">
- <div class="cell-left"></div>
- <div class="cell-main">
- <b><%=name%></b><br/>
- <%=title%><br/>
- <%=email%><br/>
- <%=phone%>
- </div>
- </div>
- </script>
-
- <script src="../lib/firebugx.js"></script>
-
- <script src="../lib/jquery-1.7.min.js"></script>
- <script src="../lib/jquery.event.drag-2.0.min.js"></script>
-
- <script src="../slick.core.js"></script>
- <script src="../slick.grid.js"></script>
-
- <script>
- // Simple JavaScript Templating
- // John Resig - http://ejohn.org/ - MIT Licensed
- (function(){
- var cache = {};
-
- this.tmpl = function tmpl(str, data){
- // Figure out if we're getting a template, or if we need to
- // load the template - and be sure to cache the result.
- var fn = !/\W/.test(str) ?
- cache[str] = cache[str] ||
- tmpl(document.getElementById(str).innerHTML) :
-
- // Generate a reusable function that will serve as a template
- // generator (and which will be cached).
- new Function("obj",
- "var p=[],print=function(){p.push.apply(p,arguments);};" +
-
- // Introduce the data as local variables using with(){}
- "with(obj){p.push('" +
-
- // Convert the template into pure JavaScript
- str
- .replace(/[\r\t\n]/g, " ")
- .split("<%").join("\t")
- .replace(/((^|%>)[^\t]*)'/g, "$1\r")
- .replace(/\t=(.*?)%>/g, "',$1,'")
- .split("\t").join("');")
- .split("%>").join("p.push('")
- .split("\r").join("\\'")
- + "');}return p.join('');");
-
- // Provide some basic currying to the user
- return data ? fn( data ) : fn;
- };
- })();
-
-
- var grid;
- var data = [];
-
- var columns = [
- {id:"contact-card", name:"Contacts", formatter:renderCell, width:500, cssClass:"contact-card-cell"}
- ];
-
- var options = {
- rowHeight: 140,
- editable: false,
- enableAddRow: false,
- enableCellNavigation: false,
- enableColumnReorder: false
- };
-
- var compiled_template = tmpl("cell_template");
-
- function renderCell(row, cell, value, columnDef, dataContext) {
- return compiled_template(dataContext);
- }
-
- $(function()
- {
- for (var i=0; i<100; i++) {
- var d = (data[i] = {});
-
- d["name"] = "User " + i;
- d["email"] = "test.user@nospam.org";
- d["title"] = "Regional sales manager";
- d["phone"] = "206-000-0000";
- }
-
-
- grid = new Slick.Grid("#myGrid", data, columns, options);
- })
-
- </script>
- </body>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>SlickGrid example 8: Alternative display</title>
+ <link rel="stylesheet" href="../slick.grid.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" />
+ <style>
+ .slick-cell {
+ background: white !important;
+ border-color: transparent !important;
+ line-height: 19px !important;
+ }
+
+ /* alternating offsets */
+ .slick-row .cell-inner {
+ margin-right: 60px;
+ }
+
+ .slick-row[row$="1"] .cell-inner, .slick-row[row$="3"] .cell-inner, .slick-row[row$="5"] .cell-inner,
+ .slick-row[row$="7"] .cell-inner, .slick-row[row$="9"] .cell-inner {
+ margin-left: 60px;
+ margin-right: 0;
+ }
+
+ .contact-card-cell {
+ border-color: transparent !important;
+ }
+
+ .cell-inner {
+ height: 80px;
+ margin: 10px;
+ padding: 10px;
+ background: #fafafa;
+ border: 1px solid gray;
+ -moz-border-radius: 10px;
+ -webkit-border-radius: 10px;
+ -moz-box-shadow: 1px 1px 5px silver;
+ -webkit-box-shadow: 1px 1px 5px silver;
+ -webkit-transition: all 0.5s;
+ }
+
+ .cell-inner:hover {
+ background: #f0f0f0;
+ }
+
+ .cell-left {
+ width: 40px;
+ height: 100%;
+ float: left;
+ border-right: 1px dotted gray;
+ background: url("../images/user_identity.gif") no-repeat top center;
+ }
+
+ .cell-main {
+ margin-left: 50px;
+ }
+ </style>
+</head>
+<body>
+<table width="100%">
+ <tr>
+ <td valign="top" width="50%">
+ <div id="myGrid" style="width:600px;height:500px;"></div>
+ </td>
+ <td valign="top">
+ <h2>Demonstrates:</h2>
+
+ <ul>
+ <li>Template-based rendering using John Resig's <a href="http://ejohn.org/blog/javascript-micro-templating/"
+ target=_blank>micro-templates</a> while still using
+ SlickGrid's virtual rendering technology.
+ </li>
+ </ul>
+ </td>
+ </tr>
+</table>
+
+<!-- cell template -->
+<script type="text/html" id="cell_template">
+ <div class="cell-inner">
+ <div class="cell-left"></div>
+ <div class="cell-main">
+ <b><%=name%></b><br/>
+ <%=title%><br/>
+ <%=email%><br/>
+ <%=phone%>
+ </div>
+ </div>
+</script>
+
+<script src="../lib/firebugx.js"></script>
+
+<script src="../lib/jquery-1.7.min.js"></script>
+<script src="../lib/jquery.event.drag-2.0.min.js"></script>
+
+<script src="../slick.core.js"></script>
+<script src="../slick.grid.js"></script>
+
+<script>
+ // Simple JavaScript Templating
+ // John Resig - http://ejohn.org/ - MIT Licensed
+ (function () {
+ var cache = {};
+
+ this.tmpl = function tmpl(str, data) {
+ // Figure out if we're getting a template, or if we need to
+ // load the template - and be sure to cache the result.
+ var fn = !/\W/.test(str) ?
+ cache[str] = cache[str] ||
+ tmpl(document.getElementById(str).innerHTML) :
+
+ // Generate a reusable function that will serve as a template
+ // generator (and which will be cached).
+ new Function("obj",
+ "var p=[],print=function(){p.push.apply(p,arguments);};" +
+
+ // Introduce the data as local variables using with(){}
+ "with(obj){p.push('" +
+
+ // Convert the template into pure JavaScript
+ str
+ .replace(/[\r\t\n]/g, " ")
+ .split("<%").join("\t")
+ .replace(/((^|%>)[^\t]*)'/g, "$1\r")
+ .replace(/\t=(.*?)%>/g, "',$1,'")
+ .split("\t").join("');")
+ .split("%>").join("p.push('")
+ .split("\r").join("\\'")
+ + "');}return p.join('');");
+
+ // Provide some basic currying to the user
+ return data ? fn(data) : fn;
+ };
+ })();
+
+
+ var grid;
+ var data = [];
+
+ var columns = [
+ {id:"contact-card", name:"Contacts", formatter:renderCell, width:500, cssClass:"contact-card-cell"}
+ ];
+
+ var options = {
+ rowHeight:140,
+ editable:false,
+ enableAddRow:false,
+ enableCellNavigation:false,
+ enableColumnReorder:false
+ };
+
+ var compiled_template = tmpl("cell_template");
+
+ function renderCell(row, cell, value, columnDef, dataContext) {
+ return compiled_template(dataContext);
+ }
+
+ $(function () {
+ for (var i = 0; i < 100; i++) {
+ var d = (data[i] = {});
+
+ d["name"] = "User " + i;
+ d["email"] = "test.user@nospam.org";
+ d["title"] = "Regional sales manager";
+ d["phone"] = "206-000-0000";
+ }
+
+
+ grid = new Slick.Grid("#myGrid", data, columns, options);
+ })
+
+</script>
+</body>
</html>
diff --git a/examples/example9-row-reordering.html b/examples/example9-row-reordering.html
index fa3920e..fbfd18a 100644
--- a/examples/example9-row-reordering.html
+++ b/examples/example9-row-reordering.html
@@ -1,305 +1,314 @@
<!DOCTYPE HTML>
<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <title>SlickGrid example 9: Row reordering</title>
- <link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.16.custom.css" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
- <style>
- .cell-title {
- zfont-weight: bold;
- }
- .cell-effort-driven {
- text-align: center;
- }
- .cell-reorder {
- cursor: move;
- background: url("../images/drag-handle.png") no-repeat center 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 */
- }
-
- .recycle-bin {
- width: 120px;
- border: 1px solid gray;
- background: beige;
- padding: 4px;
- font-size: 12pt;
- font-weight: bold;
- color: black;
- text-align: center;
- -moz-border-radius: 10px;
- }
-
- .red {
- background: red;
- }
-
- .bold {
- font-weight: bold;
- }
- </style>
- </head>
- <body>
- <div style="position:relative">
- <div style="width:600px;">
- <div class="grid-header" style="width:100%">
- <label>Santa's TODO list:</label>
- </div>
- <div id="myGrid" style="width:100%;height:500px;"></div>
- </div>
- <div class="options-panel">
- <b>Tips:</b>
- <hr/>
- <div style="padding:6px;">
- Click to select, Ctrl-click to toggle selection, Shift-click to select a range.<br/>
- Drag one or more rows by the handle to reorder.<br/>
- Drag one or more rows to the recycle bin to delete.
-
- <br/>
- <br/>
- <div id="dropzone" class="recycle-bin">
- Recycle Bin
- </div>
- </div>
- </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.0.min.js"></script>
- <script src="../lib/jquery.event.drop-2.0.min.js"></script>
-
- <script src="../slick.core.js"></script>
- <script src="../plugins/slick.cellrangeselector.js"></script>
- <script src="../plugins/slick.cellselectionmodel.js"></script>
- <script src="../plugins/slick.rowselectionmodel.js"></script>
- <script src="../plugins/slick.rowmovemanager.js"></script>
- <script src="../slick.editors.js"></script>
- <script src="../slick.grid.js"></script>
-
- <script>
- var grid;
- var data = [];
-
- var columns = [
- {
- id: "#",
- name: "",
- width: 40,
- behavior: "selectAndMove",
- selectable: false,
- resizable: false,
- cssClass: "cell-reorder dnd"
- },
- {
- id: "name",
- name: "Name",
- field: "name",
- width: 500,
- cssClass: "cell-title",
- editor: TextCellEditor,
- validator: requiredFieldValidator
- },
- {
- id: "complete",
- name: "Complete",
- width: 60,
- cssClass: "cell-effort-driven",
- field: "complete",
- cannotTriggerInsert: true,
- formatter: BoolCellFormatter,
- editor: YesNoCheckboxCellEditor
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>SlickGrid example 9: Row reordering</title>
+ <link rel="stylesheet" href="../slick.grid.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" />
+ <style>
+ .cell-title {
+ zfont-weight: bold;
+ }
+
+ .cell-effort-driven {
+ text-align: center;
+ }
+
+ .cell-reorder {
+ cursor: move;
+ background: url("../images/drag-handle.png") no-repeat center 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 */
+ }
+
+ .recycle-bin {
+ width: 120px;
+ border: 1px solid gray;
+ background: beige;
+ padding: 4px;
+ font-size: 12pt;
+ font-weight: bold;
+ color: black;
+ text-align: center;
+ -moz-border-radius: 10px;
+ }
+
+ .red {
+ background: red;
+ }
+
+ .bold {
+ font-weight: bold;
+ }
+ </style>
+</head>
+<body>
+<div style="position:relative">
+ <div style="width:600px;">
+ <div class="grid-header" style="width:100%">
+ <label>Santa's TODO list:</label>
+ </div>
+ <div id="myGrid" style="width:100%;height:500px;"></div>
+ </div>
+ <div class="options-panel">
+ <b>Tips:</b>
+ <hr/>
+ <div style="padding:6px;">
+ Click to select, Ctrl-click to toggle selection, Shift-click to select a range.<br/>
+ Drag one or more rows by the handle to reorder.<br/>
+ Drag one or more rows to the recycle bin to delete.
+
+ <br/>
+ <br/>
+
+ <div id="dropzone" class="recycle-bin">
+ Recycle Bin
+ </div>
+ </div>
+ </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.0.min.js"></script>
+<script src="../lib/jquery.event.drop-2.0.min.js"></script>
+
+<script src="../slick.core.js"></script>
+<script src="../plugins/slick.cellrangeselector.js"></script>
+<script src="../plugins/slick.cellselectionmodel.js"></script>
+<script src="../plugins/slick.rowselectionmodel.js"></script>
+<script src="../plugins/slick.rowmovemanager.js"></script>
+<script src="../slick.editors.js"></script>
+<script src="../slick.grid.js"></script>
+
+<script>
+var grid;
+var data = [];
+
+var columns = [
+ {
+ id:"#",
+ name:"",
+ width:40,
+ behavior:"selectAndMove",
+ selectable:false,
+ resizable:false,
+ cssClass:"cell-reorder dnd"
+ },
+ {
+ id:"name",
+ name:"Name",
+ field:"name",
+ width:500,
+ cssClass:"cell-title",
+ editor:TextCellEditor,
+ validator:requiredFieldValidator
+ },
+ {
+ id:"complete",
+ name:"Complete",
+ width:60,
+ cssClass:"cell-effort-driven",
+ field:"complete",
+ cannotTriggerInsert:true,
+ formatter:BoolCellFormatter,
+ editor:YesNoCheckboxCellEditor
+ }
+];
+
+var options = {
+ editable:true,
+ enableAddRow:true,
+ enableRowReordering:true,
+ enableCellNavigation:true,
+ forceFitColumns:true,
+ autoEdit:false
+};
+
+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 () {
+ data = [
+ { name:"Make a list", complete:true},
+ { name:"Check it twice", complete:false},
+ { name:"Find out who's naughty", complete:false},
+ { name:"Find out who's nice", complete:false}
+ ];
+
+ grid = new Slick.Grid("#myGrid", data, columns, options);
+
+ grid.setSelectionModel(new Slick.RowSelectionModel());
+
+ var moveRowsPlugin = new Slick.RowMoveManager();
+
+ moveRowsPlugin.onBeforeMoveRows.subscribe(function (e, data) {
+ for (var i = 0; i < data.rows.length; i++) {
+ // no point in moving before or after itself
+ if (data.rows[i] == data.insertBefore || data.rows[i] == data.insertBefore - 1) {
+ e.stopPropagation();
+ return false;
+ }
+ }
+
+ return true;
+ });
+
+ moveRowsPlugin.onMoveRows.subscribe(function (e, args) {
+ var extractedRows = [], left, right;
+ var rows = args.rows;
+ var insertBefore = args.insertBefore;
+ left = data.slice(0, insertBefore);
+ right = data.slice(insertBefore, data.length);
+
+ for (var i = 0; i < rows.length; i++) {
+ extractedRows.push(data[rows[i]]);
+ }
+
+ rows.sort().reverse();
+
+ for (var i = 0; i < rows.length; i++) {
+ var row = rows[i];
+ if (row < insertBefore) {
+ left.splice(row, 1);
+ }
+ else {
+ right.splice(row - insertBefore, 1);
+ }
+ }
+
+ data = left.concat(extractedRows.concat(right));
+
+ var selectedRows = [];
+ for (var i = 0; i < rows.length; i++)
+ selectedRows.push(left.length + i);
+
+ grid.resetActiveCell();
+ grid.setData(data);
+ grid.setSelectedRows(selectedRows);
+ grid.render();
+ });
+
+ grid.registerPlugin(moveRowsPlugin);
+
+ grid.onDragInit.subscribe(function (e, dd) {
+ // prevent the grid from cancelling drag'n'drop by default
+ e.stopImmediatePropagation();
+ });
+
+ grid.onDragStart.subscribe(function (e, dd) {
+ var cell = grid.getCellFromEvent(e);
+ if (!cell) {
+ return;
+ }
+
+ dd.row = cell.row;
+ if (!data[dd.row]) {
+ return;
+ }
+
+ if (Slick.GlobalEditorLock.isActive()) {
+ return;
+ }
+
+ e.stopImmediatePropagation();
+ dd.mode = "recycle";
+
+ var selectedRows = grid.getSelectedRows();
+
+ if (!selectedRows.length || $.inArray(dd.row, selectedRows) == -1) {
+ selectedRows = [dd.row];
+ grid.setSelectedRows(selectedRows);
+ }
+
+ dd.rows = selectedRows;
+ dd.count = selectedRows.length;
+
+ var proxy = $("<span></span>")
+ .css({
+ position:"absolute",
+ display:"inline-block",
+ padding:"4px 10px",
+ background:"#e0e0e0",
+ border:"1px solid gray",
+ "z-index":99999,
+ "-moz-border-radius":"8px",
+ "-moz-box-shadow":"2px 2px 6px silver"
+ })
+ .text("Drag to Recycle Bin to delete " + dd.count + " selected row(s)")
+ .appendTo("body");
+
+ dd.helper = proxy;
+
+ $(dd.available).css("background", "pink");
+
+ return proxy;
+ });
+
+ grid.onDrag.subscribe(function (e, dd) {
+ if (dd.mode != "recycle") {
+ return;
+ }
+ e.stopImmediatePropagation();
+ dd.helper.css({top:e.pageY + 5, left:e.pageX + 5});
+ });
+
+ grid.onDragEnd.subscribe(function (e, dd) {
+ if (dd.mode != "recycle") {
+ return;
+ }
+ e.stopImmediatePropagation();
+ dd.helper.remove();
+ $(dd.available).css("background", "beige");
+ });
+
+
+ $("#dropzone")
+ .bind("dropstart", function (e, dd) {
+ $(this).css("background", "yellow");
+ })
+ .bind("dropend", function (e, dd) {
+ $(dd.available).css("background", "pink");
+ })
+ .bind("drop", function (e, dd) {
+ var rowsToDelete = dd.rows.sort().reverse();
+ for (var i = 0; i < rowsToDelete.length; i++) {
+ data.splice(rowsToDelete[i], 1);
}
- ];
-
- var options = {
- editable: true,
- enableAddRow: true,
- enableRowReordering: true,
- enableCellNavigation: true,
- forceFitColumns: true,
- autoEdit: false
- };
-
- 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()
- {
- data = [
- { name: "Make a list", complete: true},
- { name: "Check it twice", complete: false},
- { name: "Find out who's naughty", complete: false},
- { name: "Find out who's nice", complete: false}
- ];
-
- grid = new Slick.Grid("#myGrid", data, columns, options);
-
- grid.setSelectionModel(new Slick.RowSelectionModel());
-
- var moveRowsPlugin = new Slick.RowMoveManager();
-
- moveRowsPlugin.onBeforeMoveRows.subscribe(function(e,data) {
- for (var i = 0; i < data.rows.length; i++) {
- // no point in moving before or after itself
- if (data.rows[i] == data.insertBefore || data.rows[i] == data.insertBefore - 1) {
- e.stopPropagation();
- return false;
- }
- }
-
- return true;
- });
-
- moveRowsPlugin.onMoveRows.subscribe(function(e,args) {
- var extractedRows = [], left, right;
- var rows = args.rows;
- var insertBefore = args.insertBefore;
- left = data.slice(0,insertBefore);
- right = data.slice(insertBefore,data.length);
-
- for (var i=0; i<rows.length; i++) {
- extractedRows.push(data[rows[i]]);
- }
-
- rows.sort().reverse();
-
- for (var i=0; i<rows.length; i++) {
- var row = rows[i];
- if (row < insertBefore)
- left.splice(row,1);
- else
- right.splice(row-insertBefore,1);
- }
-
- data = left.concat(extractedRows.concat(right));
-
- var selectedRows = [];
- for (var i=0; i<rows.length; i++)
- selectedRows.push(left.length+i);
-
- grid.resetActiveCell();
- grid.setData(data);
- grid.setSelectedRows(selectedRows);
- grid.render();
- });
-
- grid.registerPlugin(moveRowsPlugin);
-
- grid.onDragInit.subscribe(function(e,dd) {
- // prevent the grid from cancelling drag'n'drop by default
- e.stopImmediatePropagation();
- });
-
- grid.onDragStart.subscribe(function(e,dd) {
- var cell = grid.getCellFromEvent(e);
- if (!cell)
- return;
-
- dd.row = cell.row;
- if (!data[dd.row])
- return;
-
- if (Slick.GlobalEditorLock.isActive())
- return;
-
- e.stopImmediatePropagation();
- dd.mode = "recycle";
-
- var selectedRows = grid.getSelectedRows();
-
- if (!selectedRows.length || $.inArray(dd.row,selectedRows) == -1) {
- selectedRows = [dd.row];
- grid.setSelectedRows(selectedRows);
- }
-
- dd.rows = selectedRows;
- dd.count = selectedRows.length;
-
- var proxy = $("<span></span>")
- .css({
- position: "absolute",
- display: "inline-block",
- padding: "4px 10px",
- background: "#e0e0e0",
- border: "1px solid gray",
- "z-index": 99999,
- "-moz-border-radius": "8px",
- "-moz-box-shadow": "2px 2px 6px silver"
- })
- .text("Drag to Recycle Bin to delete " + dd.count + " selected row(s)")
- .appendTo("body");
-
- dd.helper = proxy;
-
- $(dd.available).css("background","pink");
-
- return proxy;
- });
-
- grid.onDrag.subscribe(function(e,dd) {
- if (dd.mode != "recycle") {
- return;
- }
- e.stopImmediatePropagation();
- dd.helper.css({top: e.pageY + 5, left: e.pageX + 5});
- });
-
- grid.onDragEnd.subscribe(function(e,dd) {
- if (dd.mode != "recycle") {
- return;
- }
- e.stopImmediatePropagation();
- dd.helper.remove();
- $(dd.available).css("background","beige");
- });
-
-
- $("#dropzone")
- .bind("dropstart", function(e,dd) {
- $(this).css("background","yellow");
- })
- .bind("dropend", function(e,dd) {
- $(dd.available).css("background","pink");
- })
- .bind("drop", function(e,dd) {
- var rowsToDelete = dd.rows.sort().reverse();
- for (var i=0; i<rowsToDelete.length; i++) {
- data.splice(rowsToDelete[i],1);
- }
- grid.invalidate();
- grid.setSelectedRows([]);
- });
-
-
- grid.onAddNewRow.subscribe(function(e, args) {
- var item = {name:"New task", complete: false};
- $.extend(item, args.item);
- data.push(item);
- grid.invalidateRows([data.length - 1]);
- grid.updateRowCount();
- grid.render();
- });
- })
- </script>
- </body>
+ grid.invalidate();
+ grid.setSelectedRows([]);
+ });
+
+
+ grid.onAddNewRow.subscribe(function (e, args) {
+ var item = {name:"New task", complete:false};
+ $.extend(item, args.item);
+ data.push(item);
+ grid.invalidateRows([data.length - 1]);
+ grid.updateRowCount();
+ grid.render();
+ });
+})
+</script>
+</body>
</html>
diff --git a/examples/examples.css b/examples/examples.css
index 63b63e3..8e7d746 100644
--- a/examples/examples.css
+++ b/examples/examples.css
@@ -1,239 +1,230 @@
@import url('slick-default-theme.css');
* {
- font-family: arial;
- font-size: 8pt;
+ font-family: arial;
+ font-size: 8pt;
}
body {
- background: beige;
- padding: 0;
- margin: 8;
+ background: beige;
+ padding: 0;
+ margin: 8;
}
h2 {
- font-size: 10pt;
- border-bottom: 1px dotted gray;
+ font-size: 10pt;
+ border-bottom: 1px dotted gray;
}
ul {
- margin-left: 0;
- padding: 0;
- cursor: default;
+ margin-left: 0;
+ padding: 0;
+ cursor: default;
}
li {
- background: url("../images/arrow_right_spearmint.png") no-repeat center left;
- padding: 0 0 0 14px;
+ background: url("../images/arrow_right_spearmint.png") no-repeat center left;
+ padding: 0 0 0 14px;
- list-style: none;
- margin: 0;
-}
+ list-style: none;
+ margin: 0;
+}
#myGrid {
- background: white;
- outline: 0;
- border: 1px solid gray;
+ background: white;
+ outline: 0;
+ border: 1px solid gray;
}
.grid-header {
- border: 1px solid gray;
- border-bottom: 0;
- border-top: 0;
- background: url('../images/header-bg.gif') repeat-x center top;
- color: black;
- height: 24px;
- line-height: 24px;
-}
+ border: 1px solid gray;
+ border-bottom: 0;
+ border-top: 0;
+ background: url('../images/header-bg.gif') repeat-x center top;
+ color: black;
+ height: 24px;
+ line-height: 24px;
+}
.grid-header label {
- display: inline-block;
- font-weight: bold;
- margin: auto auto auto 6px;
+ display: inline-block;
+ font-weight: bold;
+ margin: auto auto auto 6px;
}
.grid-header .ui-icon {
- margin: 4px 4px auto 6px;
- background-color: transparent;
- border-color: transparent;
+ margin: 4px 4px auto 6px;
+ background-color: transparent;
+ border-color: transparent;
}
.grid-header .ui-icon.ui-state-hover {
- background-color: white;
+ background-color: white;
}
.grid-header #txtSearch {
- margin: 0 4px 0 4px;
- padding: 2px 2px;
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border: 1px solid silver;
+ margin: 0 4px 0 4px;
+ padding: 2px 2px;
+ -moz-border-radius: 2px;
+ -webkit-border-radius: 2px;
+ border: 1px solid silver;
}
.options-panel {
- -moz-border-radius: 6px;
- -webkit-border-radius: 6px;
- border: 1px solid silver;
- background: #f0f0f0;
- padding: 4px;
- margin-bottom: 20px;
- width:320px;
- position:absolute;
- top:0px;
- left:650px;
+ -moz-border-radius: 6px;
+ -webkit-border-radius: 6px;
+ border: 1px solid silver;
+ background: #f0f0f0;
+ padding: 4px;
+ margin-bottom: 20px;
+ width: 320px;
+ position: absolute;
+ top: 0px;
+ left: 650px;
}
-
-
/* Individual cell styles */
.slick-cell.task-name {
- font-weight: bold;
- text-align: right;
+ font-weight: bold;
+ text-align: right;
}
-
.slick-cell.task-percent {
- text-align: right;
+ text-align: right;
}
-
.slick-cell.cell-move-handle {
- font-weight: bold;
- text-align: right;
- border-right: solid gray;
+ font-weight: bold;
+ text-align: right;
+ border-right: solid gray;
- background: #efefef;
- cursor: move;
+ background: #efefef;
+ cursor: move;
}
.cell-move-handle:hover {
- background: #b6b9bd;
+ background: #b6b9bd;
}
.slick-row.selected .cell-move-handle {
- background: #D5DC8D;
+ background: #D5DC8D;
}
.slick-row .cell-actions {
- text-align: left;
+ text-align: left;
}
.slick-row.complete {
- background-color: #DFD;
- color: #555;
+ background-color: #DFD;
+ color: #555;
}
.percent-complete-bar {
- display: inline-block;
- height: 6px;
- -moz-border-radius: 3px;
- -webkit-border-radius: 3px;
+ display: inline-block;
+ height: 6px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
}
-
/* TextCellEditor, DateCellEditor */
input.editor-text {
- width: 100%;
- height: 100%;
- border: 0;
- margin: 0;
- background: transparent;
- outline: 0;
- padding: 0;
+ width: 100%;
+ height: 100%;
+ border: 0;
+ margin: 0;
+ background: transparent;
+ outline: 0;
+ padding: 0;
}
.ui-datepicker-trigger {
- margin-top: 2px;
- padding: 0;
- vertical-align: top;
+ margin-top: 2px;
+ padding: 0;
+ vertical-align: top;
}
/* PercentCompleteCellEditor */
input.editor-percentcomplete {
- width: 100%;
- height: 100%;
- border: 0;
- margin: 0;
- background: transparent;
- outline: 0;
- padding: 0;
+ width: 100%;
+ height: 100%;
+ border: 0;
+ margin: 0;
+ background: transparent;
+ outline: 0;
+ padding: 0;
- float: left;
+ float: left;
}
.editor-percentcomplete-picker {
- position: relative;
- display: inline-block;
- width: 16px;
- height: 100%;
- background: url("../images/pencil.gif") no-repeat center center;
- overflow: visible;
- z-index: 1000;
- float: right;
-}
-
+ position: relative;
+ display: inline-block;
+ width: 16px;
+ height: 100%;
+ background: url("../images/pencil.gif") no-repeat center center;
+ overflow: visible;
+ z-index: 1000;
+ float: right;
+}
+
.editor-percentcomplete-helper {
- border: 0 solid gray;
- position: absolute;
- top: -2px;
- left: -9px;
- background: url("../images/editor-helper-bg.gif") no-repeat top left;
- padding-left: 9px;
+ border: 0 solid gray;
+ position: absolute;
+ top: -2px;
+ left: -9px;
+ background: url("../images/editor-helper-bg.gif") no-repeat top left;
+ padding-left: 9px;
- width: 120px;
- height: 140px;
- display: none;
- overflow: visible;
+ width: 120px;
+ height: 140px;
+ display: none;
+ overflow: visible;
}
-
.editor-percentcomplete-wrapper {
- background:beige;
- padding: 20px 8px;
+ background: beige;
+ padding: 20px 8px;
- width:100%;
- height:98px;
- border:1px solid gray;
- border-left:0;
+ width: 100%;
+ height: 98px;
+ border: 1px solid gray;
+ border-left: 0;
}
.editor-percentcomplete-buttons {
- float: right;
+ float: right;
}
.editor-percentcomplete-buttons button {
- width: 80px;
+ width: 80px;
}
-
.editor-percentcomplete-slider {
- float: left;
+ float: left;
}
- .editor-percentcomplete-picker:hover .editor-percentcomplete-helper {
- display: block;
+.editor-percentcomplete-picker:hover .editor-percentcomplete-helper {
+ display: block;
}
.editor-percentcomplete-helper:hover {
- display: block;
+ display: block;
}
-
-
/* YesNoSelectCellEditor */
select.editor-yesno {
- width: 100%;
- margin: 0;
- vertical-align: middle;
+ width: 100%;
+ margin: 0;
+ vertical-align: middle;
}
/* YesNoCheckboxCellEditor */
input.editor-checkbox {
- margin: 0;
- height: 100%;
- padding: 0;
- border: 0;
+ margin: 0;
+ height: 100%;
+ padding: 0;
+ border: 0;
}
diff --git a/examples/slick-default-theme.css b/examples/slick-default-theme.css
index 5c96b9f..c1f3f2d 100644
--- a/examples/slick-default-theme.css
+++ b/examples/slick-default-theme.css
@@ -6,100 +6,99 @@ classes should alter those!
*/
.slick-header-columns {
- background: url('../images/header-columns-bg.gif') repeat-x center bottom;
- border-bottom: 1px solid silver;
+ background: url('../images/header-columns-bg.gif') repeat-x center bottom;
+ border-bottom: 1px solid silver;
}
.slick-header-column {
- background: url('../images/header-columns-bg.gif') repeat-x center bottom;
- border-right: 1px solid silver;
+ background: url('../images/header-columns-bg.gif') repeat-x center bottom;
+ border-right: 1px solid silver;
}
.slick-header-column:hover, .slick-header-column-active {
- background: white url('../images/header-columns-over-bg.gif') repeat-x center bottom;
+ background: white url('../images/header-columns-over-bg.gif') repeat-x center bottom;
}
.slick-headerrow {
- background: #fafafa;
+ background: #fafafa;
}
.slick-headerrow-column {
- background: #fafafa;
- border-bottom: 0;
- height: 100%;
+ background: #fafafa;
+ border-bottom: 0;
+ height: 100%;
}
.slick-row.ui-state-active {
- background: #F5F7D7;
+ background: #F5F7D7;
}
.slick-row {
- position: absolute;
- background: white;
- border: 0px;
- line-height: 20px;
+ position: absolute;
+ background: white;
+ border: 0px;
+ line-height: 20px;
}
.slick-row.selected {
- z-index: 10;
- background: #DFE8F6;
+ z-index: 10;
+ background: #DFE8F6;
}
.slick-cell {
- padding-left: 4px;
- padding-right: 4px;
+ padding-left: 4px;
+ padding-right: 4px;
}
.slick-group {
- border-bottom: 2px solid silver;
+ border-bottom: 2px solid silver;
}
.slick-group-toggle {
- width: 9px;
- height: 9px;
- margin-right: 5px;
+ width: 9px;
+ height: 9px;
+ margin-right: 5px;
}
.slick-group-toggle.expanded {
- background: url(../images/collapse.gif) no-repeat center center;
+ background: url(../images/collapse.gif) no-repeat center center;
}
.slick-group-toggle.collapsed {
- background: url(../images/expand.gif) no-repeat center center;
+ background: url(../images/expand.gif) no-repeat center center;
}
.slick-group-totals {
- color: gray;
- background: white;
+ color: gray;
+ background: white;
}
.slick-cell.selected {
- background-color: beige;
+ background-color: beige;
}
.slick-cell.active {
- border-color: gray;
- border-style: solid;
+ border-color: gray;
+ border-style: solid;
}
-
.slick-sortable-placeholder {
- background: silver!important;
+ background: silver !important;
}
-.slick-row[row$="1"], .slick-row[row$="3"], .slick-row[row$="5"], .slick-row[row$="7"], .slick-row[row$="9"] {
- background: #fafafa;
+.slick-row[row$="1"], .slick-row[row$="3"], .slick-row[row$="5"], .slick-row[row$="7"], .slick-row[row$="9"] {
+ background: #fafafa;
}
.slick-row.ui-state-active {
- background: #F5F7D7;
+ background: #F5F7D7;
}
.slick-row.loading {
- opacity: 0.5;
- filter: alpha(opacity=50);
+ opacity: 0.5;
+ filter: alpha(opacity = 50);
}
.slick-cell.invalid {
- border-color: red;
+ border-color: red;
} \ No newline at end of file
diff --git a/examples/slick.compositeeditor.js b/examples/slick.compositeeditor.js
index 9dbbc41..9854672 100644
--- a/examples/slick.compositeeditor.js
+++ b/examples/slick.compositeeditor.js
@@ -1,213 +1,211 @@
-;(function($) {
+;
+(function ($) {
+ $.extend(true, window, {
+ Slick:{
+ CompositeEditor:CompositeEditor
+ }
+ });
+
+
+ /***
+ * A composite SlickGrid editor factory.
+ * Generates an editor that is composed of multiple editors for given columns.
+ * Individual editors are provided given containers instead of the original cell.
+ * Validation will be performed on all editors individually and the results will be aggregated into one
+ * validation result.
+ *
+ *
+ * The returned editor will have its prototype set to CompositeEditor, so you can use the "instanceof" check.
+ *
+ * NOTE: This doesn't work for detached editors since they will be created and positioned relative to the
+ * active cell and not the provided container.
+ *
+ * @namespace Slick
+ * @class CompositeEditor
+ * @constructor
+ * @param columns {Array} Column definitions from which editors will be pulled.
+ * @param containers {Array} Container HTMLElements in which editors will be placed.
+ * @param options {Object} Options hash:
+ * validationFailedMsg - A generic failed validation message set on the aggregated validation resuls.
+ * hide - A function to be called when the grid asks the editor to hide itself.
+ * show - A function to be called when the grid asks the editor to show itself.
+ * position - A function to be called when the grid asks the editor to reposition itself.
+ * destroy - A function to be called when the editor is destroyed.
+ */
+ function CompositeEditor(columns, containers, options) {
+ var defaultOptions = {
+ validationFailedMsg:"Some of the fields have failed validation",
+ show:null,
+ hide:null,
+ position:null,
+ destroy:null
+ };
+
+ var noop = function () {
+ };
+
+ var firstInvalidEditor;
+
+ options = $.extend({}, defaultOptions, options);
+
+
+ function getContainerBox(i) {
+ var c = containers[i];
+ var offset = $(c).offset();
+ var w = $(c).width();
+ var h = $(c).height();
+
+ return {
+ top:offset.top,
+ left:offset.left,
+ bottom:offset.top + h,
+ right:offset.left + w,
+ width:w,
+ height:h,
+ visible:true
+ };
+ }
+
+
+ function editor(args) {
+ var editors = [];
+
+
+ function init() {
+ var newArgs = {};
+ var idx = columns.length;
+ while (idx--) {
+ if (columns[idx].editor) {
+ newArgs = $.extend({}, args);
+ newArgs.container = containers[idx];
+ newArgs.column = columns[idx];
+ newArgs.position = getContainerBox(idx);
+ newArgs.commitChanges = noop;
+ newArgs.cancelChanges = noop;
+
+ editors[idx] = new (columns[idx].editor)(newArgs);
+ }
+ }
+ }
+
- $.extend(true, window, {
- Slick: {
- CompositeEditor: CompositeEditor
+ this.destroy = function () {
+ var idx = editors.length;
+ while (idx--) {
+ editors[idx].destroy();
}
- });
-
-
- /***
- * A composite SlickGrid editor factory.
- * Generates an editor that is composed of multiple editors for given columns.
- * Individual editors are provided given containers instead of the original cell.
- * Validation will be performed on all editors individually and the results will be aggregated into one
- * validation result.
- *
- *
- * The returned editor will have its prototype set to CompositeEditor, so you can use the "instanceof" check.
- *
- * NOTE: This doesn't work for detached editors since they will be created and positioned relative to the
- * active cell and not the provided container.
- *
- * @namespace Slick
- * @class CompositeEditor
- * @constructor
- * @param columns {Array} Column definitions from which editors will be pulled.
- * @param containers {Array} Container HTMLElements in which editors will be placed.
- * @param options {Object} Options hash:
- * validationFailedMsg - A generic failed validation message set on the aggregated validation resuls.
- * hide - A function to be called when the grid asks the editor to hide itself.
- * show - A function to be called when the grid asks the editor to show itself.
- * position - A function to be called when the grid asks the editor to reposition itself.
- * destroy - A function to be called when the editor is destroyed.
- */
- function CompositeEditor(columns, containers, options) {
- var defaultOptions = {
- validationFailedMsg: "Some of the fields have failed validation",
- show: null,
- hide: null,
- position: null,
- destroy: null
- };
-
- var noop = function () {};
-
- var firstInvalidEditor;
-
- options = $.extend({}, defaultOptions, options);
-
-
- function getContainerBox(i) {
- var c = containers[i];
- var offset = $(c).offset();
- var w = $(c).width();
- var h = $(c).height();
-
- return {
- top: offset.top,
- left: offset.left,
- bottom: offset.top + h,
- right: offset.left + w,
- width: w,
- height: h,
- visible: true
- };
+
+ options.destroy && options.destroy();
+ };
+
+
+ this.focus = function () {
+ // if validation has failed, set the focus to the first invalid editor
+ (firstInvalidEditor || editors[0]).focus();
+ };
+
+
+ this.isValueChanged = function () {
+ var idx = editors.length;
+ while (idx--) {
+ if (editors[idx].isValueChanged()) {
+ return true;
+ }
+ }
+ return false;
+ };
+
+
+ this.serializeValue = function () {
+ var serializedValue = [];
+ var idx = editors.length;
+ while (idx--) {
+ serializedValue[idx] = editors[idx].serializeValue();
}
+ return serializedValue;
+ };
- function editor(args) {
- var editors = [];
-
-
- function init() {
- var newArgs = {};
- var idx = columns.length;
- while (idx--) {
- if (columns[idx].editor) {
- newArgs = $.extend({}, args);
- newArgs.container = containers[idx];
- newArgs.column = columns[idx];
- newArgs.position = getContainerBox(idx);
- newArgs.commitChanges = noop;
- newArgs.cancelChanges = noop;
-
- editors[idx] = new (columns[idx].editor)(newArgs);
- }
- }
- }
-
-
- this.destroy = function () {
- var idx = editors.length;
- while (idx--) {
- editors[idx].destroy();
- }
-
- options.destroy && options.destroy();
- };
-
-
- this.focus = function () {
- // if validation has failed, set the focus to the first invalid editor
- (firstInvalidEditor || editors[0]).focus();
- };
-
-
- this.isValueChanged = function () {
- var idx = editors.length;
- while (idx--) {
- if (editors[idx].isValueChanged()) {
- return true;
- }
- }
- return false;
- };
-
-
- this.serializeValue = function () {
- var serializedValue = [];
- var idx = editors.length;
- while (idx--) {
- serializedValue[idx] = editors[idx].serializeValue();
- }
- return serializedValue;
- };
-
-
- this.applyValue = function (item, state) {
- var idx = editors.length;
- while (idx--) {
- editors[idx].applyValue(item, state[idx]);
- }
- };
-
-
- this.loadValue = function (item) {
- var idx = editors.length;
- while (idx--) {
- editors[idx].loadValue(item);
- }
- };
-
-
- this.validate = function () {
- var validationResults;
- var errors = [];
-
- firstInvalidEditor = null;
-
- var idx = editors.length;
- while (idx--) {
- validationResults = editors[idx].validate();
- if (!validationResults.valid) {
- firstInvalidEditor = editors[idx];
- errors.push({
- index: idx,
- editor: editors[idx],
- container: containers[idx],
- msg: validationResults.msg
- });
- }
- }
-
- if (errors.length) {
- return {
- valid: false,
- msg: options.validationFailedMsg,
- errors: errors
- };
- }
- else {
- return {
- valid: true,
- msg: ""
- };
- }
- };
-
-
- this.hide = function () {
- var idx = editors.length;
- while (idx--) {
- editors[idx].hide && editors[idx].hide();
- }
-
- options.hide && options.hide();
- };
-
-
- this.show = function () {
- var idx = editors.length;
- while (idx--) {
- editors[idx].show && editors[idx].show();
- }
-
- options.show && options.show();
- };
-
-
- this.position = function (box) {
- options.position && options.position(box);
- };
-
-
- init();
+ this.applyValue = function (item, state) {
+ var idx = editors.length;
+ while (idx--) {
+ editors[idx].applyValue(item, state[idx]);
}
+ };
- // so we can do "editor instanceof Slick.CompositeEditor
- editor.prototype = this;
- return editor;
+ this.loadValue = function (item) {
+ var idx = editors.length;
+ while (idx--) {
+ editors[idx].loadValue(item);
+ }
+ };
+
+
+ this.validate = function () {
+ var validationResults;
+ var errors = [];
+
+ firstInvalidEditor = null;
+
+ var idx = editors.length;
+ while (idx--) {
+ validationResults = editors[idx].validate();
+ if (!validationResults.valid) {
+ firstInvalidEditor = editors[idx];
+ errors.push({
+ index:idx,
+ editor:editors[idx],
+ container:containers[idx],
+ msg:validationResults.msg
+ });
+ }
+ }
+
+ if (errors.length) {
+ return {
+ valid:false,
+ msg:options.validationFailedMsg,
+ errors:errors
+ };
+ } else {
+ return {
+ valid:true,
+ msg:""
+ };
+ }
+ };
+
+
+ this.hide = function () {
+ var idx = editors.length;
+ while (idx--) {
+ editors[idx].hide && editors[idx].hide();
+ }
+ options.hide && options.hide();
+ };
+
+
+ this.show = function () {
+ var idx = editors.length;
+ while (idx--) {
+ editors[idx].show && editors[idx].show();
+ }
+ options.show && options.show();
+ };
+
+
+ this.position = function (box) {
+ options.position && options.position(box);
+ };
+
+
+ init();
}
+
+ // so we can do "editor instanceof Slick.CompositeEditor
+ editor.prototype = this;
+
+ return editor;
+ }
})(jQuery); \ No newline at end of file
diff --git a/plugins/slick.autotooltips.js b/plugins/slick.autotooltips.js
index c5c4897..4d2baea 100644
--- a/plugins/slick.autotooltips.js
+++ b/plugins/slick.autotooltips.js
@@ -1,49 +1,48 @@
-(function($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "AutoTooltips": AutoTooltips
- }
- });
+(function ($) {
+ // register namespace
+ $.extend(true, window, {
+ "Slick":{
+ "AutoTooltips":AutoTooltips
+ }
+ });
- function AutoTooltips(options) {
- var _grid;
- var _self = this;
- var _defaults = {
- maxToolTipLength: null
- };
+ function AutoTooltips(options) {
+ var _grid;
+ var _self = this;
+ var _defaults = {
+ maxToolTipLength:null
+ };
- function init(grid) {
- options = $.extend(true,{},_defaults,options);
- _grid = grid;
- _grid.onMouseEnter.subscribe(handleMouseEnter);
- }
+ function init(grid) {
+ options = $.extend(true, {}, _defaults, options);
+ _grid = grid;
+ _grid.onMouseEnter.subscribe(handleMouseEnter);
+ }
- function destroy() {
- _grid.onMouseEnter.unsubscribe(handleMouseEnter);
- }
+ function destroy() {
+ _grid.onMouseEnter.unsubscribe(handleMouseEnter);
+ }
- function handleMouseEnter(e,args) {
- var cell = _grid.getCellFromEvent(e);
- if (cell) {
- var node = _grid.getCellNode(cell.row, cell.cell);
- if ($(node).innerWidth() < node.scrollWidth) {
- var text = $.trim($(node).text());
- if (options.maxToolTipLength && text.length > options.maxToolTipLength) {
- text = text.substr(0, options.maxToolTipLength - 3) + "...";
- }
- $(node).attr("title",text);
- }
- else {
- $(node).attr("title","");
- }
- }
+ function handleMouseEnter(e, args) {
+ var cell = _grid.getCellFromEvent(e);
+ if (cell) {
+ var node = _grid.getCellNode(cell.row, cell.cell);
+ if ($(node).innerWidth() < node.scrollWidth) {
+ var text = $.trim($(node).text());
+ if (options.maxToolTipLength && text.length > options.maxToolTipLength) {
+ text = text.substr(0, options.maxToolTipLength - 3) + "...";
+ }
+ $(node).attr("title", text);
+ } else {
+ $(node).attr("title", "");
}
-
- $.extend(this, {
- "init": init,
- "destroy": destroy
- });
+ }
}
+
+ $.extend(this, {
+ "init":init,
+ "destroy":destroy
+ });
+ }
})(jQuery); \ No newline at end of file
diff --git a/plugins/slick.cellcopymanager.js b/plugins/slick.cellcopymanager.js
index 2b283f0..1d9c613 100644
--- a/plugins/slick.cellcopymanager.js
+++ b/plugins/slick.cellcopymanager.js
@@ -1,86 +1,86 @@
-(function($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "CellCopyManager": CellCopyManager
- }
- });
-
-
- function CellCopyManager() {
- var _grid;
- var _self = this;
- var _copiedRanges;
+(function ($) {
+ // register namespace
+ $.extend(true, window, {
+ "Slick":{
+ "CellCopyManager":CellCopyManager
+ }
+ });
- function init(grid) {
- _grid = grid;
- _grid.onKeyDown.subscribe(handleKeyDown);
- }
- function destroy() {
- _grid.onKeyDown.unsubscribe(handleKeyDown);
- }
+ function CellCopyManager() {
+ var _grid;
+ var _self = this;
+ var _copiedRanges;
- function handleKeyDown(e, args) {
- var ranges;
- if (!_grid.getEditorLock().isActive()) {
- if (e.which == $.ui.keyCode.ESCAPE) {
- if (_copiedRanges) {
- e.preventDefault();
- clearCopySelection();
- _self.onCopyCancelled.notify({ranges:_copiedRanges});
- _copiedRanges = null;
- }
- }
+ function init(grid) {
+ _grid = grid;
+ _grid.onKeyDown.subscribe(handleKeyDown);
+ }
- if (e.which == 67 && (e.ctrlKey || e.metaKey)) {
- ranges = _grid.getSelectionModel().getSelectedRanges();
- if (ranges.length != 0) {
- e.preventDefault();
- _copiedRanges = ranges;
- markCopySelection(ranges);
- _self.onCopyCells.notify({ranges:ranges});
- }
- }
+ function destroy() {
+ _grid.onKeyDown.unsubscribe(handleKeyDown);
+ }
- if (e.which == 86 && (e.ctrlKey || e.metaKey)) {
- if (_copiedRanges) {
- e.preventDefault();
- clearCopySelection();
- ranges = _grid.getSelectionModel().getSelectedRanges();
- _self.onPasteCells.notify({from:_copiedRanges, to:ranges});
- _copiedRanges = null;
- }
- }
- }
+ function handleKeyDown(e, args) {
+ var ranges;
+ if (!_grid.getEditorLock().isActive()) {
+ if (e.which == $.ui.keyCode.ESCAPE) {
+ if (_copiedRanges) {
+ e.preventDefault();
+ clearCopySelection();
+ _self.onCopyCancelled.notify({ranges:_copiedRanges});
+ _copiedRanges = null;
+ }
}
- function markCopySelection(ranges) {
- var columns = _grid.getColumns();
- var hash = {};
- for (var i = 0; i < ranges.length; i++) {
- for (var j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
- hash[j] = {};
- for (var k = ranges[i].fromCell; k <= ranges[i].toCell; k++) {
- hash[j][columns[k].id] = "copied";
- }
- }
- }
- _grid.setCellCssStyles("copy-manager", hash);
+ if (e.which == 67 && (e.ctrlKey || e.metaKey)) {
+ ranges = _grid.getSelectionModel().getSelectedRanges();
+ if (ranges.length != 0) {
+ e.preventDefault();
+ _copiedRanges = ranges;
+ markCopySelection(ranges);
+ _self.onCopyCells.notify({ranges:ranges});
+ }
}
- function clearCopySelection() {
- _grid.removeCellCssStyles("copy-manager");
+ if (e.which == 86 && (e.ctrlKey || e.metaKey)) {
+ if (_copiedRanges) {
+ e.preventDefault();
+ clearCopySelection();
+ ranges = _grid.getSelectionModel().getSelectedRanges();
+ _self.onPasteCells.notify({from:_copiedRanges, to:ranges});
+ _copiedRanges = null;
+ }
}
+ }
+ }
- $.extend(this, {
- "init": init,
- "destroy": destroy,
- "clearCopySelection": clearCopySelection,
+ function markCopySelection(ranges) {
+ var columns = _grid.getColumns();
+ var hash = {};
+ for (var i = 0; i < ranges.length; i++) {
+ for (var j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
+ hash[j] = {};
+ for (var k = ranges[i].fromCell; k <= ranges[i].toCell; k++) {
+ hash[j][columns[k].id] = "copied";
+ }
+ }
+ }
+ _grid.setCellCssStyles("copy-manager", hash);
+ }
- "onCopyCells": new Slick.Event(),
- "onCopyCancelled": new Slick.Event(),
- "onPasteCells": new Slick.Event()
- });
+ function clearCopySelection() {
+ _grid.removeCellCssStyles("copy-manager");
}
+
+ $.extend(this, {
+ "init":init,
+ "destroy":destroy,
+ "clearCopySelection":clearCopySelection,
+
+ "onCopyCells":new Slick.Event(),
+ "onCopyCancelled":new Slick.Event(),
+ "onPasteCells":new Slick.Event()
+ });
+ }
})(jQuery); \ No newline at end of file
diff --git a/plugins/slick.cellrangedecorator.js b/plugins/slick.cellrangedecorator.js
index 38df0b6..342f705 100644
--- a/plugins/slick.cellrangedecorator.js
+++ b/plugins/slick.cellrangedecorator.js
@@ -1,65 +1,64 @@
-(function($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "CellRangeDecorator": CellRangeDecorator
- }
- });
-
- /***
- * Displays an overlay on top of a given cell range.
- *
- * TODO:
- * Currently, it blocks mouse events to DOM nodes behind it.
- * Use FF and WebKit-specific "pointer-events" CSS style, or some kind of event forwarding.
- * Could also construct the borders separately using 4 individual DIVs.
- *
- * @param {Grid} grid
- * @param {Object} options
- */
- function CellRangeDecorator(grid, options) {
- var _elem;
- var _defaults = {
- selectionCss: {
- "zIndex": "9999",
- "border": "2px dashed red"
- }
- };
-
- options = $.extend(true, {}, _defaults, options);
+(function ($) {
+ // register namespace
+ $.extend(true, window, {
+ "Slick":{
+ "CellRangeDecorator":CellRangeDecorator
+ }
+ });
+ /***
+ * Displays an overlay on top of a given cell range.
+ *
+ * TODO:
+ * Currently, it blocks mouse events to DOM nodes behind it.
+ * Use FF and WebKit-specific "pointer-events" CSS style, or some kind of event forwarding.
+ * Could also construct the borders separately using 4 individual DIVs.
+ *
+ * @param {Grid} grid
+ * @param {Object} options
+ */
+ function CellRangeDecorator(grid, options) {
+ var _elem;
+ var _defaults = {
+ selectionCss:{
+ "zIndex":"9999",
+ "border":"2px dashed red"
+ }
+ };
- function show(range) {
- if (!_elem) {
- _elem = $("<div></div>", {css: options.selectionCss})
- .css("position", "absolute")
- .appendTo(grid.getCanvasNode());
+ options = $.extend(true, {}, _defaults, options);
- }
- var from = grid.getCellNodeBox(range.fromRow,range.fromCell);
- var to = grid.getCellNodeBox(range.toRow,range.toCell);
+ function show(range) {
+ if (!_elem) {
+ _elem = $("<div></div>", {css:options.selectionCss})
+ .css("position", "absolute")
+ .appendTo(grid.getCanvasNode());
+ }
- _elem.css({
- top: from.top - 1,
- left: from.left - 1,
- height: to.bottom - from.top - 2,
- width: to.right - from.left - 2
- });
+ var from = grid.getCellNodeBox(range.fromRow, range.fromCell);
+ var to = grid.getCellNodeBox(range.toRow, range.toCell);
- return _elem;
- }
+ _elem.css({
+ top:from.top - 1,
+ left:from.left - 1,
+ height:to.bottom - from.top - 2,
+ width:to.right - from.left - 2
+ });
- function hide() {
- if (_elem) {
- _elem.remove();
- _elem = null;
- }
- }
+ return _elem;
+ }
- $.extend(this, {
- "show": show,
- "hide": hide
- });
+ function hide() {
+ if (_elem) {
+ _elem.remove();
+ _elem = null;
+ }
}
+
+ $.extend(this, {
+ "show":show,
+ "hide":hide
+ });
+ }
})(jQuery); \ No newline at end of file
diff --git a/plugins/slick.cellrangeselector.js b/plugins/slick.cellrangeselector.js
index 3928b2f..118239e 100644
--- a/plugins/slick.cellrangeselector.js
+++ b/plugins/slick.cellrangeselector.js
@@ -1,112 +1,112 @@
-(function($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "CellRangeSelector": CellRangeSelector
- }
- });
+(function ($) {
+ // register namespace
+ $.extend(true, window, {
+ "Slick":{
+ "CellRangeSelector":CellRangeSelector
+ }
+ });
+
+
+ function CellRangeSelector(options) {
+ var _grid;
+ var _canvas;
+ var _dragging;
+ var _decorator;
+ var _self = this;
+ var _defaults = {
+ selectionCss:{
+ "border":"2px dashed blue"
+ }
+ };
+
+
+ function init(grid) {
+ options = $.extend(true, {}, _defaults, options);
+ _decorator = new Slick.CellRangeDecorator(grid, options);
+ _grid = grid;
+ _canvas = _grid.getCanvasNode();
+ _grid.onDragInit.subscribe(handleDragInit);
+ _grid.onDragStart.subscribe(handleDragStart);
+ _grid.onDrag.subscribe(handleDrag);
+ _grid.onDragEnd.subscribe(handleDragEnd);
+ }
+ function destroy() {
+ _grid.onDragInit.unsubscribe(handleDragInit);
+ _grid.onDragStart.unsubscribe(handleDragStart);
+ _grid.onDrag.unsubscribe(handleDrag);
+ _grid.onDragEnd.unsubscribe(handleDragEnd);
+ }
- function CellRangeSelector(options) {
- var _grid;
- var _canvas;
- var _dragging;
- var _decorator;
- var _self = this;
- var _defaults = {
- selectionCss: {
- "border": "2px dashed blue"
- }
- };
-
-
- function init(grid) {
- options = $.extend(true, {}, _defaults, options);
- _decorator = new Slick.CellRangeDecorator(grid, options);
- _grid = grid;
- _canvas = _grid.getCanvasNode();
- _grid.onDragInit.subscribe(handleDragInit);
- _grid.onDragStart.subscribe(handleDragStart);
- _grid.onDrag.subscribe(handleDrag);
- _grid.onDragEnd.subscribe(handleDragEnd);
- }
+ function handleDragInit(e, dd) {
+ // prevent the grid from cancelling drag'n'drop by default
+ e.stopImmediatePropagation();
+ }
- function destroy() {
- _grid.onDragInit.unsubscribe(handleDragInit);
- _grid.onDragStart.unsubscribe(handleDragStart);
- _grid.onDrag.unsubscribe(handleDrag);
- _grid.onDragEnd.unsubscribe(handleDragEnd);
+ function handleDragStart(e, dd) {
+ var cell = _grid.getCellFromEvent(e);
+ if (_self.onBeforeCellRangeSelected.notify(cell) !== false) {
+ if (_grid.canCellBeSelected(cell.row, cell.cell)) {
+ _dragging = true;
+ e.stopImmediatePropagation();
}
+ }
+ if (!_dragging) {
+ return;
+ }
- function handleDragInit(e, dd) {
- // prevent the grid from cancelling drag'n'drop by default
- e.stopImmediatePropagation();
- }
+ var start = _grid.getCellFromPoint(
+ dd.startX - $(_canvas).offset().left,
+ dd.startY - $(_canvas).offset().top);
- function handleDragStart(e, dd) {
- var cell = _grid.getCellFromEvent(e);
- if (_self.onBeforeCellRangeSelected.notify(cell) !== false) {
- if (_grid.canCellBeSelected(cell.row,cell.cell)) {
- _dragging = true;
- e.stopImmediatePropagation();
- }
- }
- if (!_dragging) {
- return;
- }
-
- var start = _grid.getCellFromPoint(
- dd.startX - $(_canvas).offset().left,
- dd.startY - $(_canvas).offset().top);
-
- dd.range = {start:start,end:{}};
-
- return _decorator.show(new Slick.Range(start.row,start.cell));
- }
+ dd.range = {start:start, end:{}};
- function handleDrag(e, dd) {
- if (!_dragging) {
- return;
- }
- e.stopImmediatePropagation();
-
- var end = _grid.getCellFromPoint(
- e.pageX - $(_canvas).offset().left,
- e.pageY - $(_canvas).offset().top);
+ return _decorator.show(new Slick.Range(start.row, start.cell));
+ }
- if (!_grid.canCellBeSelected(end.row,end.cell)) {
- return;
- }
+ function handleDrag(e, dd) {
+ if (!_dragging) {
+ return;
+ }
+ e.stopImmediatePropagation();
- dd.range.end = end;
- _decorator.show(new Slick.Range(dd.range.start.row,dd.range.start.cell,end.row,end.cell));
- }
+ var end = _grid.getCellFromPoint(
+ e.pageX - $(_canvas).offset().left,
+ e.pageY - $(_canvas).offset().top);
- function handleDragEnd(e, dd) {
- if (!_dragging) {
- return;
- }
-
- _dragging = false;
- e.stopImmediatePropagation();
-
- _decorator.hide();
- _self.onCellRangeSelected.notify({
- range: new Slick.Range(
- dd.range.start.row,
- dd.range.start.cell,
- dd.range.end.row,
- dd.range.end.cell
- )
- });
- }
+ if (!_grid.canCellBeSelected(end.row, end.cell)) {
+ return;
+ }
- $.extend(this, {
- "init": init,
- "destroy": destroy,
+ dd.range.end = end;
+ _decorator.show(new Slick.Range(dd.range.start.row, dd.range.start.cell, end.row, end.cell));
+ }
- "onBeforeCellRangeSelected": new Slick.Event(),
- "onCellRangeSelected": new Slick.Event()
- });
+ function handleDragEnd(e, dd) {
+ if (!_dragging) {
+ return;
+ }
+
+ _dragging = false;
+ e.stopImmediatePropagation();
+
+ _decorator.hide();
+ _self.onCellRangeSelected.notify({
+ range:new Slick.Range(
+ dd.range.start.row,
+ dd.range.start.cell,
+ dd.range.end.row,
+ dd.range.end.cell
+ )
+ });
}
+
+ $.extend(this, {
+ "init":init,
+ "destroy":destroy,
+
+ "onBeforeCellRangeSelected":new Slick.Event(),
+ "onCellRangeSelected":new Slick.Event()
+ });
+ }
})(jQuery); \ No newline at end of file
diff --git a/plugins/slick.cellselectionmodel.js b/plugins/slick.cellselectionmodel.js
index e1dd565..c517117 100644
--- a/plugins/slick.cellselectionmodel.js
+++ b/plugins/slick.cellselectionmodel.js
@@ -1,92 +1,92 @@
-(function($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "CellSelectionModel": CellSelectionModel
- }
+(function ($) {
+ // register namespace
+ $.extend(true, window, {
+ "Slick":{
+ "CellSelectionModel":CellSelectionModel
+ }
+ });
+
+
+ function CellSelectionModel(options) {
+ var _grid;
+ var _canvas;
+ var _ranges = [];
+ var _self = this;
+ var _selector = new Slick.CellRangeSelector({
+ "selectionCss":{
+ "border":"2px solid black"
+ }
});
+ var _options;
+ var _defaults = {
+ selectActiveCell:true
+ };
+
+
+ function init(grid) {
+ _options = $.extend(true, {}, _defaults, options);
+ _grid = grid;
+ _canvas = _grid.getCanvasNode();
+ _grid.onActiveCellChanged.subscribe(handleActiveCellChange);
+ grid.registerPlugin(_selector);
+ _selector.onCellRangeSelected.subscribe(handleCellRangeSelected);
+ _selector.onBeforeCellRangeSelected.subscribe(handleBeforeCellRangeSelected);
+ }
+ function destroy() {
+ _grid.onActiveCellChanged.unsubscribe(handleActiveCellChange);
+ _selector.onCellRangeSelected.unsubscribe(handleCellRangeSelected);
+ _selector.onBeforeCellRangeSelected.unsubscribe(handleBeforeCellRangeSelected);
+ _grid.unregisterPlugin(_selector);
+ }
- function CellSelectionModel(options) {
- var _grid;
- var _canvas;
- var _ranges = [];
- var _self = this;
- var _selector = new Slick.CellRangeSelector({
- "selectionCss": {
- "border": "2px solid black"
- }
- });
- var _options;
- var _defaults = {
- selectActiveCell: true
- };
-
-
- function init(grid) {
- _options = $.extend(true, {}, _defaults, options);
- _grid = grid;
- _canvas = _grid.getCanvasNode();
- _grid.onActiveCellChanged.subscribe(handleActiveCellChange);
- grid.registerPlugin(_selector);
- _selector.onCellRangeSelected.subscribe(handleCellRangeSelected);
- _selector.onBeforeCellRangeSelected.subscribe(handleBeforeCellRangeSelected);
- }
+ function removeInvalidRanges(ranges) {
+ var result = [];
- function destroy() {
- _grid.onActiveCellChanged.unsubscribe(handleActiveCellChange);
- _selector.onCellRangeSelected.unsubscribe(handleCellRangeSelected);
- _selector.onBeforeCellRangeSelected.unsubscribe(handleBeforeCellRangeSelected);
- _grid.unregisterPlugin(_selector);
+ for (var i = 0; i < ranges.length; i++) {
+ var r = ranges[i];
+ if (_grid.canCellBeSelected(r.fromRow, r.fromCell) && _grid.canCellBeSelected(r.toRow, r.toCell)) {
+ result.push(r);
}
+ }
- function removeInvalidRanges(ranges) {
- var result = [];
-
- for (var i = 0; i < ranges.length; i++) {
- var r = ranges[i];
- if (_grid.canCellBeSelected(r.fromRow,r.fromCell) && _grid.canCellBeSelected(r.toRow,r.toCell)) {
- result.push(r);
- }
- }
-
- return result;
- }
+ return result;
+ }
- function setSelectedRanges(ranges) {
- _ranges = removeInvalidRanges(ranges);
- _self.onSelectedRangesChanged.notify(_ranges);
- }
+ function setSelectedRanges(ranges) {
+ _ranges = removeInvalidRanges(ranges);
+ _self.onSelectedRangesChanged.notify(_ranges);
+ }
- function getSelectedRanges() {
- return _ranges;
- }
+ function getSelectedRanges() {
+ return _ranges;
+ }
- function handleBeforeCellRangeSelected(e, args) {
- if (_grid.getEditorLock().isActive()) {
- e.stopPropagation();
- return false;
- }
- }
+ function handleBeforeCellRangeSelected(e, args) {
+ if (_grid.getEditorLock().isActive()) {
+ e.stopPropagation();
+ return false;
+ }
+ }
- function handleCellRangeSelected(e, args) {
- setSelectedRanges([args.range]);
- }
+ function handleCellRangeSelected(e, args) {
+ setSelectedRanges([args.range]);
+ }
- function handleActiveCellChange(e, args) {
- if (_options.selectActiveCell) {
- setSelectedRanges([new Slick.Range(args.row,args.cell)]);
- }
- }
+ function handleActiveCellChange(e, args) {
+ if (_options.selectActiveCell) {
+ setSelectedRanges([new Slick.Range(args.row, args.cell)]);
+ }
+ }
- $.extend(this, {
- "getSelectedRanges": getSelectedRanges,
- "setSelectedRanges": setSelectedRanges,
+ $.extend(this, {
+ "getSelectedRanges":getSelectedRanges,
+ "setSelectedRanges":setSelectedRanges,
- "init": init,
- "destroy": destroy,
+ "init":init,
+ "destroy":destroy,
- "onSelectedRangesChanged": new Slick.Event()
- });
- }
+ "onSelectedRangesChanged":new Slick.Event()
+ });
+ }
})(jQuery); \ No newline at end of file
diff --git a/plugins/slick.checkboxselectcolumn.js b/plugins/slick.checkboxselectcolumn.js
index 3a95255..c7078b9 100644
--- a/plugins/slick.checkboxselectcolumn.js
+++ b/plugins/slick.checkboxselectcolumn.js
@@ -1,136 +1,135 @@
-(function($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "CheckboxSelectColumn": CheckboxSelectColumn
- }
- });
-
+(function ($) {
+ // register namespace
+ $.extend(true, window, {
+ "Slick":{
+ "CheckboxSelectColumn":CheckboxSelectColumn
+ }
+ });
- function CheckboxSelectColumn(options) {
- var _grid;
- var _self = this;
- var _selectedRowsLookup = {};
- var _defaults = {
- columnId: "_checkbox_selector",
- cssClass: null,
- toolTip: "Select/Deselect All",
- width: 30
- };
- var _options = $.extend(true,{},_defaults,options);
+ function CheckboxSelectColumn(options) {
+ var _grid;
+ var _self = this;
+ var _selectedRowsLookup = {};
+ var _defaults = {
+ columnId:"_checkbox_selector",
+ cssClass:null,
+ toolTip:"Select/Deselect All",
+ width:30
+ };
- function init(grid) {
- _grid = grid;
- _grid.onSelectedRowsChanged.subscribe(handleSelectedRowsChanged);
- _grid.onClick.subscribe(handleClick);
- _grid.onHeaderClick.subscribe(handleHeaderClick);
- }
+ var _options = $.extend(true, {}, _defaults, options);
- function destroy() {
- _grid.onSelectedRowsChanged.unsubscribe(handleSelectedRowsChanged);
- _grid.onClick.unsubscribe(handleClick);
- _grid.onHeaderClick.unsubscribe(handleHeaderClick);
- }
+ function init(grid) {
+ _grid = grid;
+ _grid.onSelectedRowsChanged.subscribe(handleSelectedRowsChanged);
+ _grid.onClick.subscribe(handleClick);
+ _grid.onHeaderClick.subscribe(handleHeaderClick);
+ }
- 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();
+ function destroy() {
+ _grid.onSelectedRowsChanged.unsubscribe(handleSelectedRowsChanged);
+ _grid.onClick.unsubscribe(handleClick);
+ _grid.onHeaderClick.unsubscribe(handleHeaderClick);
+ }
- if (selectedRows.length == _grid.getDataLength()) {
- _grid.updateColumnHeader(_options.columnId, "<input type='checkbox' checked='checked'>", _options.toolTip);
- }
- else {
- _grid.updateColumnHeader(_options.columnId, "<input type='checkbox'>", _options.toolTip);
- }
+ 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();
- 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;
- }
+ if (selectedRows.length == _grid.getDataLength()) {
+ _grid.updateColumnHeader(_options.columnId, "<input type='checkbox' checked='checked'>", _options.toolTip);
+ } else {
+ _grid.updateColumnHeader(_options.columnId, "<input type='checkbox'>", _options.toolTip);
+ }
+ }
- if (_selectedRowsLookup[args.row]) {
- _grid.setSelectedRows($.grep(_grid.getSelectedRows(),function(n) { return n != args.row }));
- }
- else {
- _grid.setSelectedRows(_grid.getSelectedRows().concat(args.row));
- }
- e.stopPropagation();
- 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;
}
- 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;
- }
-
- if ($(e.target).is(":checked")) {
- var rows = [];
- for (var i = 0; i < _grid.getDataLength(); i++) {
- rows.push(i);
- }
- _grid.setSelectedRows(rows);
- }
- else {
- _grid.setSelectedRows([]);
- }
- e.stopPropagation();
- e.stopImmediatePropagation();
- }
+ if (_selectedRowsLookup[args.row]) {
+ _grid.setSelectedRows($.grep(_grid.getSelectedRows(), function (n) {
+ return n != args.row
+ }));
+ } else {
+ _grid.setSelectedRows(_grid.getSelectedRows().concat(args.row));
}
+ e.stopPropagation();
+ e.stopImmediatePropagation();
+ }
+ }
- function getColumnDefinition() {
- return {
- id: _options.columnId,
- name: "<input type='checkbox'>",
- toolTip: _options.toolTip,
- field: "sel",
- width: _options.width,
- resizable: false,
- sortable: false,
- cssClass: _options.cssClass,
- formatter: checkboxSelectionFormatter
- };
+ 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;
}
- function checkboxSelectionFormatter(row, cell, value, columnDef, dataContext) {
- if (dataContext) {
- return _selectedRowsLookup[row]
- ? "<input type='checkbox' checked='checked'>"
- : "<input type='checkbox'>";
- }
- return null;
+ if ($(e.target).is(":checked")) {
+ var rows = [];
+ for (var i = 0; i < _grid.getDataLength(); i++) {
+ rows.push(i);
+ }
+ _grid.setSelectedRows(rows);
+ } else {
+ _grid.setSelectedRows([]);
}
+ e.stopPropagation();
+ e.stopImmediatePropagation();
+ }
+ }
- $.extend(this, {
- "init": init,
- "destroy": destroy,
+ function getColumnDefinition() {
+ return {
+ id:_options.columnId,
+ name:"<input type='checkbox'>",
+ toolTip:_options.toolTip,
+ field:"sel",
+ width:_options.width,
+ resizable:false,
+ sortable:false,
+ cssClass:_options.cssClass,
+ formatter:checkboxSelectionFormatter
+ };
+ }
- "getColumnDefinition": getColumnDefinition
- });
+ function checkboxSelectionFormatter(row, cell, value, columnDef, dataContext) {
+ if (dataContext) {
+ return _selectedRowsLookup[row]
+ ? "<input type='checkbox' checked='checked'>"
+ : "<input type='checkbox'>";
+ }
+ return null;
}
+
+ $.extend(this, {
+ "init":init,
+ "destroy":destroy,
+
+ "getColumnDefinition":getColumnDefinition
+ });
+ }
})(jQuery); \ No newline at end of file
diff --git a/plugins/slick.rowmovemanager.js b/plugins/slick.rowmovemanager.js
index afb3519..3b26c47 100644
--- a/plugins/slick.rowmovemanager.js
+++ b/plugins/slick.rowmovemanager.js
@@ -1,133 +1,132 @@
-(function($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "RowMoveManager": RowMoveManager
- }
- });
+(function ($) {
+ // register namespace
+ $.extend(true, window, {
+ "Slick":{
+ "RowMoveManager":RowMoveManager
+ }
+ });
+
+ function RowMoveManager() {
+ var _grid;
+ var _canvas;
+ var _dragging;
+ var _self = this;
+
+ function init(grid) {
+ _grid = grid;
+ _canvas = _grid.getCanvasNode();
+ _grid.onDragInit.subscribe(handleDragInit);
+ _grid.onDragStart.subscribe(handleDragStart);
+ _grid.onDrag.subscribe(handleDrag);
+ _grid.onDragEnd.subscribe(handleDragEnd);
+ }
- function RowMoveManager() {
- var _grid;
- var _canvas;
- var _dragging;
- var _self = this;
-
- function init(grid) {
- _grid = grid;
- _canvas = _grid.getCanvasNode();
- _grid.onDragInit.subscribe(handleDragInit);
- _grid.onDragStart.subscribe(handleDragStart);
- _grid.onDrag.subscribe(handleDrag);
- _grid.onDragEnd.subscribe(handleDragEnd);
- }
+ function destroy() {
+ _grid.onDragInit.unsubscribe(handleDragInit);
+ _grid.onDragStart.unsubscribe(handleDragStart);
+ _grid.onDrag.unsubscribe(handleDrag);
+ _grid.onDragEnd.unsubscribe(handleDragEnd);
+ }
- function destroy() {
- _grid.onDragInit.unsubscribe(handleDragInit);
- _grid.onDragStart.unsubscribe(handleDragStart);
- _grid.onDrag.unsubscribe(handleDrag);
- _grid.onDragEnd.unsubscribe(handleDragEnd);
- }
+ function handleDragInit(e, dd) {
+ // prevent the grid from cancelling drag'n'drop by default
+ e.stopImmediatePropagation();
+ }
- function handleDragInit(e, dd) {
- // prevent the grid from cancelling drag'n'drop by default
- e.stopImmediatePropagation();
- }
+ function handleDragStart(e, dd) {
+ var cell = _grid.getCellFromEvent(e);
+ if (_grid.getEditorLock().isActive() || !/move|selectAndMove/.test(_grid.getColumns()[cell.cell].behavior)) {
+ return false;
+ }
- function handleDragStart(e,dd) {
- var cell = _grid.getCellFromEvent(e);
- if (_grid.getEditorLock().isActive() || !/move|selectAndMove/.test(_grid.getColumns()[cell.cell].behavior)) {
- return false;
- }
+ _dragging = true;
+ e.stopImmediatePropagation();
- _dragging = true;
- e.stopImmediatePropagation();
+ var selectedRows = _grid.getSelectedRows();
- var selectedRows = _grid.getSelectedRows();
+ if (selectedRows.length == 0 || $.inArray(cell.row, selectedRows) == -1) {
+ selectedRows = [cell.row];
+ _grid.setSelectedRows(selectedRows);
+ }
- if (selectedRows.length == 0 || $.inArray(cell.row, selectedRows) == -1) {
- selectedRows = [cell.row];
- _grid.setSelectedRows(selectedRows);
- }
+ var rowHeight = _grid.getOptions().rowHeight;
- var rowHeight = _grid.getOptions().rowHeight;
+ dd.selectedRows = selectedRows;
- dd.selectedRows = selectedRows;
+ dd.selectionProxy = $("<div class='slick-reorder-proxy'/>")
+ .css("position", "absolute")
+ .css("zIndex", "99999")
+ .css("width", $(_canvas).innerWidth())
+ .css("height", rowHeight * selectedRows.length)
+ .appendTo(_canvas);
- dd.selectionProxy = $("<div class='slick-reorder-proxy'/>")
- .css("position", "absolute")
- .css("zIndex", "99999")
- .css("width", $(_canvas).innerWidth())
- .css("height", rowHeight*selectedRows.length)
- .appendTo(_canvas);
+ dd.guide = $("<div class='slick-reorder-guide'/>")
+ .css("position", "absolute")
+ .css("zIndex", "99998")
+ .css("width", $(_canvas).innerWidth())
+ .css("top", -1000)
+ .appendTo(_canvas);
- dd.guide = $("<div class='slick-reorder-guide'/>")
- .css("position", "absolute")
- .css("zIndex", "99998")
- .css("width", $(_canvas).innerWidth())
- .css("top", -1000)
- .appendTo(_canvas);
+ dd.insertBefore = -1;
- dd.insertBefore = -1;
+ return $("<div></div>").appendTo(_canvas);
+ }
- return $("<div></div>").appendTo(_canvas);
+ function handleDrag(e, dd) {
+ if (!_dragging) {
+ return;
+ }
+
+ e.stopImmediatePropagation();
+
+ var top = e.pageY - $(_canvas).offset().top;
+ dd.selectionProxy.css("top", top - 5);
+
+ var insertBefore = Math.max(0, Math.min(Math.round(top / _grid.getOptions().rowHeight), _grid.getDataLength()));
+ if (insertBefore !== dd.insertBefore) {
+ var eventData = {
+ "rows":dd.selectedRows,
+ "insertBefore":insertBefore
+ };
+
+ if (_self.onBeforeMoveRows.notify(eventData) === false) {
+ dd.guide.css("top", -1000);
+ dd.canMove = false;
+ } else {
+ dd.guide.css("top", insertBefore * _grid.getOptions().rowHeight);
+ dd.canMove = true;
}
- function handleDrag(e,dd) {
- if (!_dragging) {
- return;
- }
-
- e.stopImmediatePropagation();
-
- var top = e.pageY - $(_canvas).offset().top;
- dd.selectionProxy.css("top",top-5);
-
- var insertBefore = Math.max(0,Math.min(Math.round(top/_grid.getOptions().rowHeight),_grid.getDataLength()));
- if (insertBefore !== dd.insertBefore) {
- var eventData = {
- "rows": dd.selectedRows,
- "insertBefore": insertBefore
- };
-
- if (_self.onBeforeMoveRows.notify(eventData) === false) {
- dd.guide.css("top", -1000);
- dd.canMove = false;
- }
- else {
- dd.guide.css("top",insertBefore*_grid.getOptions().rowHeight);
- dd.canMove = true;
- }
-
- dd.insertBefore = insertBefore;
- }
- }
+ dd.insertBefore = insertBefore;
+ }
+ }
- function handleDragEnd(e,dd) {
- if (!_dragging) {
- return;
- }
- _dragging = false;
- e.stopImmediatePropagation();
-
- dd.guide.remove();
- dd.selectionProxy.remove();
-
- if (dd.canMove) {
- var eventData = {
- "rows": dd.selectedRows,
- "insertBefore": dd.insertBefore
- };
- // TODO: _grid.remapCellCssClasses ?
- _self.onMoveRows.notify(eventData);
- }
- }
+ function handleDragEnd(e, dd) {
+ if (!_dragging) {
+ return;
+ }
+ _dragging = false;
+ e.stopImmediatePropagation();
+
+ dd.guide.remove();
+ dd.selectionProxy.remove();
+
+ if (dd.canMove) {
+ var eventData = {
+ "rows":dd.selectedRows,
+ "insertBefore":dd.insertBefore
+ };
+ // TODO: _grid.remapCellCssClasses ?
+ _self.onMoveRows.notify(eventData);
+ }
+ }
- $.extend(this, {
- "onBeforeMoveRows": new Slick.Event(),
- "onMoveRows": new Slick.Event(),
+ $.extend(this, {
+ "onBeforeMoveRows":new Slick.Event(),
+ "onMoveRows":new Slick.Event(),
- "init": init,
- "destroy": destroy
- });
- }
+ "init":init,
+ "destroy":destroy
+ });
+ }
})(jQuery); \ No newline at end of file
diff --git a/plugins/slick.rowselectionmodel.js b/plugins/slick.rowselectionmodel.js
index a539939..e675c83 100644
--- a/plugins/slick.rowselectionmodel.js
+++ b/plugins/slick.rowselectionmodel.js
@@ -1,186 +1,187 @@
-(function($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "RowSelectionModel": RowSelectionModel
- }
- });
+(function ($) {
+ // register namespace
+ $.extend(true, window, {
+ "Slick":{
+ "RowSelectionModel":RowSelectionModel
+ }
+ });
+
+ function RowSelectionModel(options) {
+ var _grid;
+ var _ranges = [];
+ var _self = this;
+ var _handler = new Slick.EventHandler();
+ var _inHandler;
+ var _options;
+ var _defaults = {
+ selectActiveRow:true
+ };
+
+ function init(grid) {
+ _options = $.extend(true, {}, _defaults, options);
+ _grid = grid;
+ _handler.subscribe(_grid.onActiveCellChanged,
+ wrapHandler(handleActiveCellChange));
+ _handler.subscribe(_grid.onKeyDown,
+ wrapHandler(handleKeyDown));
+ _handler.subscribe(_grid.onClick,
+ wrapHandler(handleClick));
+ }
- function RowSelectionModel(options) {
- var _grid;
- var _ranges = [];
- var _self = this;
- var _handler = new Slick.EventHandler();
- var _inHandler;
- var _options;
- var _defaults = {
- selectActiveRow: true
- };
-
- function init(grid) {
- _options = $.extend(true, {}, _defaults, options);
- _grid = grid;
- _handler.subscribe(_grid.onActiveCellChanged,
- wrapHandler(handleActiveCellChange));
- _handler.subscribe(_grid.onKeyDown,
- wrapHandler(handleKeyDown));
- _handler.subscribe(_grid.onClick,
- wrapHandler(handleClick));
- }
+ function destroy() {
+ _handler.unsubscribeAll();
+ }
- function destroy() {
- _handler.unsubscribeAll();
+ function wrapHandler(handler) {
+ return function () {
+ if (!_inHandler) {
+ _inHandler = true;
+ handler.apply(this, arguments);
+ _inHandler = false;
}
+ };
+ }
- function wrapHandler(handler) {
- return function() {
- if (!_inHandler) {
- _inHandler = true;
- handler.apply(this, arguments);
- _inHandler = false;
- }
- };
+ 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 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 = _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 rowsToRanges(rows) {
- var ranges = [];
- var lastCell = _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 getRowsRange(from, to) {
+ var i, rows = [];
+ for (i = from; i <= to; i++) {
+ rows.push(i);
+ }
+ for (i = to; i < from; i++) {
+ rows.push(i);
+ }
+ return rows;
+ }
- function getRowsRange(from,to) {
- var i, rows = [];
- for (i = from; i <= to; i++) {
- rows.push(i);
- }
- for (i = to; i < from; i++) {
- rows.push(i);
- }
- return rows;
- }
+ function getSelectedRows() {
+ return rangesToRows(_ranges);
+ }
- function getSelectedRows() {
- return rangesToRows(_ranges);
- }
+ function setSelectedRows(rows) {
+ setSelectedRanges(rowsToRanges(rows));
+ }
- function setSelectedRows(rows) {
- setSelectedRanges(rowsToRanges(rows));
- }
+ function setSelectedRanges(ranges) {
+ _ranges = ranges;
+ _self.onSelectedRangesChanged.notify(_ranges);
+ }
- function setSelectedRanges(ranges) {
- _ranges = ranges;
- _self.onSelectedRangesChanged.notify(_ranges);
- }
+ function getSelectedRanges() {
+ return _ranges;
+ }
- function getSelectedRanges() {
- return _ranges;
- }
+ function handleActiveCellChange(e, data) {
+ if (_options.selectActiveRow) {
+ setSelectedRanges([new Slick.Range(data.row, 0, data.row, _grid.getColumns().length - 1)]);
+ }
+ }
- function handleActiveCellChange(e, data) {
- if (_options.selectActiveRow) {
- setSelectedRanges([new Slick.Range(data.row, 0, data.row, _grid.getColumns().length - 1)]);
- }
+ function handleKeyDown(e) {
+ var activeRow = _grid.getActiveCell();
+ if (activeRow && e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey && (e.which == 38 || e.which == 40)) {
+ var selectedRows = getSelectedRows();
+ selectedRows.sort(function (x, y) {
+ return x - y
+ });
+
+ if (!selectedRows.length) {
+ selectedRows = [activeRow.row];
}
- function handleKeyDown(e) {
- var activeRow = _grid.getActiveCell();
- if (activeRow && e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey && (e.which == 38 || e.which == 40)) {
- var selectedRows = getSelectedRows();
- selectedRows.sort(function(x,y) { return x-y });
-
- if (!selectedRows.length) {
- selectedRows = [activeRow.row];
- }
-
- var top = selectedRows[0];
- var bottom = selectedRows[selectedRows.length - 1];
- var active;
-
- if (e.which == 40) {
- active = activeRow.row < bottom || top == bottom ? ++bottom : ++top;
- }
- else {
- active = activeRow.row < bottom ? --bottom : --top;
- }
-
- if (active >= 0 && active < _grid.getDataLength()) {
- _grid.scrollRowIntoView(active);
- _ranges = rowsToRanges(getRowsRange(top,bottom));
- setSelectedRanges(_ranges);
- }
-
- e.preventDefault();
- e.stopPropagation();
- }
+ var top = selectedRows[0];
+ var bottom = selectedRows[selectedRows.length - 1];
+ var active;
+
+ if (e.which == 40) {
+ active = activeRow.row < bottom || top == bottom ? ++bottom : ++top;
+ } else {
+ active = activeRow.row < bottom ? --bottom : --top;
}
- function handleClick(e) {
- var cell = _grid.getCellFromEvent(e);
- if (!cell || !_grid.canCellBeActive(cell.row, cell.cell)) {
- return false;
- }
+ if (active >= 0 && active < _grid.getDataLength()) {
+ _grid.scrollRowIntoView(active);
+ _ranges = rowsToRanges(getRowsRange(top, bottom));
+ setSelectedRanges(_ranges);
+ }
- var selection = rangesToRows(_ranges);
- var idx = $.inArray(cell.row, selection);
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ }
- if (!e.ctrlKey && !e.shiftKey && !e.metaKey) {
- return false;
- }
- else if (_grid.getOptions().multiSelect) {
- if (idx === -1 && (e.ctrlKey || e.metaKey)) {
- selection.push(cell.row);
- _grid.setActiveCell(cell.row, cell.cell);
- }
- else if (idx !== -1 && (e.ctrlKey || e.metaKey)) {
- selection = $.grep(selection, function(o, i) { return (o !== cell.row); });
- _grid.setActiveCell(cell.row, cell.cell);
- }
- else if (selection.length && e.shiftKey) {
- var last = selection.pop();
- var from = Math.min(cell.row, last);
- var to = Math.max(cell.row, last);
- selection = [];
- for (var i = from; i <= to; i++) {
- if (i !== last) {
- selection.push(i);
- }
- }
- selection.push(last);
- _grid.setActiveCell(cell.row, cell.cell);
- }
+ function handleClick(e) {
+ var cell = _grid.getCellFromEvent(e);
+ if (!cell || !_grid.canCellBeActive(cell.row, cell.cell)) {
+ return false;
+ }
+
+ var selection = rangesToRows(_ranges);
+ var idx = $.inArray(cell.row, selection);
+
+ if (!e.ctrlKey && !e.shiftKey && !e.metaKey) {
+ return false;
+ }
+ else if (_grid.getOptions().multiSelect) {
+ if (idx === -1 && (e.ctrlKey || e.metaKey)) {
+ selection.push(cell.row);
+ _grid.setActiveCell(cell.row, cell.cell);
+ } else if (idx !== -1 && (e.ctrlKey || e.metaKey)) {
+ selection = $.grep(selection, function (o, i) {
+ return (o !== cell.row);
+ });
+ _grid.setActiveCell(cell.row, cell.cell);
+ } else if (selection.length && e.shiftKey) {
+ var last = selection.pop();
+ var from = Math.min(cell.row, last);
+ var to = Math.max(cell.row, last);
+ selection = [];
+ for (var i = from; i <= to; i++) {
+ if (i !== last) {
+ selection.push(i);
}
+ }
+ selection.push(last);
+ _grid.setActiveCell(cell.row, cell.cell);
+ }
+ }
- _ranges = rowsToRanges(selection);
- setSelectedRanges(_ranges);
- e.stopImmediatePropagation();
+ _ranges = rowsToRanges(selection);
+ setSelectedRanges(_ranges);
+ e.stopImmediatePropagation();
- return true;
- }
+ return true;
+ }
- $.extend(this, {
- "getSelectedRows": getSelectedRows,
- "setSelectedRows": setSelectedRows,
+ $.extend(this, {
+ "getSelectedRows":getSelectedRows,
+ "setSelectedRows":setSelectedRows,
- "getSelectedRanges": getSelectedRanges,
- "setSelectedRanges": setSelectedRanges,
+ "getSelectedRanges":getSelectedRanges,
+ "setSelectedRanges":setSelectedRanges,
- "init": init,
- "destroy": destroy,
+ "init":init,
+ "destroy":destroy,
- "onSelectedRangesChanged": new Slick.Event()
- });
- }
+ "onSelectedRangesChanged":new Slick.Event()
+ });
+ }
})(jQuery); \ No newline at end of file
diff --git a/slick.core.js b/slick.core.js
index 8911560..b84079a 100644
--- a/slick.core.js
+++ b/slick.core.js
@@ -4,421 +4,421 @@
* @namespace Slick
*/
-(function($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "Event": Event,
- "EventData": EventData,
- "EventHandler": EventHandler,
- "Range": Range,
- "NonDataRow": NonDataItem,
- "Group": Group,
- "GroupTotals": GroupTotals,
- "EditorLock": EditorLock,
-
- /***
- * A global singleton editor lock.
- * @class GlobalEditorLock
- * @static
- * @constructor
- */
- "GlobalEditorLock": new EditorLock()
- }
- });
+(function ($) {
+ // register namespace
+ $.extend(true, window, {
+ "Slick":{
+ "Event":Event,
+ "EventData":EventData,
+ "EventHandler":EventHandler,
+ "Range":Range,
+ "NonDataRow":NonDataItem,
+ "Group":Group,
+ "GroupTotals":GroupTotals,
+ "EditorLock":EditorLock,
+
+ /***
+ * A global singleton editor lock.
+ * @class GlobalEditorLock
+ * @static
+ * @constructor
+ */
+ "GlobalEditorLock":new EditorLock()
+ }
+ });
+
+ /***
+ * An event object for passing data to event handlers and letting them control propagation.
+ * <p>This is pretty much identical to how W3C and jQuery implement events.</p>
+ * @class EventData
+ * @constructor
+ */
+ function EventData() {
+ var isPropagationStopped = false;
+ var isImmediatePropagationStopped = false;
/***
- * An event object for passing data to event handlers and letting them control propagation.
- * <p>This is pretty much identical to how W3C and jQuery implement events.</p>
- * @class EventData
- * @constructor
+ * Stops event from propagating up the DOM tree.
+ * @method stopPropagation
*/
- function EventData() {
- var isPropagationStopped = false;
- var isImmediatePropagationStopped = false;
-
- /***
- * Stops event from propagating up the DOM tree.
- * @method stopPropagation
- */
- this.stopPropagation = function() {
- isPropagationStopped = true;
- };
-
- /***
- * Returns whether stopPropagation was called on this event object.
- * @method isPropagationStopped
- * @return {Boolean}
- */
- this.isPropagationStopped = function() {
- return isPropagationStopped;
- };
-
- /***
- * Prevents the rest of the handlers from being executed.
- * @method stopImmediatePropagation
- */
- this.stopImmediatePropagation = function() {
- isImmediatePropagationStopped = true;
- };
-
- /***
- * Returns whether stopImmediatePropagation was called on this event object.\
- * @method isImmediatePropagationStopped
- * @return {Boolean}
- */
- this.isImmediatePropagationStopped = function() {
- return isImmediatePropagationStopped;
- }
- }
+ this.stopPropagation = function () {
+ isPropagationStopped = true;
+ };
/***
- * A simple publisher-subscriber implementation.
- * @class Event
- * @constructor
+ * Returns whether stopPropagation was called on this event object.
+ * @method isPropagationStopped
+ * @return {Boolean}
*/
- function Event() {
- var handlers = [];
-
- /***
- * Adds an event handler to be called when the event is fired.
- * <p>Event handler will receive two arguments - an <code>EventData</code> and the <code>data</code>
- * object the event was fired with.<p>
- * @method subscribe
- * @param fn {Function} Event handler.
- */
- this.subscribe = function(fn) {
- handlers.push(fn);
- };
-
- /***
- * Removes an event handler added with <code>subscribe(fn)</code>.
- * @method unsubscribe
- * @param fn {Function} Event handler to be removed.
- */
- this.unsubscribe = function(fn) {
- for (var i = handlers.length - 1; i >= 0; i--) {
- if (handlers[i] === fn) {
- handlers.splice(i, 1);
- }
- }
- };
-
- /***
- * Fires an event notifying all subscribers.
- * @method notify
- * @param args {Object} Additional data object to be passed to all handlers.
- * @param e {EventData}
- * Optional.
- * An <code>EventData</code> object to be passed to all handlers.
- * For DOM events, an existing W3C/jQuery event object can be passed in.
- * @param scope {Object}
- * Optional.
- * The scope ("this") within which the handler will be executed.
- * If not specified, the scope will be set to the <code>Event</code> instance.
- */
- this.notify = function(args, e, scope) {
- e = e || new EventData();
- scope = scope || this;
-
- var returnValue;
- for (var i = 0; i < handlers.length && !(e.isPropagationStopped() || e.isImmediatePropagationStopped()); i++) {
- returnValue = handlers[i].call(scope, e, args);
- }
-
- return returnValue;
- };
- }
+ this.isPropagationStopped = function () {
+ return isPropagationStopped;
+ };
- function EventHandler() {
- var handlers = [];
-
- this.subscribe = function(event, handler) {
- handlers.push({
- event: event,
- handler: handler
- });
- event.subscribe(handler);
- };
-
- this.unsubscribe = function(event, handler) {
- var i = handlers.length;
- while (i--) {
- if (handlers[i].event === event &&
- handlers[i].handler === handler) {
- handlers.splice(i, 1);
- event.unsubscribe(handler);
- return;
- }
- }
- };
-
- this.unsubscribeAll = function() {
- var i = handlers.length;
- while (i--) {
- handlers[i].event.unsubscribe(handlers[i].handler);
- }
- handlers = [];
- }
+ /***
+ * Prevents the rest of the handlers from being executed.
+ * @method stopImmediatePropagation
+ */
+ this.stopImmediatePropagation = function () {
+ isImmediatePropagationStopped = true;
+ };
+
+ /***
+ * Returns whether stopImmediatePropagation was called on this event object.\
+ * @method isImmediatePropagationStopped
+ * @return {Boolean}
+ */
+ this.isImmediatePropagationStopped = function () {
+ return isImmediatePropagationStopped;
}
+ }
+
+ /***
+ * A simple publisher-subscriber implementation.
+ * @class Event
+ * @constructor
+ */
+ function Event() {
+ var handlers = [];
/***
- * A structure containing a range of cells.
- * @class Range
- * @constructor
- * @param fromRow {Integer} Starting row.
- * @param fromCell {Integer} Starting cell.
- * @param toRow {Integer} Optional. Ending row. Defaults to <code>fromRow</code>.
- * @param toCell {Integer} Optional. Ending cell. Defaults to <code>fromCell</code>.
+ * Adds an event handler to be called when the event is fired.
+ * <p>Event handler will receive two arguments - an <code>EventData</code> and the <code>data</code>
+ * object the event was fired with.<p>
+ * @method subscribe
+ * @param fn {Function} Event handler.
*/
- function Range(fromRow, fromCell, toRow, toCell) {
- if (toRow === undefined && toCell === undefined) {
- toRow = fromRow;
- toCell = fromCell;
+ this.subscribe = function (fn) {
+ handlers.push(fn);
+ };
+
+ /***
+ * Removes an event handler added with <code>subscribe(fn)</code>.
+ * @method unsubscribe
+ * @param fn {Function} Event handler to be removed.
+ */
+ this.unsubscribe = function (fn) {
+ for (var i = handlers.length - 1; i >= 0; i--) {
+ if (handlers[i] === fn) {
+ handlers.splice(i, 1);
}
+ }
+ };
+
+ /***
+ * Fires an event notifying all subscribers.
+ * @method notify
+ * @param args {Object} Additional data object to be passed to all handlers.
+ * @param e {EventData}
+ * Optional.
+ * An <code>EventData</code> object to be passed to all handlers.
+ * For DOM events, an existing W3C/jQuery event object can be passed in.
+ * @param scope {Object}
+ * Optional.
+ * The scope ("this") within which the handler will be executed.
+ * If not specified, the scope will be set to the <code>Event</code> instance.
+ */
+ this.notify = function (args, e, scope) {
+ e = e || new EventData();
+ scope = scope || this;
+
+ var returnValue;
+ for (var i = 0; i < handlers.length && !(e.isPropagationStopped() || e.isImmediatePropagationStopped()); i++) {
+ returnValue = handlers[i].call(scope, e, args);
+ }
+
+ return returnValue;
+ };
+ }
+
+ function EventHandler() {
+ var handlers = [];
- /***
- * @property fromRow
- * @type {Integer}
- */
- this.fromRow = Math.min(fromRow, toRow);
-
- /***
- * @property fromCell
- * @type {Integer}
- */
- this.fromCell = Math.min(fromCell, toCell);
-
- /***
- * @property toRow
- * @type {Integer}
- */
- this.toRow = Math.max(fromRow, toRow);
-
- /***
- * @property toCell
- * @type {Integer}
- */
- this.toCell = Math.max(fromCell, toCell);
-
- /***
- * Returns whether a range represents a single row.
- * @method isSingleRow
- * @return {Boolean}
- */
- this.isSingleRow = function() {
- return this.fromRow == this.toRow;
- };
-
- /***
- * Returns whether a range represents a single cell.
- * @method isSingleCell
- * @return {Boolean}
- */
- this.isSingleCell = function() {
- return this.fromRow == this.toRow && this.fromCell == this.toCell;
- };
-
- /***
- * Returns whether a range contains a given cell.
- * @method contains
- * @param row {Integer}
- * @param cell {Integer}
- * @return {Boolean}
- */
- this.contains = function(row, cell) {
- return row >= this.fromRow && row <= this.toRow &&
- cell >= this.fromCell && cell <= this.toCell;
- };
-
- /***
- * Returns a readable representation of a range.
- * @method toString
- * @return {String}
- */
- this.toString = function() {
- if (this.isSingleCell()) {
- return "(" + this.fromRow + ":" + this.fromCell + ")";
- }
- else {
- return "(" + this.fromRow + ":" + this.fromCell + " - " + this.toRow + ":" + this.toCell + ")";
- }
+ this.subscribe = function (event, handler) {
+ handlers.push({
+ event:event,
+ handler:handler
+ });
+ event.subscribe(handler);
+ };
+
+ this.unsubscribe = function (event, handler) {
+ var i = handlers.length;
+ while (i--) {
+ if (handlers[i].event === event &&
+ handlers[i].handler === handler) {
+ handlers.splice(i, 1);
+ event.unsubscribe(handler);
+ return;
}
+ }
+ };
+
+ this.unsubscribeAll = function () {
+ var i = handlers.length;
+ while (i--) {
+ handlers[i].event.unsubscribe(handlers[i].handler);
+ }
+ handlers = [];
+ }
+ }
+
+ /***
+ * A structure containing a range of cells.
+ * @class Range
+ * @constructor
+ * @param fromRow {Integer} Starting row.
+ * @param fromCell {Integer} Starting cell.
+ * @param toRow {Integer} Optional. Ending row. Defaults to <code>fromRow</code>.
+ * @param toCell {Integer} Optional. Ending cell. Defaults to <code>fromCell</code>.
+ */
+ function Range(fromRow, fromCell, toRow, toCell) {
+ if (toRow === undefined && toCell === undefined) {
+ toRow = fromRow;
+ toCell = fromCell;
}
+ /***
+ * @property fromRow
+ * @type {Integer}
+ */
+ this.fromRow = Math.min(fromRow, toRow);
/***
- * A base class that all special / non-data rows (like Group and GroupTotals) derive from.
- * @class NonDataItem
- * @constructor
+ * @property fromCell
+ * @type {Integer}
*/
- function NonDataItem() {
- this.__nonDataRow = true;
- }
+ this.fromCell = Math.min(fromCell, toCell);
+ /***
+ * @property toRow
+ * @type {Integer}
+ */
+ this.toRow = Math.max(fromRow, toRow);
/***
- * Information about a group of rows.
- * @class Group
- * @extends Slick.NonDataItem
- * @constructor
+ * @property toCell
+ * @type {Integer}
*/
- function Group() {
- this.__group = true;
- this.__updated = false;
-
- /***
- * Number of rows in the group.
- * @property count
- * @type {Integer}
- */
- this.count = 0;
-
- /***
- * Grouping value.
- * @property value
- * @type {Object}
- */
- this.value = null;
-
- /***
- * Formatted display value of the group.
- * @property title
- * @type {String}
- */
- this.title = null;
-
- /***
- * Whether a group is collapsed.
- * @property collapsed
- * @type {Boolean}
- */
- this.collapsed = false;
-
- /***
- * GroupTotals, if any.
- * @property totals
- * @type {GroupTotals}
- */
- this.totals = null;
- }
+ this.toCell = Math.max(fromCell, toCell);
- Group.prototype = new NonDataItem();
+ /***
+ * Returns whether a range represents a single row.
+ * @method isSingleRow
+ * @return {Boolean}
+ */
+ this.isSingleRow = function () {
+ return this.fromRow == this.toRow;
+ };
/***
- * Compares two Group instances.
- * @method equals
+ * Returns whether a range represents a single cell.
+ * @method isSingleCell
* @return {Boolean}
- * @param group {Group} Group instance to compare to.
*/
- Group.prototype.equals = function(group) {
- return this.value === group.value &&
- this.count === group.count &&
- this.collapsed === group.collapsed;
+ this.isSingleCell = function () {
+ return this.fromRow == this.toRow && this.fromCell == this.toCell;
};
/***
- * Information about group totals.
- * An instance of GroupTotals will be created for each totals row and passed to the aggregators
- * so that they can store arbitrary data in it. That data can later be accessed by group totals
- * formatters during the display.
- * @class GroupTotals
- * @extends Slick.NonDataItem
- * @constructor
+ * Returns whether a range contains a given cell.
+ * @method contains
+ * @param row {Integer}
+ * @param cell {Integer}
+ * @return {Boolean}
*/
- function GroupTotals() {
- this.__groupTotals = true;
-
- /***
- * Parent Group.
- * @param group
- * @type {Group}
- */
- this.group = null;
+ this.contains = function (row, cell) {
+ return row >= this.fromRow && row <= this.toRow &&
+ cell >= this.fromCell && cell <= this.toCell;
+ };
+
+ /***
+ * Returns a readable representation of a range.
+ * @method toString
+ * @return {String}
+ */
+ this.toString = function () {
+ if (this.isSingleCell()) {
+ return "(" + this.fromRow + ":" + this.fromCell + ")";
+ }
+ else {
+ return "(" + this.fromRow + ":" + this.fromCell + " - " + this.toRow + ":" + this.toCell + ")";
+ }
}
+ }
+
+
+ /***
+ * A base class that all special / non-data rows (like Group and GroupTotals) derive from.
+ * @class NonDataItem
+ * @constructor
+ */
+ function NonDataItem() {
+ this.__nonDataRow = true;
+ }
+
- GroupTotals.prototype = new NonDataItem();
+ /***
+ * Information about a group of rows.
+ * @class Group
+ * @extends Slick.NonDataItem
+ * @constructor
+ */
+ function Group() {
+ this.__group = true;
+ this.__updated = false;
/***
- * A locking helper to track the active edit controller and ensure that only a single controller
- * can be active at a time. This prevents a whole class of state and validation synchronization
- * issues. An edit controller (such as SlickGrid) can query if an active edit is in progress
- * and attempt a commit or cancel before proceeding.
- * @class EditorLock
- * @constructor
+ * Number of rows in the group.
+ * @property count
+ * @type {Integer}
*/
- function EditorLock() {
- var activeEditController = null;
-
- /***
- * Returns true if a specified edit controller is active (has the edit lock).
- * If the parameter is not specified, returns true if any edit controller is active.
- * @method isActive
- * @param editController {EditController}
- * @return {Boolean}
- */
- this.isActive = function(editController) {
- return (editController ? activeEditController === editController : activeEditController !== null);
- };
-
- /***
- * Sets the specified edit controller as the active edit controller (acquire edit lock).
- * If another edit controller is already active, and exception will be thrown.
- * @method activate
- * @param editController {EditController} edit controller acquiring the lock
- */
- this.activate = function(editController) {
- if (editController === activeEditController) { // already activated?
- return;
- }
- if (activeEditController !== null) {
- throw "SlickGrid.EditorLock.activate: an editController is still active, can't activate another editController";
- }
- if (!editController.commitCurrentEdit) {
- throw "SlickGrid.EditorLock.activate: editController must implement .commitCurrentEdit()";
- }
- if (!editController.cancelCurrentEdit) {
- throw "SlickGrid.EditorLock.activate: editController must implement .cancelCurrentEdit()";
- }
- activeEditController = editController;
- };
-
- /***
- * Unsets the specified edit controller as the active edit controller (release edit lock).
- * If the specified edit controller is not the active one, an exception will be thrown.
- * @method deactivate
- * @param editController {EditController} edit controller releasing the lock
- */
- this.deactivate = function(editController) {
- if (activeEditController !== editController) {
- throw "SlickGrid.EditorLock.deactivate: specified editController is not the currently active one";
- }
- activeEditController = null;
- };
-
- /***
- * Attempts to commit the current edit by calling "commitCurrentEdit" method on the active edit
- * controller and returns whether the commit attempt was successful (commit may fail due to validation
- * errors, etc.). Edit controller's "commitCurrentEdit" must return true if the commit has succeeded
- * and false otherwise. If no edit controller is active, returns true.
- * @method commitCurrentEdit
- * @return {Boolean}
- */
- this.commitCurrentEdit = function() {
- return (activeEditController ? activeEditController.commitCurrentEdit() : true);
- };
-
- /***
- * Attempts to cancel the current edit by calling "cancelCurrentEdit" method on the active edit
- * controller and returns whether the edit was successfully cancelled. If no edit controller is
- * active, returns true.
- * @method cancelCurrentEdit
- * @return {Boolean}
- */
- this.cancelCurrentEdit = function cancelCurrentEdit() {
- return (activeEditController ? activeEditController.cancelCurrentEdit() : true);
- };
- }
+ this.count = 0;
+
+ /***
+ * Grouping value.
+ * @property value
+ * @type {Object}
+ */
+ this.value = null;
+
+ /***
+ * Formatted display value of the group.
+ * @property title
+ * @type {String}
+ */
+ this.title = null;
+
+ /***
+ * Whether a group is collapsed.
+ * @property collapsed
+ * @type {Boolean}
+ */
+ this.collapsed = false;
+
+ /***
+ * GroupTotals, if any.
+ * @property totals
+ * @type {GroupTotals}
+ */
+ this.totals = null;
+ }
+
+ Group.prototype = new NonDataItem();
+
+ /***
+ * Compares two Group instances.
+ * @method equals
+ * @return {Boolean}
+ * @param group {Group} Group instance to compare to.
+ */
+ Group.prototype.equals = function (group) {
+ return this.value === group.value &&
+ this.count === group.count &&
+ this.collapsed === group.collapsed;
+ };
+
+ /***
+ * Information about group totals.
+ * An instance of GroupTotals will be created for each totals row and passed to the aggregators
+ * so that they can store arbitrary data in it. That data can later be accessed by group totals
+ * formatters during the display.
+ * @class GroupTotals
+ * @extends Slick.NonDataItem
+ * @constructor
+ */
+ function GroupTotals() {
+ this.__groupTotals = true;
+
+ /***
+ * Parent Group.
+ * @param group
+ * @type {Group}
+ */
+ this.group = null;
+ }
+
+ GroupTotals.prototype = new NonDataItem();
+
+ /***
+ * A locking helper to track the active edit controller and ensure that only a single controller
+ * can be active at a time. This prevents a whole class of state and validation synchronization
+ * issues. An edit controller (such as SlickGrid) can query if an active edit is in progress
+ * and attempt a commit or cancel before proceeding.
+ * @class EditorLock
+ * @constructor
+ */
+ function EditorLock() {
+ var activeEditController = null;
+
+ /***
+ * Returns true if a specified edit controller is active (has the edit lock).
+ * If the parameter is not specified, returns true if any edit controller is active.
+ * @method isActive
+ * @param editController {EditController}
+ * @return {Boolean}
+ */
+ this.isActive = function (editController) {
+ return (editController ? activeEditController === editController : activeEditController !== null);
+ };
+
+ /***
+ * Sets the specified edit controller as the active edit controller (acquire edit lock).
+ * If another edit controller is already active, and exception will be thrown.
+ * @method activate
+ * @param editController {EditController} edit controller acquiring the lock
+ */
+ this.activate = function (editController) {
+ if (editController === activeEditController) { // already activated?
+ return;
+ }
+ if (activeEditController !== null) {
+ throw "SlickGrid.EditorLock.activate: an editController is still active, can't activate another editController";
+ }
+ if (!editController.commitCurrentEdit) {
+ throw "SlickGrid.EditorLock.activate: editController must implement .commitCurrentEdit()";
+ }
+ if (!editController.cancelCurrentEdit) {
+ throw "SlickGrid.EditorLock.activate: editController must implement .cancelCurrentEdit()";
+ }
+ activeEditController = editController;
+ };
+
+ /***
+ * Unsets the specified edit controller as the active edit controller (release edit lock).
+ * If the specified edit controller is not the active one, an exception will be thrown.
+ * @method deactivate
+ * @param editController {EditController} edit controller releasing the lock
+ */
+ this.deactivate = function (editController) {
+ if (activeEditController !== editController) {
+ throw "SlickGrid.EditorLock.deactivate: specified editController is not the currently active one";
+ }
+ activeEditController = null;
+ };
+
+ /***
+ * Attempts to commit the current edit by calling "commitCurrentEdit" method on the active edit
+ * controller and returns whether the commit attempt was successful (commit may fail due to validation
+ * errors, etc.). Edit controller's "commitCurrentEdit" must return true if the commit has succeeded
+ * and false otherwise. If no edit controller is active, returns true.
+ * @method commitCurrentEdit
+ * @return {Boolean}
+ */
+ this.commitCurrentEdit = function () {
+ return (activeEditController ? activeEditController.commitCurrentEdit() : true);
+ };
+
+ /***
+ * Attempts to cancel the current edit by calling "cancelCurrentEdit" method on the active edit
+ * controller and returns whether the edit was successfully cancelled. If no edit controller is
+ * active, returns true.
+ * @method cancelCurrentEdit
+ * @return {Boolean}
+ */
+ this.cancelCurrentEdit = function cancelCurrentEdit() {
+ return (activeEditController ? activeEditController.cancelCurrentEdit() : true);
+ };
+ }
})(jQuery);
diff --git a/slick.dataview.js b/slick.dataview.js
index 9a4605c..790ec94 100644
--- a/slick.dataview.js
+++ b/slick.dataview.js
@@ -1,738 +1,763 @@
-(function($) {
- $.extend(true, window, {
- Slick: {
- Data: {
- DataView: DataView,
- Aggregators: {
- Avg: AvgAggregator,
- Min: MinAggregator,
- Max: MaxAggregator
- }
- }
- }
- });
-
-
- /***
- * A sample Model implementation.
- * Provides a filtered view of the underlying data.
- *
- * Relies on the data item having an "id" property uniquely identifying it.
- */
- function DataView(options) {
- var self = this;
-
- var defaults = {
- groupItemMetadataProvider: null
- };
-
-
- // private
- var idProperty = "id"; // property holding a unique row id
- var items = []; // data by index
- var rows = []; // data by row
- var idxById = {}; // indexes by id
- var rowsById = null; // rows by id; lazy-calculated
- var filter = null; // filter function
- var updated = null; // updated item ids
- var suspend = false; // suspends the recalculation
- var sortAsc = true;
- var fastSortField;
- var sortComparer;
- var refreshHints = {};
- var prevRefreshHints = {};
- var filterArgs;
- var filteredItems = [];
- var compiledFilter;
- var compiledFilterWithCaching;
- var filterCache = [];
-
- // grouping
- var groupingGetter;
- var groupingGetterIsAFn;
- var groupingFormatter;
- var groupingComparer;
- var groups = [];
- var collapsedGroups = {};
- var aggregators;
- var aggregateCollapsed = false;
- var compiledAccumulators;
-
- var pagesize = 0;
- var pagenum = 0;
- var totalRows = 0;
-
- // events
- var onRowCountChanged = new Slick.Event();
- var onRowsChanged = new Slick.Event();
- var onPagingInfoChanged = new Slick.Event();
-
- options = $.extend(true, {}, defaults, options);
-
-
- function beginUpdate() {
- suspend = true;
- }
+(function ($) {
+ $.extend(true, window, {
+ Slick:{
+ Data:{
+ DataView:DataView,
+ Aggregators:{
+ Avg:AvgAggregator,
+ Min:MinAggregator,
+ Max:MaxAggregator
+ }
+ }
+ }
+ });
+
+
+ /***
+ * A sample Model implementation.
+ * Provides a filtered view of the underlying data.
+ *
+ * Relies on the data item having an "id" property uniquely identifying it.
+ */
+ function DataView(options) {
+ var self = this;
+
+ var defaults = {
+ groupItemMetadataProvider:null
+ };
+
+
+ // private
+ var idProperty = "id"; // property holding a unique row id
+ var items = []; // data by index
+ var rows = []; // data by row
+ var idxById = {}; // indexes by id
+ var rowsById = null; // rows by id; lazy-calculated
+ var filter = null; // filter function
+ var updated = null; // updated item ids
+ var suspend = false; // suspends the recalculation
+ var sortAsc = true;
+ var fastSortField;
+ var sortComparer;
+ var refreshHints = {};
+ var prevRefreshHints = {};
+ var filterArgs;
+ var filteredItems = [];
+ var compiledFilter;
+ var compiledFilterWithCaching;
+ var filterCache = [];
+
+ // grouping
+ var groupingGetter;
+ var groupingGetterIsAFn;
+ var groupingFormatter;
+ var groupingComparer;
+ var groups = [];
+ var collapsedGroups = {};
+ var aggregators;
+ var aggregateCollapsed = false;
+ var compiledAccumulators;
+
+ var pagesize = 0;
+ var pagenum = 0;
+ var totalRows = 0;
+
+ // events
+ var onRowCountChanged = new Slick.Event();
+ var onRowsChanged = new Slick.Event();
+ var onPagingInfoChanged = new Slick.Event();
+
+ options = $.extend(true, {}, defaults, options);
+
+
+ function beginUpdate() {
+ suspend = true;
+ }
- function endUpdate() {
- suspend = false;
- refresh();
- }
+ function endUpdate() {
+ suspend = false;
+ refresh();
+ }
- function setRefreshHints(hints){
- refreshHints = hints;
- }
+ function setRefreshHints(hints) {
+ refreshHints = hints;
+ }
- function setFilterArgs(args) {
- filterArgs = args;
- }
+ function setFilterArgs(args) {
+ filterArgs = args;
+ }
- function updateIdxById(startingIndex) {
- startingIndex = startingIndex || 0;
- var id;
- for (var i = startingIndex, l = items.length; i < l; i++) {
- id = items[i][idProperty];
- if (id === undefined) {
- throw "Each data element must implement a unique 'id' property";
- }
- idxById[id] = i;
- }
+ function updateIdxById(startingIndex) {
+ startingIndex = startingIndex || 0;
+ var id;
+ for (var i = startingIndex, l = items.length; i < l; i++) {
+ id = items[i][idProperty];
+ if (id === undefined) {
+ throw "Each data element must implement a unique 'id' property";
}
+ idxById[id] = i;
+ }
+ }
- function ensureIdUniqueness() {
- var id;
- for (var i = 0, l = items.length; i < l; i++) {
- id = items[i][idProperty];
- if (id === undefined || idxById[id] !== i) {
- throw "Each data element must implement a unique 'id' property";
- }
- }
+ function ensureIdUniqueness() {
+ var id;
+ for (var i = 0, l = items.length; i < l; i++) {
+ id = items[i][idProperty];
+ if (id === undefined || idxById[id] !== i) {
+ throw "Each data element must implement a unique 'id' property";
}
+ }
+ }
- function getItems() {
- return items;
- }
+ function getItems() {
+ return items;
+ }
- function setItems(data, objectIdProperty) {
- if (objectIdProperty !== undefined) idProperty = objectIdProperty;
- items = filteredItems = data;
- idxById = {};
- updateIdxById();
- ensureIdUniqueness();
- refresh();
- }
+ function setItems(data, objectIdProperty) {
+ if (objectIdProperty !== undefined) {
+ idProperty = objectIdProperty;
+ }
+ items = filteredItems = data;
+ idxById = {};
+ updateIdxById();
+ ensureIdUniqueness();
+ refresh();
+ }
- function setPagingOptions(args) {
- if (args.pageSize != undefined)
- pagesize = args.pageSize;
+ function setPagingOptions(args) {
+ if (args.pageSize != undefined) {
+ pagesize = args.pageSize;
+ }
- if (args.pageNum != undefined)
- pagenum = Math.min(args.pageNum, Math.ceil(totalRows / pagesize));
+ if (args.pageNum != undefined) {
+ pagenum = Math.min(args.pageNum, Math.ceil(totalRows / pagesize));
+ }
- onPagingInfoChanged.notify(getPagingInfo(), null, self);
+ onPagingInfoChanged.notify(getPagingInfo(), null, self);
- refresh();
- }
+ refresh();
+ }
- function getPagingInfo() {
- return {pageSize:pagesize, pageNum:pagenum, totalRows:totalRows};
- }
+ function getPagingInfo() {
+ return {pageSize:pagesize, pageNum:pagenum, totalRows:totalRows};
+ }
- function sort(comparer, ascending) {
- sortAsc = ascending;
- sortComparer = comparer;
- fastSortField = null;
- if (ascending === false) items.reverse();
- items.sort(comparer);
- if (ascending === false) items.reverse();
- idxById = {};
- updateIdxById();
- refresh();
- }
+ function sort(comparer, ascending) {
+ sortAsc = ascending;
+ sortComparer = comparer;
+ fastSortField = null;
+ if (ascending === false) {
+ items.reverse();
+ }
+ items.sort(comparer);
+ if (ascending === false) {
+ items.reverse();
+ }
+ idxById = {};
+ updateIdxById();
+ refresh();
+ }
- /***
- * Provides a workaround for the extremely slow sorting in IE.
- * Does a [lexicographic] sort on a give column by temporarily overriding Object.prototype.toString
- * to return the value of that field and then doing a native Array.sort().
- */
- function fastSort(field, ascending) {
- sortAsc = ascending;
- fastSortField = field;
- sortComparer = null;
- var oldToString = Object.prototype.toString;
- Object.prototype.toString = (typeof field == "function")?field:function() { return this[field] };
- // an extra reversal for descending sort keeps the sort stable
- // (assuming a stable native sort implementation, which isn't true in some cases)
- if (ascending === false) items.reverse();
- items.sort();
- Object.prototype.toString = oldToString;
- if (ascending === false) items.reverse();
- idxById = {};
- updateIdxById();
- refresh();
- }
+ /***
+ * Provides a workaround for the extremely slow sorting in IE.
+ * Does a [lexicographic] sort on a give column by temporarily overriding Object.prototype.toString
+ * to return the value of that field and then doing a native Array.sort().
+ */
+ function fastSort(field, ascending) {
+ sortAsc = ascending;
+ fastSortField = field;
+ sortComparer = null;
+ var oldToString = Object.prototype.toString;
+ Object.prototype.toString = (typeof field == "function") ? field : function () {
+ return this[field]
+ };
+ // an extra reversal for descending sort keeps the sort stable
+ // (assuming a stable native sort implementation, which isn't true in some cases)
+ if (ascending === false) {
+ items.reverse();
+ }
+ items.sort();
+ Object.prototype.toString = oldToString;
+ if (ascending === false) {
+ items.reverse();
+ }
+ idxById = {};
+ updateIdxById();
+ refresh();
+ }
- function reSort() {
- if (sortComparer) {
- sort(sortComparer, sortAsc);
- }
- else if (fastSortField) {
- fastSort(fastSortField, sortAsc);
- }
- }
+ function reSort() {
+ if (sortComparer) {
+ sort(sortComparer, sortAsc);
+ }
+ else if (fastSortField) {
+ fastSort(fastSortField, sortAsc);
+ }
+ }
- function setFilter(filterFn) {
- filter = filterFn;
- compiledFilter = compileFilter();
- compiledFilterWithCaching = compileFilterWithCaching();
- refresh();
- }
+ function setFilter(filterFn) {
+ filter = filterFn;
+ compiledFilter = compileFilter();
+ compiledFilterWithCaching = compileFilterWithCaching();
+ refresh();
+ }
- function groupBy(valueGetter, valueFormatter, sortComparer) {
- if (!options.groupItemMetadataProvider) {
- options.groupItemMetadataProvider = new Slick.Data.GroupItemMetadataProvider();
- }
-
- groupingGetter = valueGetter;
- groupingGetterIsAFn = typeof groupingGetter === "function";
- groupingFormatter = valueFormatter;
- groupingComparer = sortComparer;
- collapsedGroups = {};
- groups = [];
- refresh();
- }
+ function groupBy(valueGetter, valueFormatter, sortComparer) {
+ if (!options.groupItemMetadataProvider) {
+ options.groupItemMetadataProvider = new Slick.Data.GroupItemMetadataProvider();
+ }
+
+ groupingGetter = valueGetter;
+ groupingGetterIsAFn = typeof groupingGetter === "function";
+ groupingFormatter = valueFormatter;
+ groupingComparer = sortComparer;
+ collapsedGroups = {};
+ groups = [];
+ refresh();
+ }
- function setAggregators(groupAggregators, includeCollapsed) {
- aggregators = groupAggregators;
- aggregateCollapsed = (includeCollapsed !== undefined)
- ? includeCollapsed : aggregateCollapsed;
+ function setAggregators(groupAggregators, includeCollapsed) {
+ aggregators = groupAggregators;
+ aggregateCollapsed = (includeCollapsed !== undefined)
+ ? includeCollapsed : aggregateCollapsed;
- // pre-compile accumulator loops
- compiledAccumulators = [];
- var idx = aggregators.length;
- while (idx--) {
- compiledAccumulators[idx] = compileAccumulatorLoop(aggregators[idx]);
- }
+ // pre-compile accumulator loops
+ compiledAccumulators = [];
+ var idx = aggregators.length;
+ while (idx--) {
+ compiledAccumulators[idx] = compileAccumulatorLoop(aggregators[idx]);
+ }
- refresh();
- }
+ refresh();
+ }
- function getItemByIdx(i) {
- return items[i];
- }
+ function getItemByIdx(i) {
+ return items[i];
+ }
- function getIdxById(id) {
- return idxById[id];
- }
+ function getIdxById(id) {
+ return idxById[id];
+ }
- function ensureRowsByIdCache() {
- if (!rowsById) {
- rowsById = {};
- for (var i = 0, l = rows.length; i < l; i++) {
- rowsById[rows[i][idProperty]] = i;
- }
- }
+ function ensureRowsByIdCache() {
+ if (!rowsById) {
+ rowsById = {};
+ for (var i = 0, l = rows.length; i < l; i++) {
+ rowsById[rows[i][idProperty]] = i;
}
+ }
+ }
- function getRowById(id) {
- ensureRowsByIdCache();
- return rowsById[id];
- }
+ function getRowById(id) {
+ ensureRowsByIdCache();
+ return rowsById[id];
+ }
- function getItemById(id) {
- return items[idxById[id]];
- }
+ function getItemById(id) {
+ return items[idxById[id]];
+ }
- function updateItem(id, item) {
- if (idxById[id] === undefined || id !== item[idProperty])
- throw "Invalid or non-matching id";
- items[idxById[id]] = item;
- if (!updated) updated = {};
- updated[id] = true;
- refresh();
- }
+ function updateItem(id, item) {
+ if (idxById[id] === undefined || id !== item[idProperty]) {
+ throw "Invalid or non-matching id";
+ }
+ items[idxById[id]] = item;
+ if (!updated) {
+ updated = {};
+ }
+ updated[id] = true;
+ refresh();
+ }
- function insertItem(insertBefore, item) {
- items.splice(insertBefore, 0, item);
- updateIdxById(insertBefore);
- refresh();
- }
+ function insertItem(insertBefore, item) {
+ items.splice(insertBefore, 0, item);
+ updateIdxById(insertBefore);
+ refresh();
+ }
- function addItem(item) {
- items.push(item);
- updateIdxById(items.length - 1);
- refresh();
- }
+ function addItem(item) {
+ items.push(item);
+ updateIdxById(items.length - 1);
+ refresh();
+ }
- function deleteItem(id) {
- var idx = idxById[id];
- if (idx === undefined) {
- throw "Invalid id";
- }
- delete idxById[id];
- items.splice(idx, 1);
- updateIdxById(idx);
- refresh();
- }
+ function deleteItem(id) {
+ var idx = idxById[id];
+ if (idx === undefined) {
+ throw "Invalid id";
+ }
+ delete idxById[id];
+ items.splice(idx, 1);
+ updateIdxById(idx);
+ refresh();
+ }
- function getLength() {
- return rows.length;
- }
+ function getLength() {
+ return rows.length;
+ }
- function getItem(i) {
- return rows[i];
- }
+ function getItem(i) {
+ return rows[i];
+ }
- function getItemMetadata(i) {
- var item = rows[i];
- if (item === undefined) {
- return null;
- }
+ function getItemMetadata(i) {
+ var item = rows[i];
+ if (item === undefined) {
+ return null;
+ }
- // overrides for group rows
- if (item.__group) {
- return options.groupItemMetadataProvider.getGroupRowMetadata(item);
- }
+ // overrides for group rows
+ if (item.__group) {
+ return options.groupItemMetadataProvider.getGroupRowMetadata(item);
+ }
- // overrides for totals rows
- if (item.__groupTotals) {
- return options.groupItemMetadataProvider.getTotalsRowMetadata(item);
- }
+ // overrides for totals rows
+ if (item.__groupTotals) {
+ return options.groupItemMetadataProvider.getTotalsRowMetadata(item);
+ }
- return null;
- }
+ return null;
+ }
- function collapseGroup(groupingValue) {
- collapsedGroups[groupingValue] = true;
- refresh();
- }
+ function collapseGroup(groupingValue) {
+ collapsedGroups[groupingValue] = true;
+ refresh();
+ }
- function expandGroup(groupingValue) {
- delete collapsedGroups[groupingValue];
- refresh();
- }
+ function expandGroup(groupingValue) {
+ delete collapsedGroups[groupingValue];
+ refresh();
+ }
- function getGroups() {
- return groups;
- }
+ function getGroups() {
+ return groups;
+ }
- function extractGroups(rows) {
- var group;
- var val;
- var groups = [];
- var groupsByVal = [];
- var r;
-
- for (var i = 0, l = rows.length; i < l; i++) {
- r = rows[i];
- val = (groupingGetterIsAFn) ? groupingGetter(r) : r[groupingGetter];
- val = val || 0;
- group = groupsByVal[val];
- if (!group) {
- group = new Slick.Group();
- group.count = 0;
- group.value = val;
- group.rows = [];
- groups[groups.length] = group;
- groupsByVal[val] = group;
- }
-
- group.rows[group.count++] = r;
- }
-
- return groups;
- }
+ function extractGroups(rows) {
+ var group;
+ var val;
+ var groups = [];
+ var groupsByVal = [];
+ var r;
+
+ for (var i = 0, l = rows.length; i < l; i++) {
+ r = rows[i];
+ val = (groupingGetterIsAFn) ? groupingGetter(r) : r[groupingGetter];
+ val = val || 0;
+ group = groupsByVal[val];
+ if (!group) {
+ group = new Slick.Group();
+ group.count = 0;
+ group.value = val;
+ group.rows = [];
+ groups[groups.length] = group;
+ groupsByVal[val] = group;
+ }
+
+ group.rows[group.count++] = r;
+ }
+
+ return groups;
+ }
- // TODO: lazy totals calculation
- function calculateGroupTotals(group) {
- if (group.collapsed && !aggregateCollapsed) {
- return;
- }
-
- // TODO: try moving iterating over groups into compiled accumulator
- var totals = new Slick.GroupTotals();
- var agg, idx = aggregators.length;
- while (idx--) {
- agg = aggregators[idx];
- agg.init();
- compiledAccumulators[idx].call(agg, group.rows);
- agg.storeResult(totals);
- }
- totals.group = group;
- group.totals = totals;
- }
+ // TODO: lazy totals calculation
+ function calculateGroupTotals(group) {
+ if (group.collapsed && !aggregateCollapsed) {
+ return;
+ }
+
+ // TODO: try moving iterating over groups into compiled accumulator
+ var totals = new Slick.GroupTotals();
+ var agg, idx = aggregators.length;
+ while (idx--) {
+ agg = aggregators[idx];
+ agg.init();
+ compiledAccumulators[idx].call(agg, group.rows);
+ agg.storeResult(totals);
+ }
+ totals.group = group;
+ group.totals = totals;
+ }
- function calculateTotals(groups) {
- var idx = groups.length;
- while (idx--) {
- calculateGroupTotals(groups[idx]);
- }
- }
+ function calculateTotals(groups) {
+ var idx = groups.length;
+ while (idx--) {
+ calculateGroupTotals(groups[idx]);
+ }
+ }
- function finalizeGroups(groups) {
- var idx = groups.length, g;
- while (idx--) {
- g = groups[idx];
- g.collapsed = (g.value in collapsedGroups);
- g.title = groupingFormatter ? groupingFormatter(g) : g.value;
- }
- }
+ function finalizeGroups(groups) {
+ var idx = groups.length, g;
+ while (idx--) {
+ g = groups[idx];
+ g.collapsed = (g.value in collapsedGroups);
+ g.title = groupingFormatter ? groupingFormatter(g) : g.value;
+ }
+ }
- function flattenGroupedRows(groups) {
- var groupedRows = [], gl = 0, g;
- for (var i = 0, l = groups.length; i < l; i++) {
- g = groups[i];
- groupedRows[gl++] = g;
-
- if (!g.collapsed) {
- for (var j = 0, jj = g.rows.length; j < jj; j++) {
- groupedRows[gl++] = g.rows[j];
- }
- }
-
- if (g.totals && (!g.collapsed || aggregateCollapsed)) {
- groupedRows[gl++] = g.totals;
- }
- }
- return groupedRows;
- }
+ function flattenGroupedRows(groups) {
+ var groupedRows = [], gl = 0, g;
+ for (var i = 0, l = groups.length; i < l; i++) {
+ g = groups[i];
+ groupedRows[gl++] = g;
- function getFunctionInfo(fn) {
- var fnRegex = /^function[^(]*\(([^)]*)\)\s*{([\s\S]*)}$/;
- var matches = fn.toString().match(fnRegex);
- return {
- params: matches[1].split(","),
- body: matches[2]
- };
+ if (!g.collapsed) {
+ for (var j = 0, jj = g.rows.length; j < jj; j++) {
+ groupedRows[gl++] = g.rows[j];
+ }
}
- function compileAccumulatorLoop(aggregator) {
- var accumulatorInfo = getFunctionInfo(aggregator.accumulate);
- var fn = new Function(
- "_items",
- "for (var " + accumulatorInfo.params[0] + ", _i=0, _il=_items.length; _i<_il; _i++) {" +
- accumulatorInfo.params[0] + " = _items[_i]; " +
- accumulatorInfo.body +
- "}"
- );
- fn.displayName = fn.name = "compiledAccumulatorLoop";
- return fn;
- }
-
- function compileFilter() {
- var filterInfo = getFunctionInfo(filter);
-
- var filterBody = filterInfo.body
- .replace(/return false;/gi, "{ continue _coreloop; }")
- .replace(/return true;/gi, "{ _retval[_idx++] = $item$; continue _coreloop; }")
- .replace(/return ([^;]+?);/gi,
- "{ if ($1) { _retval[_idx++] = $item$; }; continue _coreloop; }");
-
- // This preserves the function template code after JS compression,
- // so that replace() commands still work as expected.
- var tpl = [
- //"function(_items, _args) { ",
- "var _retval = [], _idx = 0; ",
- "var $item$, $args$ = _args; ",
- "_coreloop: ",
- "for (var _i = 0, _il = _items.length; _i < _il; _i++) { ",
- "$item$ = _items[_i]; ",
- "$filter$; ",
- "} ",
- "return _retval; "
- //"}"
- ].join("");
- tpl = tpl.replace(/\$filter\$/gi, filterBody);
- tpl = tpl.replace(/\$item\$/gi, filterInfo.params[0]);
- tpl = tpl.replace(/\$args\$/gi, filterInfo.params[1]);
-
- var fn = new Function("_items,_args", tpl);
- fn.displayName = fn.name = "compiledFilter";
- return fn;
+ if (g.totals && (!g.collapsed || aggregateCollapsed)) {
+ groupedRows[gl++] = g.totals;
}
+ }
+ return groupedRows;
+ }
- function compileFilterWithCaching() {
- var filterInfo = getFunctionInfo(filter);
-
- var filterBody = filterInfo.body
- .replace(/return false;/gi, "{ continue _coreloop; }")
- .replace(/return true;/gi, "{ _cache[_i] = true;_retval[_idx++] = $item$; continue _coreloop; }")
- .replace(/return ([^;]+?);/gi,
- "{ if ((_cache[_i] = $1)) { _retval[_idx++] = $item$; }; continue _coreloop; }");
-
- // This preserves the function template code after JS compression,
- // so that replace() commands still work as expected.
- var tpl = [
- //"function(_items, _args, _cache) { ",
- "var _retval = [], _idx = 0; ",
- "var $item$, $args$ = _args; ",
- "_coreloop: ",
- "for (var _i = 0, _il = _items.length; _i < _il; _i++) { ",
- "$item$ = _items[_i]; ",
- "if (_cache[_i]) { ",
- "_retval[_idx++] = $item$; ",
- "continue _coreloop; ",
- "} ",
- "$filter$; ",
- "} ",
- "return _retval; "
- //"}"
- ].join("");
- tpl = tpl.replace(/\$filter\$/gi, filterBody);
- tpl = tpl.replace(/\$item\$/gi, filterInfo.params[0]);
- tpl = tpl.replace(/\$args\$/gi, filterInfo.params[1]);
-
- var fn = new Function("_items,_args,_cache", tpl);
- fn.displayName = fn.name = "compiledFilterWithCaching";
- return fn;
- }
+ function getFunctionInfo(fn) {
+ var fnRegex = /^function[^(]*\(([^)]*)\)\s*{([\s\S]*)}$/;
+ var matches = fn.toString().match(fnRegex);
+ return {
+ params:matches[1].split(","),
+ body:matches[2]
+ };
+ }
- function getFilteredAndPagedItems(items) {
- if (filter && !refreshHints.isFilterUnchanged) {
- if (refreshHints.isFilterNarrowing) {
- filteredItems = compiledFilter(filteredItems, filterArgs);
- } else if (refreshHints.isFilterExpanding) {
- filteredItems = compiledFilterWithCaching(items, filterArgs, filterCache);
- } else {
- filteredItems = compiledFilter(items, filterArgs);
- }
- } else {
- // special case: if not filtering and not paging, the resulting
- // rows collection needs to be a copy so that changes due to sort
- // can be caught
- filteredItems = pagesize ? items : items.concat();
- }
-
- // get the current page
- var paged;
- if (pagesize) {
- if (filteredItems.length < pagenum * pagesize) {
- pagenum = Math.floor(filteredItems.length / pagesize);
- }
- paged = filteredItems.slice(pagesize * pagenum, pagesize * pagenum + pagesize);
- } else {
- paged = filteredItems;
- }
-
- return {totalRows:filteredItems.length, rows:paged};
- }
+ function compileAccumulatorLoop(aggregator) {
+ var accumulatorInfo = getFunctionInfo(aggregator.accumulate);
+ var fn = new Function(
+ "_items",
+ "for (var " + accumulatorInfo.params[0] + ", _i=0, _il=_items.length; _i<_il; _i++) {" +
+ accumulatorInfo.params[0] + " = _items[_i]; " +
+ accumulatorInfo.body +
+ "}"
+ );
+ fn.displayName = fn.name = "compiledAccumulatorLoop";
+ return fn;
+ }
- function getRowDiffs(rows, newRows) {
- var item, r, eitherIsNonData, diff = [];
- var from = 0, to = newRows.length;
-
- if (refreshHints && refreshHints.ignoreDiffsBefore) {
- from = Math.max(0,
- Math.min(newRows.length, refreshHints.ignoreDiffsBefore));
- }
-
- if (refreshHints && refreshHints.ignoreDiffsAfter) {
- to = Math.min(newRows.length,
- Math.max(0, refreshHints.ignoreDiffsAfter));
- }
-
- for (var i = from, rl = rows.length; i < to; i++) {
- if (i >= rl) {
- diff[diff.length] = i;
- }
- else {
- item = newRows[i];
- r = rows[i];
-
- if ((groupingGetter && (eitherIsNonData = (item.__nonDataRow) || (r.__nonDataRow)) &&
- item.__group !== r.__group ||
- item.__updated ||
- item.__group && !item.equals(r))
- || (aggregators && eitherIsNonData &&
- // no good way to compare totals since they are arbitrary DTOs
- // deep object comparison is pretty expensive
- // always considering them 'dirty' seems easier for the time being
- (item.__groupTotals || r.__groupTotals))
- || item[idProperty] != r[idProperty]
- || (updated && updated[item[idProperty]])
- ) {
- diff[diff.length] = i;
- }
- }
- }
- return diff;
- }
+ function compileFilter() {
+ var filterInfo = getFunctionInfo(filter);
+
+ var filterBody = filterInfo.body
+ .replace(/return false;/gi, "{ continue _coreloop; }")
+ .replace(/return true;/gi, "{ _retval[_idx++] = $item$; continue _coreloop; }")
+ .replace(/return ([^;]+?);/gi,
+ "{ if ($1) { _retval[_idx++] = $item$; }; continue _coreloop; }");
+
+ // This preserves the function template code after JS compression,
+ // so that replace() commands still work as expected.
+ var tpl = [
+ //"function(_items, _args) { ",
+ "var _retval = [], _idx = 0; ",
+ "var $item$, $args$ = _args; ",
+ "_coreloop: ",
+ "for (var _i = 0, _il = _items.length; _i < _il; _i++) { ",
+ "$item$ = _items[_i]; ",
+ "$filter$; ",
+ "} ",
+ "return _retval; "
+ //"}"
+ ].join("");
+ tpl = tpl.replace(/\$filter\$/gi, filterBody);
+ tpl = tpl.replace(/\$item\$/gi, filterInfo.params[0]);
+ tpl = tpl.replace(/\$args\$/gi, filterInfo.params[1]);
+
+ var fn = new Function("_items,_args", tpl);
+ fn.displayName = fn.name = "compiledFilter";
+ return fn;
+ }
- function recalc(_items) {
- rowsById = null;
+ function compileFilterWithCaching() {
+ var filterInfo = getFunctionInfo(filter);
+
+ var filterBody = filterInfo.body
+ .replace(/return false;/gi, "{ continue _coreloop; }")
+ .replace(/return true;/gi, "{ _cache[_i] = true;_retval[_idx++] = $item$; continue _coreloop; }")
+ .replace(/return ([^;]+?);/gi,
+ "{ if ((_cache[_i] = $1)) { _retval[_idx++] = $item$; }; continue _coreloop; }");
+
+ // This preserves the function template code after JS compression,
+ // so that replace() commands still work as expected.
+ var tpl = [
+ //"function(_items, _args, _cache) { ",
+ "var _retval = [], _idx = 0; ",
+ "var $item$, $args$ = _args; ",
+ "_coreloop: ",
+ "for (var _i = 0, _il = _items.length; _i < _il; _i++) { ",
+ "$item$ = _items[_i]; ",
+ "if (_cache[_i]) { ",
+ "_retval[_idx++] = $item$; ",
+ "continue _coreloop; ",
+ "} ",
+ "$filter$; ",
+ "} ",
+ "return _retval; "
+ //"}"
+ ].join("");
+ tpl = tpl.replace(/\$filter\$/gi, filterBody);
+ tpl = tpl.replace(/\$item\$/gi, filterInfo.params[0]);
+ tpl = tpl.replace(/\$args\$/gi, filterInfo.params[1]);
+
+ var fn = new Function("_items,_args,_cache", tpl);
+ fn.displayName = fn.name = "compiledFilterWithCaching";
+ return fn;
+ }
- if (refreshHints.isFilterNarrowing != prevRefreshHints.isFilterNarrowing ||
- refreshHints.isFilterExpanding != prevRefreshHints.isFilterExpanding) {
- filterCache = [];
- }
+ function getFilteredAndPagedItems(items) {
+ if (filter && !refreshHints.isFilterUnchanged) {
+ if (refreshHints.isFilterNarrowing) {
+ filteredItems = compiledFilter(filteredItems, filterArgs);
+ } else if (refreshHints.isFilterExpanding) {
+ filteredItems = compiledFilterWithCaching(items, filterArgs, filterCache);
+ } else {
+ filteredItems = compiledFilter(items, filterArgs);
+ }
+ } else {
+ // special case: if not filtering and not paging, the resulting
+ // rows collection needs to be a copy so that changes due to sort
+ // can be caught
+ filteredItems = pagesize ? items : items.concat();
+ }
+
+ // get the current page
+ var paged;
+ if (pagesize) {
+ if (filteredItems.length < pagenum * pagesize) {
+ pagenum = Math.floor(filteredItems.length / pagesize);
+ }
+ paged = filteredItems.slice(pagesize * pagenum, pagesize * pagenum + pagesize);
+ } else {
+ paged = filteredItems;
+ }
+
+ return {totalRows:filteredItems.length, rows:paged};
+ }
- var filteredItems = getFilteredAndPagedItems(_items);
- totalRows = filteredItems.totalRows;
- var newRows = filteredItems.rows;
+ function getRowDiffs(rows, newRows) {
+ var item, r, eitherIsNonData, diff = [];
+ var from = 0, to = newRows.length;
+
+ if (refreshHints && refreshHints.ignoreDiffsBefore) {
+ from = Math.max(0,
+ Math.min(newRows.length, refreshHints.ignoreDiffsBefore));
+ }
+
+ if (refreshHints && refreshHints.ignoreDiffsAfter) {
+ to = Math.min(newRows.length,
+ Math.max(0, refreshHints.ignoreDiffsAfter));
+ }
+
+ for (var i = from, rl = rows.length; i < to; i++) {
+ if (i >= rl) {
+ diff[diff.length] = i;
+ }
+ else {
+ item = newRows[i];
+ r = rows[i];
+
+ if ((groupingGetter && (eitherIsNonData = (item.__nonDataRow) || (r.__nonDataRow)) &&
+ item.__group !== r.__group ||
+ item.__updated ||
+ item.__group && !item.equals(r))
+ || (aggregators && eitherIsNonData &&
+ // no good way to compare totals since they are arbitrary DTOs
+ // deep object comparison is pretty expensive
+ // always considering them 'dirty' seems easier for the time being
+ (item.__groupTotals || r.__groupTotals))
+ || item[idProperty] != r[idProperty]
+ || (updated && updated[item[idProperty]])
+ ) {
+ diff[diff.length] = i;
+ }
+ }
+ }
+ return diff;
+ }
- groups = [];
- if (groupingGetter != null) {
- groups = extractGroups(newRows);
- if (groups.length) {
- finalizeGroups(groups);
- if (aggregators) {
- calculateTotals(groups);
- }
- groups.sort(groupingComparer);
- newRows = flattenGroupedRows(groups);
- }
- }
+ function recalc(_items) {
+ rowsById = null;
- var diff = getRowDiffs(rows, newRows);
+ if (refreshHints.isFilterNarrowing != prevRefreshHints.isFilterNarrowing ||
+ refreshHints.isFilterExpanding != prevRefreshHints.isFilterExpanding) {
+ filterCache = [];
+ }
- rows = newRows;
+ var filteredItems = getFilteredAndPagedItems(_items);
+ totalRows = filteredItems.totalRows;
+ var newRows = filteredItems.rows;
- return diff;
+ groups = [];
+ if (groupingGetter != null) {
+ groups = extractGroups(newRows);
+ if (groups.length) {
+ finalizeGroups(groups);
+ if (aggregators) {
+ calculateTotals(groups);
+ }
+ groups.sort(groupingComparer);
+ newRows = flattenGroupedRows(groups);
}
+ }
- function refresh() {
- if (suspend) return;
+ var diff = getRowDiffs(rows, newRows);
- var countBefore = rows.length;
- var totalRowsBefore = totalRows;
+ rows = newRows;
- var diff = recalc(items, filter); // pass as direct refs to avoid closure perf hit
-
- // if the current page is no longer valid, go to last page and recalc
- // we suffer a performance penalty here, but the main loop (recalc) remains highly optimized
- if (pagesize && totalRows < pagenum * pagesize) {
- pagenum = Math.floor(totalRows / pagesize);
- diff = recalc(items, filter);
- }
-
- updated = null;
- prevRefreshHints = refreshHints;
- refreshHints = {};
+ return diff;
+ }
- if (totalRowsBefore != totalRows) onPagingInfoChanged.notify(getPagingInfo(), null, self);
- if (countBefore != rows.length) onRowCountChanged.notify({previous:countBefore, current:rows.length}, null, self);
- if (diff.length > 0) onRowsChanged.notify({rows:diff}, null, self);
- }
+ function refresh() {
+ if (suspend) {
+ return;
+ }
+
+ var countBefore = rows.length;
+ var totalRowsBefore = totalRows;
+
+ var diff = recalc(items, filter); // pass as direct refs to avoid closure perf hit
+
+ // if the current page is no longer valid, go to last page and recalc
+ // we suffer a performance penalty here, but the main loop (recalc) remains highly optimized
+ if (pagesize && totalRows < pagenum * pagesize) {
+ pagenum = Math.floor(totalRows / pagesize);
+ diff = recalc(items, filter);
+ }
+
+ updated = null;
+ prevRefreshHints = refreshHints;
+ refreshHints = {};
+
+ if (totalRowsBefore != totalRows) {
+ onPagingInfoChanged.notify(getPagingInfo(), null, self);
+ }
+ if (countBefore != rows.length) {
+ onRowCountChanged.notify({previous:countBefore, current:rows.length}, null, self);
+ }
+ if (diff.length > 0) {
+ onRowsChanged.notify({rows:diff}, null, self);
+ }
+ }
- return {
- // methods
- "beginUpdate": beginUpdate,
- "endUpdate": endUpdate,
- "setPagingOptions": setPagingOptions,
- "getPagingInfo": getPagingInfo,
- "getItems": getItems,
- "setItems": setItems,
- "setFilter": setFilter,
- "sort": sort,
- "fastSort": fastSort,
- "reSort": reSort,
- "groupBy": groupBy,
- "setAggregators": setAggregators,
- "collapseGroup": collapseGroup,
- "expandGroup": expandGroup,
- "getGroups": getGroups,
- "getIdxById": getIdxById,
- "getRowById": getRowById,
- "getItemById": getItemById,
- "getItemByIdx": getItemByIdx,
- "setRefreshHints": setRefreshHints,
- "setFilterArgs": setFilterArgs,
- "refresh": refresh,
- "updateItem": updateItem,
- "insertItem": insertItem,
- "addItem": addItem,
- "deleteItem": deleteItem,
-
- // data provider methods
- "getLength": getLength,
- "getItem": getItem,
- "getItemMetadata": getItemMetadata,
-
- // events
- "onRowCountChanged": onRowCountChanged,
- "onRowsChanged": onRowsChanged,
- "onPagingInfoChanged": onPagingInfoChanged
- };
- }
-
- function AvgAggregator(field) {
- this.field_ = field;
-
- this.init = function() {
- this.count_ = 0;
- this.nonNullCount_ = 0;
- this.sum_ = 0;
- };
-
- this.accumulate = function(item) {
- var val = item[this.field_];
- this.count_++;
- if (val != null && val != NaN) {
- this.nonNullCount_++;
- this.sum_ += 1 * val;
- }
- };
-
- this.storeResult = function(groupTotals) {
- if (!groupTotals.avg) {
- groupTotals.avg = {};
- }
- if (this.nonNullCount_ != 0) {
- groupTotals.avg[this.field_] = this.sum_ / this.nonNullCount_;
- }
- };
- }
-
- function MinAggregator(field) {
- this.field_ = field;
-
- this.init = function() {
- this.min_ = null;
- };
-
- this.accumulate = function(item) {
- var val = item[this.field_];
- if (val != null && val != NaN) {
- if (this.min_ == null ||val < this.min_) {
- this.min_ = val;
- }
- }
- };
-
- this.storeResult = function(groupTotals) {
- if (!groupTotals.min) {
- groupTotals.min = {};
- }
- groupTotals.min[this.field_] = this.min_;
- }
+ return {
+ // methods
+ "beginUpdate":beginUpdate,
+ "endUpdate":endUpdate,
+ "setPagingOptions":setPagingOptions,
+ "getPagingInfo":getPagingInfo,
+ "getItems":getItems,
+ "setItems":setItems,
+ "setFilter":setFilter,
+ "sort":sort,
+ "fastSort":fastSort,
+ "reSort":reSort,
+ "groupBy":groupBy,
+ "setAggregators":setAggregators,
+ "collapseGroup":collapseGroup,
+ "expandGroup":expandGroup,
+ "getGroups":getGroups,
+ "getIdxById":getIdxById,
+ "getRowById":getRowById,
+ "getItemById":getItemById,
+ "getItemByIdx":getItemByIdx,
+ "setRefreshHints":setRefreshHints,
+ "setFilterArgs":setFilterArgs,
+ "refresh":refresh,
+ "updateItem":updateItem,
+ "insertItem":insertItem,
+ "addItem":addItem,
+ "deleteItem":deleteItem,
+
+ // data provider methods
+ "getLength":getLength,
+ "getItem":getItem,
+ "getItemMetadata":getItemMetadata,
+
+ // events
+ "onRowCountChanged":onRowCountChanged,
+ "onRowsChanged":onRowsChanged,
+ "onPagingInfoChanged":onPagingInfoChanged
+ };
+ }
+
+ function AvgAggregator(field) {
+ this.field_ = field;
+
+ this.init = function () {
+ this.count_ = 0;
+ this.nonNullCount_ = 0;
+ this.sum_ = 0;
+ };
+
+ this.accumulate = function (item) {
+ var val = item[this.field_];
+ this.count_++;
+ if (val != null && val != NaN) {
+ this.nonNullCount_++;
+ this.sum_ += 1 * val;
+ }
+ };
+
+ this.storeResult = function (groupTotals) {
+ if (!groupTotals.avg) {
+ groupTotals.avg = {};
+ }
+ if (this.nonNullCount_ != 0) {
+ groupTotals.avg[this.field_] = this.sum_ / this.nonNullCount_;
+ }
+ };
+ }
+
+ function MinAggregator(field) {
+ this.field_ = field;
+
+ this.init = function () {
+ this.min_ = null;
+ };
+
+ this.accumulate = function (item) {
+ var val = item[this.field_];
+ if (val != null && val != NaN) {
+ if (this.min_ == null || val < this.min_) {
+ this.min_ = val;
+ }
+ }
+ };
+
+ this.storeResult = function (groupTotals) {
+ if (!groupTotals.min) {
+ groupTotals.min = {};
+ }
+ groupTotals.min[this.field_] = this.min_;
}
+ }
- function MaxAggregator(field) {
- this.field_ = field;
+ function MaxAggregator(field) {
+ this.field_ = field;
- this.init = function() {
- this.max_ = null;
- };
+ this.init = function () {
+ this.max_ = null;
+ };
- this.accumulate = function(item) {
- var val = item[this.field_];
- if (val != null && val != NaN) {
- if (this.max_ == null ||val > this.max_) {
- this.max_ = val;
- }
- }
- };
-
- this.storeResult = function(groupTotals) {
- if (!groupTotals.max) {
- groupTotals.max = {};
- }
- groupTotals.max[this.field_] = this.max_;
+ this.accumulate = function (item) {
+ var val = item[this.field_];
+ if (val != null && val != NaN) {
+ if (this.max_ == null || val > this.max_) {
+ this.max_ = val;
}
+ }
+ };
+
+ this.storeResult = function (groupTotals) {
+ if (!groupTotals.max) {
+ groupTotals.max = {};
+ }
+ groupTotals.max[this.field_] = this.max_;
}
+ }
- // TODO: add more built-in aggregators
- // TODO: merge common aggregators in one to prevent needles iterating
+ // TODO: add more built-in aggregators
+ // TODO: merge common aggregators in one to prevent needles iterating
})(jQuery); \ No newline at end of file
diff --git a/slick.editors.js b/slick.editors.js
index a458195..3101da7 100644
--- a/slick.editors.js
+++ b/slick.editors.js
@@ -1,616 +1,626 @@
/* THESE FORMATTERS & EDITORS ARE JUST SAMPLES! */
+(function ($) {
+ var SlickEditor = {
+ SelectorCellFormatter:function (row, cell, value, columnDef, dataContext) {
+ return (!dataContext ? "" : row);
+ },
+
+ PercentCompleteCellFormatter:function (row, cell, value, columnDef, dataContext) {
+ if (value == null || value === "") {
+ return "-";
+ } else if (value < 50) {
+ return "<span style='color:red;font-weight:bold;'>" + value + "%</span>";
+ } else {
+ return "<span style='color:green'>" + value + "%</span>";
+ }
+ },
+
+ GraphicalPercentCompleteCellFormatter:function (row, cell, value, columnDef, dataContext) {
+ if (value == null || value === "") {
+ return "";
+ }
+
+ var color;
+
+ if (value < 30) {
+ color = "red";
+ } else if (value < 70) {
+ color = "silver";
+ } else {
+ color = "green";
+ }
+
+ return "<span class='percent-complete-bar' style='background:" + color + ";width:" + value + "%'></span>";
+ },
+
+ YesNoCellFormatter:function (row, cell, value, columnDef, dataContext) {
+ return value ? "Yes" : "No";
+ },
+
+ BoolCellFormatter:function (row, cell, value, columnDef, dataContext) {
+ return value ? "<img src='../images/tick.png'>" : "";
+ },
+
+ TaskNameFormatter:function (row, cell, value, columnDef, dataContext) {
+ // todo: html encode
+ var spacer = "<span style='display:inline-block;height:1px;width:" + (2 + 15 * dataContext["indent"]) + "px'></span>";
+ return spacer + " <img src='../images/expand.gif'>&nbsp;" + value;
+ },
+
+ ResourcesFormatter:function (row, cell, value, columnDef, dataContext) {
+ var resources = dataContext["resources"];
+
+ if (!resources || resources.length == 0) {
+ return "";
+ }
+
+ if (columnDef.width < 50) {
+ return (resources.length > 1 ? "<center><img src='../images/user_identity_plus.gif' " : "<center><img src='../images/user_identity.gif' ") +
+ " title='" + resources.join(", ") + "'></center>";
+ } else {
+ return resources.join(", ");
+ }
+ },
+
+ StarFormatter:function (row, cell, value, columnDef, dataContext) {
+ return (value) ? "<img src='../images/bullet_star.png' align='absmiddle'>" : "";
+ },
+
+
+ TextCellEditor:function (args) {
+ var $input;
+ var defaultValue;
+ var scope = this;
+
+ this.init = function () {
+ $input = $("<INPUT type=text class='editor-text' />")
+ .appendTo(args.container)
+ .bind("keydown.nav", function (e) {
+ if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
+ e.stopImmediatePropagation();
+ }
+ })
+ .focus()
+ .select();
+ };
+
+ this.destroy = function () {
+ $input.remove();
+ };
+
+ this.focus = function () {
+ $input.focus();
+ };
+
+ this.getValue = function () {
+ return $input.val();
+ };
+
+ this.setValue = function (val) {
+ $input.val(val);
+ };
+
+ this.loadValue = function (item) {
+ defaultValue = item[args.column.field] || "";
+ $input.val(defaultValue);
+ $input[0].defaultValue = defaultValue;
+ $input.select();
+ };
+
+ this.serializeValue = function () {
+ return $input.val();
+ };
+
+ this.applyValue = function (item, state) {
+ item[args.column.field] = state;
+ };
+
+ this.isValueChanged = function () {
+ return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
+ };
+
+ this.validate = function () {
+ if (args.column.validator) {
+ var validationResults = args.column.validator($input.val());
+ if (!validationResults.valid) {
+ return validationResults;
+ }
+ }
+
+ return {
+ valid:true,
+ msg:null
+ };
+ };
+
+ this.init();
+ },
+
+ IntegerCellEditor:function (args) {
+ var $input;
+ var defaultValue;
+ var scope = this;
+
+ this.init = function () {
+ $input = $("<INPUT type=text class='editor-text' />");
+
+ $input.bind("keydown.nav", function (e) {
+ if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
+ e.stopImmediatePropagation();
+ }
+ });
+
+ $input.appendTo(args.container);
+ $input.focus().select();
+ };
+
+ this.destroy = function () {
+ $input.remove();
+ };
+
+ this.focus = function () {
+ $input.focus();
+ };
+
+ this.loadValue = function (item) {
+ defaultValue = item[args.column.field];
+ $input.val(defaultValue);
+ $input[0].defaultValue = defaultValue;
+ $input.select();
+ };
+
+ this.serializeValue = function () {
+ return parseInt($input.val(), 10) || 0;
+ };
+
+ this.applyValue = function (item, state) {
+ item[args.column.field] = state;
+ };
+
+ this.isValueChanged = function () {
+ return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
+ };
+
+ this.validate = function () {
+ if (isNaN($input.val())) {
+ return {
+ valid:false,
+ msg:"Please enter a valid integer"
+ };
+ }
+
+ return {
+ valid:true,
+ msg:null
+ };
+ };
+
+ this.init();
+ },
+
+ DateCellEditor:function (args) {
+ var $input;
+ var defaultValue;
+ var scope = this;
+ var calendarOpen = false;
+
+ this.init = function () {
+ $input = $("<INPUT type=text class='editor-text' />");
+ $input.appendTo(args.container);
+ $input.focus().select();
+ $input.datepicker({
+ showOn:"button",
+ buttonImageOnly:true,
+ buttonImage:"../images/calendar.gif",
+ beforeShow:function () {
+ calendarOpen = true
+ },
+ onClose:function () {
+ calendarOpen = false
+ }
+ });
+ $input.width($input.width() - 18);
+ };
+
+ this.destroy = function () {
+ $.datepicker.dpDiv.stop(true, true);
+ $input.datepicker("hide");
+ $input.datepicker("destroy");
+ $input.remove();
+ };
+
+ this.show = function () {
+ if (calendarOpen) {
+ $.datepicker.dpDiv.stop(true, true).show();
+ }
+ };
-(function($) {
-
- var SlickEditor = {
-
- SelectorCellFormatter : function(row, cell, value, columnDef, dataContext) {
- return (!dataContext ? "" : row);
- },
-
- PercentCompleteCellFormatter : function(row, cell, value, columnDef, dataContext) {
- if (value == null || value === "")
- return "-";
- else if (value < 50)
- return "<span style='color:red;font-weight:bold;'>" + value + "%</span>";
- else
- return "<span style='color:green'>" + value + "%</span>";
- },
-
- GraphicalPercentCompleteCellFormatter : function(row, cell, value, columnDef, dataContext) {
- if (value == null || value === "")
- return "";
-
- var color;
-
- if (value < 30)
- color = "red";
- else if (value < 70)
- color = "silver";
- else
- color = "green";
-
- return "<span class='percent-complete-bar' style='background:" + color + ";width:" + value + "%'></span>";
- },
-
- YesNoCellFormatter : function(row, cell, value, columnDef, dataContext) {
- return value ? "Yes" : "No";
- },
-
- BoolCellFormatter : function(row, cell, value, columnDef, dataContext) {
- return value ? "<img src='../images/tick.png'>" : "";
- },
-
- TaskNameFormatter : function(row, cell, value, columnDef, dataContext) {
- // todo: html encode
- var spacer = "<span style='display:inline-block;height:1px;width:" + (2 + 15 * dataContext["indent"]) + "px'></span>";
- return spacer + " <img src='../images/expand.gif'>&nbsp;" + value;
- },
-
- ResourcesFormatter : function(row, cell, value, columnDef, dataContext) {
- var resources = dataContext["resources"];
-
- if (!resources || resources.length == 0)
- return "";
-
- if (columnDef.width < 50)
- return (resources.length > 1 ? "<center><img src='../images/user_identity_plus.gif' " : "<center><img src='../images/user_identity.gif' ") +
- " title='" + resources.join(", ") + "'></center>";
- else
- return resources.join(", ");
- },
-
- StarFormatter : function(row, cell, value, columnDef, dataContext) {
- return (value) ? "<img src='../images/bullet_star.png' align='absmiddle'>" : "";
- },
-
-
- TextCellEditor : function(args) {
- var $input;
- var defaultValue;
- var scope = this;
-
- this.init = function() {
- $input = $("<INPUT type=text class='editor-text' />")
- .appendTo(args.container)
- .bind("keydown.nav", function(e) {
- if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
- e.stopImmediatePropagation();
- }
- })
- .focus()
- .select();
- };
-
- this.destroy = function() {
- $input.remove();
- };
-
- this.focus = function() {
- $input.focus();
- };
-
- this.getValue = function() {
- return $input.val();
- };
-
- this.setValue = function(val) {
- $input.val(val);
- };
-
- this.loadValue = function(item) {
- defaultValue = item[args.column.field] || "";
- $input.val(defaultValue);
- $input[0].defaultValue = defaultValue;
- $input.select();
- };
-
- this.serializeValue = function() {
- return $input.val();
- };
-
- this.applyValue = function(item,state) {
- item[args.column.field] = state;
- };
-
- this.isValueChanged = function() {
- return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
- };
-
- this.validate = function() {
- if (args.column.validator) {
- var validationResults = args.column.validator($input.val());
- if (!validationResults.valid)
- return validationResults;
- }
-
- return {
- valid: true,
- msg: null
- };
- };
-
- this.init();
- },
-
- IntegerCellEditor : function(args) {
- var $input;
- var defaultValue;
- var scope = this;
-
- this.init = function() {
- $input = $("<INPUT type=text class='editor-text' />");
-
- $input.bind("keydown.nav", function(e) {
- if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
- e.stopImmediatePropagation();
- }
- });
-
- $input.appendTo(args.container);
- $input.focus().select();
- };
-
- this.destroy = function() {
- $input.remove();
- };
-
- this.focus = function() {
- $input.focus();
- };
-
- this.loadValue = function(item) {
- defaultValue = item[args.column.field];
- $input.val(defaultValue);
- $input[0].defaultValue = defaultValue;
- $input.select();
- };
-
- this.serializeValue = function() {
- return parseInt($input.val(),10) || 0;
- };
-
- this.applyValue = function(item,state) {
- item[args.column.field] = state;
- };
-
- this.isValueChanged = function() {
- return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
- };
-
- this.validate = function() {
- if (isNaN($input.val()))
- return {
- valid: false,
- msg: "Please enter a valid integer"
- };
-
- return {
- valid: true,
- msg: null
- };
- };
-
- this.init();
- },
-
- DateCellEditor : function(args) {
- var $input;
- var defaultValue;
- var scope = this;
- var calendarOpen = false;
-
- this.init = function() {
- $input = $("<INPUT type=text class='editor-text' />");
- $input.appendTo(args.container);
- $input.focus().select();
- $input.datepicker({
- showOn: "button",
- buttonImageOnly: true,
- buttonImage: "../images/calendar.gif",
- beforeShow: function() { calendarOpen = true },
- onClose: function() { calendarOpen = false }
- });
- $input.width($input.width() - 18);
- };
-
- this.destroy = function() {
- $.datepicker.dpDiv.stop(true,true);
- $input.datepicker("hide");
- $input.datepicker("destroy");
- $input.remove();
- };
-
- this.show = function() {
- if (calendarOpen) {
- $.datepicker.dpDiv.stop(true,true).show();
- }
- };
-
- this.hide = function() {
- if (calendarOpen) {
- $.datepicker.dpDiv.stop(true,true).hide();
- }
- };
-
- this.position = function(position) {
- if (!calendarOpen) return;
- $.datepicker.dpDiv
- .css("top", position.top + 30)
- .css("left", position.left);
- };
-
- this.focus = function() {
- $input.focus();
- };
-
- this.loadValue = function(item) {
- defaultValue = item[args.column.field];
- $input.val(defaultValue);
- $input[0].defaultValue = defaultValue;
- $input.select();
- };
-
- this.serializeValue = function() {
- return $input.val();
- };
-
- this.applyValue = function(item,state) {
- item[args.column.field] = state;
- };
-
- this.isValueChanged = function() {
- return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
- };
-
- this.validate = function() {
- return {
- valid: true,
- msg: null
- };
- };
-
- this.init();
- },
-
- YesNoSelectCellEditor : function(args) {
- var $select;
- var defaultValue;
- var scope = this;
-
- this.init = function() {
- $select = $("<SELECT tabIndex='0' class='editor-yesno'><OPTION value='yes'>Yes</OPTION><OPTION value='no'>No</OPTION></SELECT>");
- $select.appendTo(args.container);
- $select.focus();
- };
-
- this.destroy = function() {
- $select.remove();
- };
-
- this.focus = function() {
- $select.focus();
- };
-
- this.loadValue = function(item) {
- $select.val((defaultValue = item[args.column.field]) ? "yes" : "no");
- $select.select();
- };
-
- this.serializeValue = function() {
- return ($select.val() == "yes");
- };
-
- this.applyValue = function(item,state) {
- item[args.column.field] = state;
- };
-
- this.isValueChanged = function() {
- return ($select.val() != defaultValue);
- };
-
- this.validate = function() {
- return {
- valid: true,
- msg: null
- };
- };
-
- this.init();
- },
-
- YesNoCheckboxCellEditor : function(args) {
- var $select;
- var defaultValue;
- var scope = this;
-
- this.init = function() {
- $select = $("<INPUT type=checkbox value='true' class='editor-checkbox' hideFocus>");
- $select.appendTo(args.container);
- $select.focus();
- };
-
- this.destroy = function() {
- $select.remove();
- };
-
- this.focus = function() {
- $select.focus();
- };
-
- this.loadValue = function(item) {
- defaultValue = item[args.column.field];
- if (defaultValue)
- $select.attr("checked", "checked");
- else
- $select.removeAttr("checked");
- };
-
- this.serializeValue = function() {
- return $select.attr("checked");
- };
-
- this.applyValue = function(item,state) {
- item[args.column.field] = state;
- };
-
- this.isValueChanged = function() {
- return ($select.attr("checked") != defaultValue);
- };
-
- this.validate = function() {
- return {
- valid: true,
- msg: null
- };
- };
-
- this.init();
- },
-
- PercentCompleteCellEditor : function(args) {
- var $input, $picker;
- var defaultValue;
- var scope = this;
-
- this.init = function() {
- $input = $("<INPUT type=text class='editor-percentcomplete' />");
- $input.width($(args.container).innerWidth() - 25);
- $input.appendTo(args.container);
-
- $picker = $("<div class='editor-percentcomplete-picker' />").appendTo(args.container);
- $picker.append("<div class='editor-percentcomplete-helper'><div class='editor-percentcomplete-wrapper'><div class='editor-percentcomplete-slider' /><div class='editor-percentcomplete-buttons' /></div></div>");
-
- $picker.find(".editor-percentcomplete-buttons").append("<button val=0>Not started</button><br/><button val=50>In Progress</button><br/><button val=100>Complete</button>");
-
- $input.focus().select();
-
- $picker.find(".editor-percentcomplete-slider").slider({
- orientation: "vertical",
- range: "min",
- value: defaultValue,
- slide: function(event, ui) {
- $input.val(ui.value)
- }
- });
-
- $picker.find(".editor-percentcomplete-buttons button").bind("click", function(e) {
- $input.val($(this).attr("val"));
- $picker.find(".editor-percentcomplete-slider").slider("value", $(this).attr("val"));
- })
- };
-
- this.destroy = function() {
- $input.remove();
- $picker.remove();
- };
-
- this.focus = function() {
- $input.focus();
- };
-
- this.loadValue = function(item) {
- $input.val(defaultValue = item[args.column.field]);
- $input.select();
- };
-
- this.serializeValue = function() {
- return parseInt($input.val(),10) || 0;
- };
-
- this.applyValue = function(item,state) {
- item[args.column.field] = state;
- };
-
- this.isValueChanged = function() {
- return (!($input.val() == "" && defaultValue == null)) && ((parseInt($input.val(),10) || 0) != defaultValue);
- };
-
- this.validate = function() {
- if (isNaN(parseInt($input.val(),10)))
- return {
- valid: false,
- msg: "Please enter a valid positive number"
- };
-
- return {
- valid: true,
- msg: null
- };
- };
-
- this.init();
- },
-
- StarCellEditor : function(args) {
- var $input;
- var defaultValue;
- var scope = this;
-
- function toggle(e) {
- if (e.type == "keydown" && e.which != 32) return;
-
- if ($input.css("opacity") == "1")
- $input.css("opacity", 0.5);
- else
- $input.css("opacity", 1);
-
- e.preventDefault();
- e.stopPropagation();
- return false;
- }
-
- this.init = function() {
- $input = $("<IMG src='../images/bullet_star.png' align=absmiddle tabIndex=0 title='Click or press Space to toggle' />")
- .bind("click keydown", toggle)
- .appendTo(args.container)
- .focus();
- };
-
- this.destroy = function() {
- $input.unbind("click keydown", toggle);
- $input.remove();
- };
-
- this.focus = function() {
- $input.focus();
- };
-
- this.loadValue = function(item) {
- defaultValue = item[args.column.field];
- $input.css("opacity", defaultValue ? 1 : 0.2);
- };
-
- this.serializeValue = function() {
- return ($input.css("opacity") == "1");
- };
-
- this.applyValue = function(item,state) {
- item[args.column.field] = state;
- };
-
- this.isValueChanged = function() {
- return defaultValue != ($input.css("opacity") == "1");
- };
-
- this.validate = function() {
- return {
- valid: true,
- msg: null
- };
- };
-
- this.init();
- },
-
- /*
- * An example of a "detached" editor.
- * The UI is added onto document BODY and .position(), .show() and .hide() are implemented.
- * KeyDown events are also handled to provide handling for Tab, Shift-Tab, Esc and Ctrl-Enter.
- */
- LongTextCellEditor : function (args) {
- var $input, $wrapper;
- var defaultValue;
- var scope = this;
-
- this.init = function() {
- var $container = $("body");
-
- $wrapper = $("<DIV style='z-index:10000;position:absolute;background:white;padding:5px;border:3px solid gray; -moz-border-radius:10px; border-radius:10px;'/>")
- .appendTo($container);
-
- $input = $("<TEXTAREA hidefocus rows=5 style='backround:white;width:250px;height:80px;border:0;outline:0'>")
- .appendTo($wrapper);
-
- $("<DIV style='text-align:right'><BUTTON>Save</BUTTON><BUTTON>Cancel</BUTTON></DIV>")
- .appendTo($wrapper);
-
- $wrapper.find("button:first").bind("click", this.save);
- $wrapper.find("button:last").bind("click", this.cancel);
- $input.bind("keydown", this.handleKeyDown);
-
- scope.position(args.position);
- $input.focus().select();
- };
-
- this.handleKeyDown = function(e) {
- if (e.which == $.ui.keyCode.ENTER && e.ctrlKey) {
- scope.save();
- }
- else if (e.which == $.ui.keyCode.ESCAPE) {
- e.preventDefault();
- scope.cancel();
- }
- else if (e.which == $.ui.keyCode.TAB && e.shiftKey) {
- e.preventDefault();
- grid.navigatePrev();
- }
- else if (e.which == $.ui.keyCode.TAB) {
- e.preventDefault();
- grid.navigateNext();
- }
- };
-
- this.save = function() {
- args.commitChanges();
- };
-
- this.cancel = function() {
- $input.val(defaultValue);
- args.cancelChanges();
- };
-
- this.hide = function() {
- $wrapper.hide();
- };
-
- this.show = function() {
- $wrapper.show();
- };
-
- this.position = function(position) {
- $wrapper
- .css("top", position.top - 5)
- .css("left", position.left - 5)
- };
-
- this.destroy = function() {
- $wrapper.remove();
- };
-
- this.focus = function() {
- $input.focus();
- };
-
- this.loadValue = function(item) {
- $input.val(defaultValue = item[args.column.field]);
- $input.select();
- };
-
- this.serializeValue = function() {
- return $input.val();
- };
-
- this.applyValue = function(item,state) {
- item[args.column.field] = state;
- };
-
- this.isValueChanged = function() {
- return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
- };
-
- this.validate = function() {
- return {
- valid: true,
- msg: null
- };
- };
-
- this.init();
+ this.hide = function () {
+ if (calendarOpen) {
+ $.datepicker.dpDiv.stop(true, true).hide();
}
+ };
- };
+ this.position = function (position) {
+ if (!calendarOpen) {
+ return;
+ }
+ $.datepicker.dpDiv
+ .css("top", position.top + 30)
+ .css("left", position.left);
+ };
+
+ this.focus = function () {
+ $input.focus();
+ };
+
+ this.loadValue = function (item) {
+ defaultValue = item[args.column.field];
+ $input.val(defaultValue);
+ $input[0].defaultValue = defaultValue;
+ $input.select();
+ };
+
+ this.serializeValue = function () {
+ return $input.val();
+ };
+
+ this.applyValue = function (item, state) {
+ item[args.column.field] = state;
+ };
+
+ this.isValueChanged = function () {
+ return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
+ };
+
+ this.validate = function () {
+ return {
+ valid:true,
+ msg:null
+ };
+ };
+
+ this.init();
+ },
+
+ YesNoSelectCellEditor:function (args) {
+ var $select;
+ var defaultValue;
+ var scope = this;
+
+ this.init = function () {
+ $select = $("<SELECT tabIndex='0' class='editor-yesno'><OPTION value='yes'>Yes</OPTION><OPTION value='no'>No</OPTION></SELECT>");
+ $select.appendTo(args.container);
+ $select.focus();
+ };
+
+ this.destroy = function () {
+ $select.remove();
+ };
+
+ this.focus = function () {
+ $select.focus();
+ };
+
+ this.loadValue = function (item) {
+ $select.val((defaultValue = item[args.column.field]) ? "yes" : "no");
+ $select.select();
+ };
+
+ this.serializeValue = function () {
+ return ($select.val() == "yes");
+ };
+
+ this.applyValue = function (item, state) {
+ item[args.column.field] = state;
+ };
+
+ this.isValueChanged = function () {
+ return ($select.val() != defaultValue);
+ };
+
+ this.validate = function () {
+ return {
+ valid:true,
+ msg:null
+ };
+ };
+
+ this.init();
+ },
+
+ YesNoCheckboxCellEditor:function (args) {
+ var $select;
+ var defaultValue;
+ var scope = this;
+
+ this.init = function () {
+ $select = $("<INPUT type=checkbox value='true' class='editor-checkbox' hideFocus>");
+ $select.appendTo(args.container);
+ $select.focus();
+ };
+
+ this.destroy = function () {
+ $select.remove();
+ };
+
+ this.focus = function () {
+ $select.focus();
+ };
+
+ this.loadValue = function (item) {
+ defaultValue = item[args.column.field];
+ if (defaultValue) {
+ $select.attr("checked", "checked");
+ } else {
+ $select.removeAttr("checked");
+ }
+ };
+
+ this.serializeValue = function () {
+ return $select.attr("checked");
+ };
+
+ this.applyValue = function (item, state) {
+ item[args.column.field] = state;
+ };
+
+ this.isValueChanged = function () {
+ return ($select.attr("checked") != defaultValue);
+ };
+
+ this.validate = function () {
+ return {
+ valid:true,
+ msg:null
+ };
+ };
+
+ this.init();
+ },
+
+ PercentCompleteCellEditor:function (args) {
+ var $input, $picker;
+ var defaultValue;
+ var scope = this;
+
+ this.init = function () {
+ $input = $("<INPUT type=text class='editor-percentcomplete' />");
+ $input.width($(args.container).innerWidth() - 25);
+ $input.appendTo(args.container);
+
+ $picker = $("<div class='editor-percentcomplete-picker' />").appendTo(args.container);
+ $picker.append("<div class='editor-percentcomplete-helper'><div class='editor-percentcomplete-wrapper'><div class='editor-percentcomplete-slider' /><div class='editor-percentcomplete-buttons' /></div></div>");
+
+ $picker.find(".editor-percentcomplete-buttons").append("<button val=0>Not started</button><br/><button val=50>In Progress</button><br/><button val=100>Complete</button>");
+
+ $input.focus().select();
+
+ $picker.find(".editor-percentcomplete-slider").slider({
+ orientation:"vertical",
+ range:"min",
+ value:defaultValue,
+ slide:function (event, ui) {
+ $input.val(ui.value)
+ }
+ });
+
+ $picker.find(".editor-percentcomplete-buttons button").bind("click", function (e) {
+ $input.val($(this).attr("val"));
+ $picker.find(".editor-percentcomplete-slider").slider("value", $(this).attr("val"));
+ })
+ };
+
+ this.destroy = function () {
+ $input.remove();
+ $picker.remove();
+ };
+
+ this.focus = function () {
+ $input.focus();
+ };
+
+ this.loadValue = function (item) {
+ $input.val(defaultValue = item[args.column.field]);
+ $input.select();
+ };
+
+ this.serializeValue = function () {
+ return parseInt($input.val(), 10) || 0;
+ };
+
+ this.applyValue = function (item, state) {
+ item[args.column.field] = state;
+ };
+
+ this.isValueChanged = function () {
+ return (!($input.val() == "" && defaultValue == null)) && ((parseInt($input.val(), 10) || 0) != defaultValue);
+ };
+
+ this.validate = function () {
+ if (isNaN(parseInt($input.val(), 10))) {
+ return {
+ valid:false,
+ msg:"Please enter a valid positive number"
+ };
+ }
- $.extend(window, SlickEditor);
+ return {
+ valid:true,
+ msg:null
+ };
+ };
+ this.init();
+ },
+
+ StarCellEditor:function (args) {
+ var $input;
+ var defaultValue;
+ var scope = this;
+
+ function toggle(e) {
+ if (e.type == "keydown" && e.which != 32) {
+ return;
+ }
+
+ if ($input.css("opacity") == "1") {
+ $input.css("opacity", 0.5);
+ } else {
+ $input.css("opacity", 1);
+ }
+
+ e.preventDefault();
+ e.stopPropagation();
+ return false;
+ }
+
+ this.init = function () {
+ $input = $("<IMG src='../images/bullet_star.png' align=absmiddle tabIndex=0 title='Click or press Space to toggle' />")
+ .bind("click keydown", toggle)
+ .appendTo(args.container)
+ .focus();
+ };
+
+ this.destroy = function () {
+ $input.unbind("click keydown", toggle);
+ $input.remove();
+ };
+
+ this.focus = function () {
+ $input.focus();
+ };
+
+ this.loadValue = function (item) {
+ defaultValue = item[args.column.field];
+ $input.css("opacity", defaultValue ? 1 : 0.2);
+ };
+
+ this.serializeValue = function () {
+ return ($input.css("opacity") == "1");
+ };
+
+ this.applyValue = function (item, state) {
+ item[args.column.field] = state;
+ };
+
+ this.isValueChanged = function () {
+ return defaultValue != ($input.css("opacity") == "1");
+ };
+
+ this.validate = function () {
+ return {
+ valid:true,
+ msg:null
+ };
+ };
+
+ this.init();
+ },
+
+ /*
+ * An example of a "detached" editor.
+ * The UI is added onto document BODY and .position(), .show() and .hide() are implemented.
+ * KeyDown events are also handled to provide handling for Tab, Shift-Tab, Esc and Ctrl-Enter.
+ */
+ LongTextCellEditor:function (args) {
+ var $input, $wrapper;
+ var defaultValue;
+ var scope = this;
+
+ this.init = function () {
+ var $container = $("body");
+
+ $wrapper = $("<DIV style='z-index:10000;position:absolute;background:white;padding:5px;border:3px solid gray; -moz-border-radius:10px; border-radius:10px;'/>")
+ .appendTo($container);
+
+ $input = $("<TEXTAREA hidefocus rows=5 style='backround:white;width:250px;height:80px;border:0;outline:0'>")
+ .appendTo($wrapper);
+
+ $("<DIV style='text-align:right'><BUTTON>Save</BUTTON><BUTTON>Cancel</BUTTON></DIV>")
+ .appendTo($wrapper);
+
+ $wrapper.find("button:first").bind("click", this.save);
+ $wrapper.find("button:last").bind("click", this.cancel);
+ $input.bind("keydown", this.handleKeyDown);
+
+ scope.position(args.position);
+ $input.focus().select();
+ };
+
+ this.handleKeyDown = function (e) {
+ if (e.which == $.ui.keyCode.ENTER && e.ctrlKey) {
+ scope.save();
+ } else if (e.which == $.ui.keyCode.ESCAPE) {
+ e.preventDefault();
+ scope.cancel();
+ } else if (e.which == $.ui.keyCode.TAB && e.shiftKey) {
+ e.preventDefault();
+ grid.navigatePrev();
+ } else if (e.which == $.ui.keyCode.TAB) {
+ e.preventDefault();
+ grid.navigateNext();
+ }
+ };
+
+ this.save = function () {
+ args.commitChanges();
+ };
+
+ this.cancel = function () {
+ $input.val(defaultValue);
+ args.cancelChanges();
+ };
+
+ this.hide = function () {
+ $wrapper.hide();
+ };
+
+ this.show = function () {
+ $wrapper.show();
+ };
+
+ this.position = function (position) {
+ $wrapper
+ .css("top", position.top - 5)
+ .css("left", position.left - 5)
+ };
+
+ this.destroy = function () {
+ $wrapper.remove();
+ };
+
+ this.focus = function () {
+ $input.focus();
+ };
+
+ this.loadValue = function (item) {
+ $input.val(defaultValue = item[args.column.field]);
+ $input.select();
+ };
+
+ this.serializeValue = function () {
+ return $input.val();
+ };
+
+ this.applyValue = function (item, state) {
+ item[args.column.field] = state;
+ };
+
+ this.isValueChanged = function () {
+ return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
+ };
+
+ this.validate = function () {
+ return {
+ valid:true,
+ msg:null
+ };
+ };
+
+ this.init();
+ }
+ };
+
+ $.extend(window, SlickEditor);
})(jQuery);
diff --git a/slick.grid.css b/slick.grid.css
index b817638..db7fca1 100644
--- a/slick.grid.css
+++ b/slick.grid.css
@@ -5,154 +5,153 @@ No built-in (selected, editable, highlight, flashing, invalid, loading, :focus)
classes should alter those!
*/
-
.slick-header.ui-state-default, .slick-headerrow.ui-state-default {
- width: 100%;
- overflow: hidden;
- border-left: 0px;
+ width: 100%;
+ overflow: hidden;
+ border-left: 0px;
}
.slick-header-columns, .slick-headerrow-columns {
- width: 999999px;
- position: relative;
- white-space: nowrap;
- cursor: default;
- overflow: hidden;
+ width: 999999px;
+ position: relative;
+ white-space: nowrap;
+ cursor: default;
+ overflow: hidden;
}
.slick-header-column.ui-state-default {
- position: relative;
- display: inline-block;
- overflow: hidden;
- text-overflow: ellipsis;
- height: 16px;
- line-height: 16px;
- margin: 0;
- padding: 4px;
- border-right: 1px solid silver;
- border-left: 0px;
- border-top: 0px;
- border-bottom: 0px;
- float: left;
+ position: relative;
+ display: inline-block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ height: 16px;
+ line-height: 16px;
+ margin: 0;
+ padding: 4px;
+ border-right: 1px solid silver;
+ border-left: 0px;
+ border-top: 0px;
+ border-bottom: 0px;
+ float: left;
}
.slick-headerrow-column.ui-state-default {
- padding: 4px;
+ padding: 4px;
}
.slick-header-column-sorted {
- font-style: italic;
+ font-style: italic;
}
.slick-sort-indicator {
- display: inline-block;
- width: 8px;
- height: 5px;
- margin-left: 4px;
+ display: inline-block;
+ width: 8px;
+ height: 5px;
+ margin-left: 4px;
}
.slick-sort-indicator-desc {
- background: url(images/sort-desc.gif);
+ background: url(images/sort-desc.gif);
}
.slick-sort-indicator-asc {
- background: url(images/sort-asc.gif);
+ background: url(images/sort-asc.gif);
}
.slick-resizable-handle {
- position: absolute;
- font-size: 0.1px;
- display: block;
- cursor: col-resize;
- width: 4px;
- right: 0px;
- top: 0;
- height: 100%;
+ position: absolute;
+ font-size: 0.1px;
+ display: block;
+ cursor: col-resize;
+ width: 4px;
+ right: 0px;
+ top: 0;
+ height: 100%;
}
.slick-sortable-placeholder {
- background: silver;
+ background: silver;
}
.grid-canvas {
- position: relative;
- outline: 0;
+ position: relative;
+ outline: 0;
}
.slick-row.ui-widget-content, .slick-row.ui-state-active {
- position: absolute;
- border: 0px;
+ position: absolute;
+ border: 0px;
}
.slick-cell, .slick-headerrow-column {
- position: absolute;
+ position: absolute;
- border: 1px solid transparent;
- border-right: 1px dotted silver;
- border-bottom-color: silver;
+ border: 1px solid transparent;
+ border-right: 1px dotted silver;
+ border-bottom-color: silver;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- vertical-align: middle;
- z-index: 1;
- padding: 1px 2px 2px 1px;
- margin: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ vertical-align: middle;
+ z-index: 1;
+ padding: 1px 2px 2px 1px;
+ margin: 0;
- white-space: nowrap;
+ white-space: nowrap;
- cursor: default;
+ cursor: default;
}
.slick-group {
}
.slick-group-toggle {
- display: inline-block;
+ display: inline-block;
}
.slick-cell.highlighted {
- background: lightskyblue;
- background: rgba(0,0,255,0.2);
- -webkit-transition: all 0.5s;
- -moz-transition: all 0.5s;
- transition: all 0.5s;
+ background: lightskyblue;
+ background: rgba(0, 0, 255, 0.2);
+ -webkit-transition: all 0.5s;
+ -moz-transition: all 0.5s;
+ transition: all 0.5s;
}
.slick-cell.flashing {
- border: 1px solid red !important;
+ border: 1px solid red !important;
}
.slick-cell.editable {
- z-index: 11;
- overflow: visible;
- background: white;
- border-color: black;
- border-style: solid;
+ z-index: 11;
+ overflow: visible;
+ background: white;
+ border-color: black;
+ border-style: solid;
}
.slick-cell:focus {
- outline: none;
+ outline: none;
}
.slick-reorder-proxy {
- display: inline-block;
- background: blue;
- opacity: 0.15;
- filter: alpha(opacity=15);
- cursor: move;
+ display: inline-block;
+ background: blue;
+ opacity: 0.15;
+ filter: alpha(opacity = 15);
+ cursor: move;
}
.slick-reorder-guide {
- display: inline-block;
- height: 2px;
- background: blue;
- opacity: 0.7;
- filter: alpha(opacity=70);
+ display: inline-block;
+ height: 2px;
+ background: blue;
+ opacity: 0.7;
+ filter: alpha(opacity = 70);
}
.slick-selection {
- z-index: 10;
- position: absolute;
- border: 2px dashed black;
+ z-index: 10;
+ position: absolute;
+ border: 2px dashed black;
} \ No newline at end of file
diff --git a/slick.grid.js b/slick.grid.js
index 37500e3..408c068 100644
--- a/slick.grid.js
+++ b/slick.grid.js
@@ -1,8 +1,9 @@
/**
* @license
- * (c) 2009-2010 Michael Leibman
+ * (c) 2009-2012 Michael Leibman
* michael{dot}leibman{at}gmail{dot}com
* http://github.com/mleibman/slickgrid
+ *
* Distributed under MIT license.
* All rights reserved.
*
@@ -17,2605 +18,2658 @@
// make sure required JavaScript modules are loaded
if (typeof jQuery === "undefined") {
- throw "SlickGrid requires jquery module to be loaded";
+ throw "SlickGrid requires jquery module to be loaded";
}
if (!jQuery.fn.drag) {
- throw "SlickGrid requires jquery.event.drag module to be loaded";
+ throw "SlickGrid requires jquery.event.drag module to be loaded";
}
if (typeof Slick === "undefined") {
- throw "slick.core.js not loaded";
+ throw "slick.core.js not loaded";
}
-(function($) {
- // Slick.Grid
- $.extend(true, window, {
- Slick: {
- Grid: SlickGrid
- }
- });
+(function ($) {
+ // Slick.Grid
+ $.extend(true, window, {
+ Slick:{
+ Grid:SlickGrid
+ }
+ });
+
+ // shared across all grids on the page
+ var scrollbarDimensions;
+ var maxSupportedCssHeight; // browser's breaking point
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ // SlickGrid class implementation (available as Slick.Grid)
+
+ /**
+ * Creates a new instance of the grid.
+ * @class SlickGrid
+ * @constructor
+ * @param {Node} container Container node to create the grid in.
+ * @param {Array,Object} data An array of objects for databinding.
+ * @param {Array} columns An array of column definitions.
+ * @param {Object} options Grid options.
+ **/
+ function SlickGrid(container, data, columns, options) {
+ // settings
+ var defaults = {
+ headerHeight:25,
+ rowHeight:25,
+ defaultColumnWidth:80,
+ enableAddRow:false,
+ leaveSpaceForNewRows:false,
+ editable:false,
+ autoEdit:true,
+ enableCellNavigation:true,
+ enableColumnReorder:true,
+ asyncEditorLoading:false,
+ asyncEditorLoadDelay:100,
+ forceFitColumns:false,
+ enableAsyncPostRender:false,
+ asyncPostRenderDelay:60,
+ autoHeight:false,
+ editorLock:Slick.GlobalEditorLock,
+ showHeaderRow:false,
+ headerRowHeight:25,
+ showTopPanel:false,
+ topPanelHeight:25,
+ formatterFactory:null,
+ editorFactory:null,
+ cellFlashingCssClass:"flashing",
+ selectedCellCssClass:"selected",
+ multiSelect:true,
+ enableTextSelectionOnCells:false,
+ dataItemColumnValueExtractor:null
+ };
+
+ var columnDefaults = {
+ name:"",
+ resizable:true,
+ sortable:false,
+ minWidth:30,
+ rerenderOnResize:false,
+ headerCssClass:null
+ };
+
+ // scroller
+ var th; // virtual height
+ var h; // real scrollable height
+ var ph; // page height
+ var n; // number of pages
+ var cj; // "jumpiness" coefficient
+
+ var page = 0; // current page
+ var offset = 0; // current page offset
+ var scrollDir = 1;
+
+ // private
+ var $container;
+ var uid = "slickgrid_" + Math.round(1000000 * Math.random());
+ var self = this;
+ var $headerScroller;
+ var $headers;
+ var $headerRow, $headerRowScroller;
+ var $topPanelScroller;
+ var $topPanel;
+ var $viewport;
+ var $canvas;
+ var $style;
+ var stylesheet;
+ var viewportH, viewportW;
+ var viewportHasHScroll;
+ var headerColumnWidthDiff, headerColumnHeightDiff, cellWidthDiff, cellHeightDiff; // padding+border
+ var absoluteColumnMinWidth;
+
+ var activePosX;
+ var activeRow, activeCell;
+ var activeCellNode = null;
+ var currentEditor = null;
+ var serializedEditorValue;
+ var editController;
+
+ var rowsCache = {};
+ var renderedRows = 0;
+ var numVisibleRows;
+ var prevScrollTop = 0;
+ var scrollTop = 0;
+ var lastRenderedScrollTop = 0;
+ var prevScrollLeft = 0;
+ var avgRowRenderTime = 10;
+
+ var selectionModel;
+ var selectedRows = [];
+
+ var plugins = [];
+ var cellCssClasses = {};
+
+ var columnsById = {};
+ var sortColumnId;
+ var sortAsc = true;
+
+ // async call handles
+ var h_editorLoader = null;
+ var h_render = null;
+ var h_postrender = null;
+ var postProcessedRows = {};
+ var postProcessToRow = null;
+ var postProcessFromRow = null;
+
+ // perf counters
+ var counter_rows_rendered = 0;
+ var counter_rows_removed = 0;
- // shared across all grids on the page
- var scrollbarDimensions;
- var maxSupportedCssHeight; // browser's breaking point
//////////////////////////////////////////////////////////////////////////////////////////////
- // SlickGrid class implementation (available as Slick.Grid)
-
- /**
- * @param {Node} container Container node to create the grid in.
- * @param {Array,Object} data An array of objects for databinding.
- * @param {Array} columns An array of column definitions.
- * @param {Object} options Grid options.
- **/
- function SlickGrid(container,data,columns,options) {
- /// <summary>
- /// Create and manage virtual grid in the specified $container,
- /// connecting it to the specified data source. Data is presented
- /// as a grid with the specified columns and data.length rows.
- /// Options alter behaviour of the grid.
- /// </summary>
-
- // settings
- var defaults = {
- headerHeight: 25,
- rowHeight: 25,
- defaultColumnWidth: 80,
- enableAddRow: false,
- leaveSpaceForNewRows: false,
- editable: false,
- autoEdit: true,
- enableCellNavigation: true,
- enableColumnReorder: true,
- asyncEditorLoading: false,
- asyncEditorLoadDelay: 100,
- forceFitColumns: false,
- enableAsyncPostRender: false,
- asyncPostRenderDelay: 60,
- autoHeight: false,
- editorLock: Slick.GlobalEditorLock,
- showHeaderRow: false,
- headerRowHeight: 25,
- showTopPanel: false,
- topPanelHeight: 25,
- formatterFactory: null,
- editorFactory: null,
- cellFlashingCssClass: "flashing",
- selectedCellCssClass: "selected",
- multiSelect: true,
- enableTextSelectionOnCells: false,
- dataItemColumnValueExtractor: null
- };
-
- var columnDefaults = {
- name: "",
- resizable: true,
- sortable: false,
- minWidth: 30,
- rerenderOnResize: false,
- headerCssClass: null
- };
-
- // scroller
- var th; // virtual height
- var h; // real scrollable height
- var ph; // page height
- var n; // number of pages
- var cj; // "jumpiness" coefficient
-
- var page = 0; // current page
- var offset = 0; // current page offset
- var scrollDir = 1;
-
- // private
- var $container;
- var uid = "slickgrid_" + Math.round(1000000 * Math.random());
- var self = this;
- var $headerScroller;
- var $headers;
- var $headerRow, $headerRowScroller;
- var $topPanelScroller;
- var $topPanel;
- var $viewport;
- var $canvas;
- var $style;
- var stylesheet;
- var viewportH, viewportW;
- var viewportHasHScroll;
- var headerColumnWidthDiff, headerColumnHeightDiff, cellWidthDiff, cellHeightDiff; // padding+border
- var absoluteColumnMinWidth;
-
- var activePosX;
- var activeRow, activeCell;
- var activeCellNode = null;
- var currentEditor = null;
- var serializedEditorValue;
- var editController;
-
- var rowsCache = {};
- var renderedRows = 0;
- var numVisibleRows;
- var prevScrollTop = 0;
- var scrollTop = 0;
- var lastRenderedScrollTop = 0;
- var prevScrollLeft = 0;
- var avgRowRenderTime = 10;
-
- var selectionModel;
- var selectedRows = [];
-
- var plugins = [];
- var cellCssClasses = {};
-
- var columnsById = {};
- var sortColumnId;
- var sortAsc = true;
-
- // async call handles
- var h_editorLoader = null;
- var h_render = null;
- var h_postrender = null;
- var postProcessedRows = {};
- var postProcessToRow = null;
- var postProcessFromRow = null;
-
- // perf counters
- var counter_rows_rendered = 0;
- var counter_rows_removed = 0;
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////
- // Initialization
-
- function init() {
- /// <summary>
- /// Initialize 'this' (self) instance of a SlickGrid.
- /// This function is called by the constructor.
- /// </summary>
-
- $container = $(container);
- if($container.length < 1) {
- throw new Error("SlickGrid requires a valid container, "+container+" does not exist in the DOM.");
- }
-
- maxSupportedCssHeight = getMaxSupportedCssHeight();
-
- scrollbarDimensions = scrollbarDimensions || measureScrollbar(); // skip measurement if already have dimensions
- options = $.extend({},defaults,options);
- columnDefaults.width = options.defaultColumnWidth;
-
- // validate loaded JavaScript modules against requested options
- if (options.enableColumnReorder && !$.fn.sortable) {
- throw new Error("SlickGrid's \"enableColumnReorder = true\" option requires jquery-ui.sortable module to be loaded");
- }
-
- editController = {
- "commitCurrentEdit": commitCurrentEdit,
- "cancelCurrentEdit": cancelCurrentEdit
- };
-
- $container
- .empty()
- .attr("tabIndex",0)
- .attr("hideFocus",true)
- .css("overflow","hidden")
- .css("outline",0)
- .addClass(uid)
- .addClass("ui-widget");
+ // Initialization
+
+ function init() {
+ $container = $(container);
+ if ($container.length < 1) {
+ throw new Error("SlickGrid requires a valid container, " + container + " does not exist in the DOM.");
+ }
+
+ // calculate these only once and share between grid instances
+ maxSupportedCssHeight = maxSupportedCssHeight || getMaxSupportedCssHeight();
+ scrollbarDimensions = scrollbarDimensions || measureScrollbar();
+
+ options = $.extend({}, defaults, options);
+ columnDefaults.width = options.defaultColumnWidth;
+
+ // validate loaded JavaScript modules against requested options
+ if (options.enableColumnReorder && !$.fn.sortable) {
+ throw new Error("SlickGrid's 'enableColumnReorder = true' option requires jquery-ui.sortable module to be loaded");
+ }
+
+ editController = {
+ "commitCurrentEdit":commitCurrentEdit,
+ "cancelCurrentEdit":cancelCurrentEdit
+ };
+
+ $container
+ .empty()
+ .attr("tabIndex", 0)
+ .attr("hideFocus", true)
+ .css("overflow", "hidden")
+ .css("outline", 0)
+ .addClass(uid)
+ .addClass("ui-widget");
+
+ // set up a positioning container if needed
+ if (!/relative|absolute|fixed/.test($container.css("position"))) {
+ $container.css("position", "relative");
+ }
+
+ $headerScroller = $("<div class='slick-header ui-state-default' style='overflow:hidden;position:relative;' />").appendTo($container);
+ $headers = $("<div class='slick-header-columns' style='width:10000px; left:-1000px' />").appendTo($headerScroller);
+
+ $headerRowScroller = $("<div class='slick-headerrow ui-state-default' style='overflow:hidden;position:relative;' />").appendTo($container);
+ $headerRow = $("<div class='slick-headerrow-columns' />").appendTo($headerRowScroller);
+
+ $topPanelScroller = $("<div class='slick-top-panel-scroller ui-state-default' style='overflow:hidden;position:relative;' />").appendTo($container);
+ $topPanel = $("<div class='slick-top-panel' style='width:10000px' />").appendTo($topPanelScroller);
+
+ if (!options.showTopPanel) {
+ $topPanelScroller.hide();
+ }
+
+ if (!options.showHeaderRow) {
+ $headerRowScroller.hide();
+ }
+
+ $viewport = $("<div class='slick-viewport' tabIndex='0' hideFocus style='width:100%;overflow-x:auto;outline:0;position:relative;overflow-y:auto;'>").appendTo($container);
+ $canvas = $("<div class='grid-canvas' tabIndex='0' hideFocus />").appendTo($viewport);
+
+ // header columns and cells may have different padding/border skewing width calculations (box-sizing, hello?)
+ // calculate the diff so we can set consistent sizes
+ measureCellPaddingAndBorder();
+
+ // for usability reasons, all text selection in SlickGrid is disabled
+ // with the exception of input and textarea elements (selection must
+ // be enabled there so that editors work as expected); note that
+ // selection in grid cells (grid body) is already unavailable in
+ // all browsers except IE
+ disableSelection($headers); // disable all text selection in header (including input and textarea)
+
+ if (!options.enableTextSelectionOnCells) {
+ // disable text selection in grid cells except in input and textarea elements
+ // (this is IE-specific, because selectstart event will only fire in IE)
+ $viewport.bind("selectstart.ui", function (event) {
+ return $(event.target).is("input,textarea");
+ });
+ }
+
+ viewportW = parseFloat($.css($container[0], "width", true));
+
+ createColumnHeaders();
+ setupColumnSort();
+ createCssRules();
+ resizeAndRender();
+
+ bindAncestorScrollEvents();
+ $viewport.bind("scroll.slickgrid", handleScroll);
+ $container.bind("resize.slickgrid", resizeAndRender);
+ $headerScroller
+ .bind("contextmenu.slickgrid", handleHeaderContextMenu)
+ .bind("click.slickgrid", handleHeaderClick);
+
+ $canvas
+ .bind("keydown.slickgrid", handleKeyDown)
+ .bind("click.slickgrid", handleClick)
+ .bind("dblclick.slickgrid", handleDblClick)
+ .bind("contextmenu.slickgrid", handleContextMenu)
+ .bind("draginit", handleDragInit)
+ .bind("dragstart", handleDragStart)
+ .bind("drag", handleDrag)
+ .bind("dragend", handleDragEnd);
+
+ $canvas.delegate(".slick-cell", "mouseenter", handleMouseEnter);
+ $canvas.delegate(".slick-cell", "mouseleave", handleMouseLeave);
+ }
- // set up a positioning container if needed
- if (!/relative|absolute|fixed/.test($container.css("position")))
- $container.css("position","relative");
+ function registerPlugin(plugin) {
+ plugins.unshift(plugin);
+ plugin.init(self);
+ }
- $headerScroller = $("<div class='slick-header ui-state-default' style='overflow:hidden;position:relative;' />").appendTo($container);
- $headers = $("<div class='slick-header-columns' style='width:10000px; left:-1000px' />").appendTo($headerScroller);
+ function unregisterPlugin(plugin) {
+ for (var i = plugins.length; i >= 0; i--) {
+ if (plugins[i] === plugin) {
+ if (plugins[i].destroy) {
+ plugins[i].destroy();
+ }
+ plugins.splice(i, 1);
+ break;
+ }
+ }
+ }
- $headerRowScroller = $("<div class='slick-headerrow ui-state-default' style='overflow:hidden;position:relative;' />").appendTo($container);
- $headerRow = $("<div class='slick-headerrow-columns' />").appendTo($headerRowScroller);
+ function setSelectionModel(model) {
+ if (selectionModel) {
+ selectionModel.onSelectedRangesChanged.unsubscribe(handleSelectedRangesChanged);
+ if (selectionModel.destroy) {
+ selectionModel.destroy();
+ }
+ }
- $topPanelScroller = $("<div class='slick-top-panel-scroller ui-state-default' style='overflow:hidden;position:relative;' />").appendTo($container);
- $topPanel = $("<div class='slick-top-panel' style='width:10000px' />").appendTo($topPanelScroller);
+ selectionModel = model;
+ if (selectionModel) {
+ selectionModel.init(self);
+ selectionModel.onSelectedRangesChanged.subscribe(handleSelectedRangesChanged);
+ }
+ }
- if (!options.showTopPanel) {
- $topPanelScroller.hide();
- }
+ function getSelectionModel() {
+ return selectionModel;
+ }
- if (!options.showHeaderRow) {
- $headerRowScroller.hide();
- }
+ function getCanvasNode() {
+ return $canvas[0];
+ }
- $viewport = $("<div class='slick-viewport' tabIndex='0' hideFocus style='width:100%;overflow-x:auto;outline:0;position:relative;overflow-y:auto;'>").appendTo($container);
- $canvas = $("<div class='grid-canvas' tabIndex='0' hideFocus />").appendTo($viewport);
-
- // header columns and cells may have different padding/border skewing width calculations (box-sizing, hello?)
- // calculate the diff so we can set consistent sizes
- measureCellPaddingAndBorder();
-
- // for usability reasons, all text selection in SlickGrid is disabled
- // with the exception of input and textarea elements (selection must
- // be enabled there so that editors work as expected); note that
- // selection in grid cells (grid body) is already unavailable in
- // all browsers except IE
- disableSelection($headers); // disable all text selection in header (including input and textarea)
-
- if (!options.enableTextSelectionOnCells) {
- // disable text selection in grid cells except in input and textarea elements
- // (this is IE-specific, because selectstart event will only fire in IE)
- $viewport.bind("selectstart.ui", function (event) {
- return $(event.target).is("input,textarea");
- });
- }
+ function measureScrollbar() {
+ var $c = $("<div style='position:absolute; top:-10000px; left:-10000px; width:100px; height:100px; overflow:scroll;'></div>").appendTo("body");
+ var dim = {
+ width:$c.width() - $c[0].clientWidth,
+ height:$c.height() - $c[0].clientHeight
+ };
+ $c.remove();
+ return dim;
+ }
- viewportW = parseFloat($.css($container[0], "width", true));
+ function getRowWidth() {
+ var rowWidth = 0;
+ var i = columns.length;
+ while (i--) {
+ rowWidth += (columns[i].width || columnDefaults.width);
+ }
+ return rowWidth;
+ }
- createColumnHeaders();
- setupColumnSort();
- createCssRules();
- resizeAndRender();
+ function setCanvasWidth(width) {
+ $canvas.width(width);
+ $headerRow.width(width);
+ viewportHasHScroll = (width > viewportW - scrollbarDimensions.width);
+ }
- bindAncestorScrollEvents();
- $viewport.bind("scroll.slickgrid", handleScroll);
- $container.bind("resize.slickgrid", resizeAndRender);
- $headerScroller
- .bind("contextmenu.slickgrid", handleHeaderContextMenu)
- .bind("click.slickgrid", handleHeaderClick);
+ function disableSelection($target) {
+ if ($target && $target.jquery) {
+ $target
+ .attr("unselectable", "on")
+ .css("MozUserSelect", "none")
+ .bind("selectstart.ui", function () {
+ return false;
+ }); // from jquery:ui.core.js 1.7.2
+ }
+ }
- $canvas
- .bind("keydown.slickgrid", handleKeyDown)
- .bind("click.slickgrid", handleClick)
- .bind("dblclick.slickgrid", handleDblClick)
- .bind("contextmenu.slickgrid", handleContextMenu)
- .bind("draginit", handleDragInit)
- .bind("dragstart", handleDragStart)
- .bind("drag", handleDrag)
- .bind("dragend", handleDragEnd);
+ function getMaxSupportedCssHeight() {
+ var increment = 1000000;
+ var supportedHeight = increment;
+ // FF reports the height back but still renders blank after ~6M px
+ var testUpTo = ($.browser.mozilla) ? 5000000 : 1000000000;
+ var div = $("<div style='display:none' />").appendTo(document.body);
- $canvas.delegate(".slick-cell", "mouseenter", handleMouseEnter);
- $canvas.delegate(".slick-cell", "mouseleave", handleMouseLeave);
+ while (supportedHeight <= testUpTo) {
+ div.css("height", supportedHeight + increment);
+ if (div.height() !== supportedHeight + increment) {
+ break;
+ } else {
+ supportedHeight += increment;
}
+ }
- function registerPlugin(plugin) {
- plugins.unshift(plugin);
- plugin.init(self);
- }
+ div.remove();
+ return supportedHeight;
+ }
- function unregisterPlugin(plugin) {
- for (var i = plugins.length; i >= 0; i--) {
- if (plugins[i] === plugin) {
- if (plugins[i].destroy) {
- plugins[i].destroy();
- }
- plugins.splice(i, 1);
- break;
- }
- }
+ // TODO: this is static. need to handle page mutation.
+ function bindAncestorScrollEvents() {
+ var elem = $canvas[0];
+ while ((elem = elem.parentNode) != document.body && elem != null) {
+ // bind to scroll containers only
+ if (elem == $viewport[0] || elem.scrollWidth != elem.clientWidth || elem.scrollHeight != elem.clientHeight) {
+ $(elem).bind("scroll.slickgrid", handleActiveCellPositionChange);
}
+ }
+ }
- function setSelectionModel(model) {
- if (selectionModel) {
- selectionModel.onSelectedRangesChanged.unsubscribe(handleSelectedRangesChanged);
- if (selectionModel.destroy) {
- selectionModel.destroy();
- }
- }
+ function unbindAncestorScrollEvents() {
+ $canvas.parents().unbind("scroll.slickgrid");
+ }
- selectionModel = model;
- if (selectionModel) {
- selectionModel.init(self);
- selectionModel.onSelectedRangesChanged.subscribe(handleSelectedRangesChanged);
- }
- }
+ function updateColumnHeader(columnId, title, toolTip) {
+ var idx = getColumnIndex(columnId);
+ var $header = $headers.children().eq(idx);
+ if ($header) {
+ columns[idx].name = title;
+ columns[idx].toolTip = toolTip;
+ $header
+ .attr("title", toolTip || title || "")
+ .children().eq(0).html(title);
+ }
+ }
- function getSelectionModel() {
- return selectionModel;
- }
+ function getHeaderRow() {
+ return $headerRow[0];
+ }
- function getCanvasNode() {
- return $canvas[0];
- }
+ function getHeaderRowColumn(columnId) {
+ var idx = getColumnIndex(columnId);
+ var $header = $headerRow.children().eq(idx);
+ return $header && $header[0];
+ }
- function measureScrollbar() {
- /// <summary>
- /// Measure width of a vertical scrollbar
- /// and height of a horizontal scrollbar.
- /// </summary
- /// <returns>
- /// { width: pixelWidth, height: pixelHeight }
- /// </returns>
- var $c = $("<div style='position:absolute; top:-10000px; left:-10000px; width:100px; height:100px; overflow:scroll;'></div>").appendTo("body");
- var dim = { width: $c.width() - $c[0].clientWidth, height: $c.height() - $c[0].clientHeight };
- $c.remove();
- return dim;
- }
+ function createColumnHeaders() {
+ var i;
- function getRowWidth() {
- var rowWidth = 0;
- var i = columns.length;
- while (i--) {
- rowWidth += (columns[i].width || columnDefaults.width);
- }
- return rowWidth;
- }
+ function hoverBegin() {
+ $(this).addClass("ui-state-hover");
+ }
- function setCanvasWidth(width) {
- $canvas.width(width);
- $headerRow.width(width);
- viewportHasHScroll = (width > viewportW - scrollbarDimensions.width);
- }
+ function hoverEnd() {
+ $(this).removeClass("ui-state-hover");
+ }
- function disableSelection($target) {
- /// <summary>
- /// Disable text selection (using mouse) in
- /// the specified target.
- /// </summary
- if ($target && $target.jquery) {
- $target
- .attr('unselectable', 'on')
- .css('MozUserSelect', 'none')
- .bind('selectstart.ui', function() { return false; }); // from jquery:ui.core.js 1.7.2
- }
- }
+ $headers.empty();
+ $headerRow.empty();
+ columnsById = {};
- function getMaxSupportedCssHeight() {
- // return cached value if already calculated
- if (maxSupportedCssHeight) {
- return maxSupportedCssHeight;
- }
+ for (i = 0; i < columns.length; i++) {
+ var m = columns[i] = $.extend({}, columnDefaults, columns[i]);
+ columnsById[m.id] = i;
- var increment = 1000000;
- var supportedHeight = increment;
- // FF reports the height back but still renders blank after ~6M px
- var testUpTo = ($.browser.mozilla) ? 5000000 : 1000000000;
- var div = $("<div style='display:none' />").appendTo(document.body);
-
- while (supportedHeight <= testUpTo) {
- div.css("height", supportedHeight + increment);
- if (div.height() !== supportedHeight + increment)
- break;
- else
- supportedHeight += increment;
- }
+ var header = $("<div class='ui-state-default slick-header-column' id='" + uid + m.id + "' />")
+ .html("<span class='slick-column-name'>" + m.name + "</span>")
+ .width(m.width - headerColumnWidthDiff)
+ .attr("title", m.toolTip || m.name || "")
+ .data("fieldId", m.id)
+ .addClass(m.headerCssClass || "")
+ .appendTo($headers);
- div.remove();
- return supportedHeight;
+ if (options.enableColumnReorder || m.sortable) {
+ header.hover(hoverBegin, hoverEnd);
}
- // TODO: this is static. need to handle page mutation.
- function bindAncestorScrollEvents() {
- var elem = $canvas[0];
- while ((elem = elem.parentNode) != document.body) {
- // bind to scroll containers only
- if (elem == $viewport[0] || elem.scrollWidth != elem.clientWidth || elem.scrollHeight != elem.clientHeight)
- $(elem).bind("scroll.slickgrid", handleActiveCellPositionChange);
- }
+ if (m.sortable) {
+ header.append("<span class='slick-sort-indicator' />");
}
- function unbindAncestorScrollEvents() {
- $canvas.parents().unbind("scroll.slickgrid");
+ if (options.showHeaderRow) {
+ $("<div class='ui-state-default slick-headerrow-column l" + i + " r" + i + "'></div>")
+ .appendTo($headerRow);
}
+ }
- function updateColumnHeader(columnId, title, toolTip) {
- var idx = getColumnIndex(columnId);
- var $header = $headers.children().eq(idx);
- if ($header) {
- columns[idx].name = title;
- columns[idx].toolTip = toolTip;
- $header
- .attr("title", toolTip || title || "")
- .children().eq(0).html(title);
- }
- }
+ setSortColumn(sortColumnId, sortAsc);
+ setupColumnResize();
+ if (options.enableColumnReorder) {
+ setupColumnReorder();
+ }
+ }
- function getHeaderRow() {
- return $headerRow[0];
+ function setupColumnSort() {
+ $headers.click(function (e) {
+ if ($(e.target).hasClass("slick-resizable-handle")) {
+ return;
}
- function getHeaderRowColumn(columnId) {
- var idx = getColumnIndex(columnId);
- var $header = $headerRow.children().eq(idx);
- return $header && $header[0];
+ var $col = $(e.target).closest(".slick-header-column");
+ if (!$col.length) {
+ return;
}
- function createColumnHeaders() {
- var i;
-
- function hoverBegin() {
- $(this).addClass("ui-state-hover");
- }
- function hoverEnd() {
- $(this).removeClass("ui-state-hover");
- }
-
- $headers.empty();
- $headerRow.empty();
- columnsById = {};
-
- for (i = 0; i < columns.length; i++) {
- var m = columns[i] = $.extend({},columnDefaults,columns[i]);
- columnsById[m.id] = i;
+ var column = columns[getColumnIndex($col.data("fieldId"))];
+ if (column.sortable) {
+ if (!getEditorLock().commitCurrentEdit()) {
+ return;
+ }
- var header = $("<div class='ui-state-default slick-header-column' id='" + uid + m.id + "' />")
- .html("<span class='slick-column-name'>" + m.name + "</span>")
- .width(m.width - headerColumnWidthDiff)
- .attr("title", m.toolTip || m.name || "")
- .data("fieldId", m.id)
- .addClass(m.headerCssClass || "")
- .appendTo($headers);
+ if (column.id === sortColumnId) {
+ sortAsc = !sortAsc;
+ }
+ else {
+ sortColumnId = column.id;
+ sortAsc = true;
+ }
- if (options.enableColumnReorder || m.sortable) {
- header.hover(hoverBegin, hoverEnd);
- }
-
- if (m.sortable) {
- header.append("<span class='slick-sort-indicator' />");
- }
-
- if (options.showHeaderRow) {
- $("<div class='ui-state-default slick-headerrow-column l" + i + " r" + i +"'></div>")
- .appendTo($headerRow);
- }
- }
-
- setSortColumn(sortColumnId,sortAsc);
- setupColumnResize();
- if (options.enableColumnReorder) {
- setupColumnReorder();
- }
+ setSortColumn(sortColumnId, sortAsc);
+ trigger(self.onSort, {sortCol:column, sortAsc:sortAsc}, e);
}
+ });
+ }
- function setupColumnSort() {
- $headers.click(function(e) {
- if ($(e.target).hasClass("slick-resizable-handle")) {
- return;
- }
-
- var $col = $(e.target).closest(".slick-header-column");
- if (!$col.length)
- return;
-
- var column = columns[getColumnIndex($col.data("fieldId"))];
- if (column.sortable) {
- if (!getEditorLock().commitCurrentEdit())
- return;
+ function setupColumnReorder() {
+ $headers.sortable({
+ containment:"parent",
+ axis:"x",
+ cursor:"default",
+ tolerance:"intersection",
+ helper:"clone",
+ placeholder:"slick-sortable-placeholder ui-state-default slick-header-column",
+ forcePlaceholderSize:true,
+ start:function (e, ui) {
+ $(ui.helper).addClass("slick-header-column-active");
+ },
+ beforeStop:function (e, ui) {
+ $(ui.helper).removeClass("slick-header-column-active");
+ },
+ stop:function (e) {
+ if (!getEditorLock().commitCurrentEdit()) {
+ $(this).sortable("cancel");
+ return;
+ }
+
+ var reorderedIds = $headers.sortable("toArray");
+ var reorderedColumns = [];
+ for (var i = 0; i < reorderedIds.length; i++) {
+ reorderedColumns.push(columns[getColumnIndex(reorderedIds[i].replace(uid, ""))]);
+ }
+ setColumns(reorderedColumns);
+
+ trigger(self.onColumnsReordered, {});
+ e.stopPropagation();
+ setupColumnResize();
+ }
+ });
+ }
- if (column.id === sortColumnId) {
- sortAsc = !sortAsc;
+ function setupColumnResize() {
+ var $col, j, c, pageX, columnElements, minPageX, maxPageX, firstResizable, lastResizable, originalCanvasWidth;
+ columnElements = $headers.children();
+ columnElements.find(".slick-resizable-handle").remove();
+ columnElements.each(function (i, e) {
+ if (columns[i].resizable) {
+ if (firstResizable === undefined) {
+ firstResizable = i;
+ }
+ lastResizable = i;
+ }
+ });
+ if (firstResizable === undefined) {
+ return;
+ }
+ columnElements.each(function (i, e) {
+ if (i < firstResizable || (options.forceFitColumns && i >= lastResizable)) {
+ return;
+ }
+ $col = $(e);
+ $("<div class='slick-resizable-handle' />")
+ .appendTo(e)
+ .bind("dragstart", function (e, dd) {
+ if (!getEditorLock().commitCurrentEdit()) {
+ return false;
+ }
+ pageX = e.pageX;
+ $(this).parent().addClass("slick-header-column-active");
+ var shrinkLeewayOnRight = null, stretchLeewayOnRight = null;
+ // lock each column's width option to current width
+ columnElements.each(function (i, e) {
+ columns[i].previousWidth = $(e).outerWidth();
+ });
+ if (options.forceFitColumns) {
+ shrinkLeewayOnRight = 0;
+ stretchLeewayOnRight = 0;
+ // colums on right affect maxPageX/minPageX
+ for (j = i + 1; j < columnElements.length; j++) {
+ c = columns[j];
+ if (c.resizable) {
+ if (stretchLeewayOnRight !== null) {
+ if (c.maxWidth) {
+ stretchLeewayOnRight += c.maxWidth - c.previousWidth;
+ }
+ else {
+ stretchLeewayOnRight = null;
+ }
+ }
+ shrinkLeewayOnRight += c.previousWidth - Math.max(c.minWidth || 0, absoluteColumnMinWidth);
+ }
+ }
+ }
+ var shrinkLeewayOnLeft = 0, stretchLeewayOnLeft = 0;
+ for (j = 0; j <= i; j++) {
+ // columns on left only affect minPageX
+ c = columns[j];
+ if (c.resizable) {
+ if (stretchLeewayOnLeft !== null) {
+ if (c.maxWidth) {
+ stretchLeewayOnLeft += c.maxWidth - c.previousWidth;
}
else {
- sortColumnId = column.id;
- sortAsc = true;
+ stretchLeewayOnLeft = null;
}
-
- setSortColumn(sortColumnId,sortAsc);
- trigger(self.onSort, {sortCol:column,sortAsc:sortAsc}, e);
+ }
+ shrinkLeewayOnLeft += c.previousWidth - Math.max(c.minWidth || 0, absoluteColumnMinWidth);
}
- });
- }
-
- function setupColumnReorder() {
- $headers.sortable({
- containment: "parent",
- axis: "x",
- cursor: "default",
- tolerance: "intersection",
- helper: "clone",
- placeholder: "slick-sortable-placeholder ui-state-default slick-header-column",
- forcePlaceholderSize: true,
- start: function(e, ui) { $(ui.helper).addClass("slick-header-column-active"); },
- beforeStop: function(e, ui) { $(ui.helper).removeClass("slick-header-column-active"); },
- stop: function(e) {
- if (!getEditorLock().commitCurrentEdit()) {
- $(this).sortable("cancel");
- return;
+ }
+ if (shrinkLeewayOnRight === null) {
+ shrinkLeewayOnRight = 100000;
+ }
+ if (shrinkLeewayOnLeft === null) {
+ shrinkLeewayOnLeft = 100000;
+ }
+ if (stretchLeewayOnRight === null) {
+ stretchLeewayOnRight = 100000;
+ }
+ if (stretchLeewayOnLeft === null) {
+ stretchLeewayOnLeft = 100000;
+ }
+ maxPageX = pageX + Math.min(shrinkLeewayOnRight, stretchLeewayOnLeft);
+ minPageX = pageX - Math.min(shrinkLeewayOnLeft, stretchLeewayOnRight);
+ originalCanvasWidth = $canvas.width();
+ })
+ .bind("drag", function (e, dd) {
+ var actualMinWidth, d = Math.min(maxPageX, Math.max(minPageX, e.pageX)) - pageX, x;
+ if (d < 0) { // shrink column
+ x = d;
+ for (j = i; j >= 0; j--) {
+ c = columns[j];
+ if (c.resizable) {
+ actualMinWidth = Math.max(c.minWidth || 0, absoluteColumnMinWidth);
+ if (x && c.previousWidth + x < actualMinWidth) {
+ x += c.previousWidth - actualMinWidth;
+ c.width = actualMinWidth;
+ } else {
+ c.width = c.previousWidth + x;
+ x = 0;
}
+ }
+ }
- var reorderedIds = $headers.sortable("toArray");
- var reorderedColumns = [];
- for (var i=0; i<reorderedIds.length; i++) {
- reorderedColumns.push(columns[getColumnIndex(reorderedIds[i].replace(uid,""))]);
+ if (options.forceFitColumns) {
+ x = -d;
+ for (j = i + 1; j < columnElements.length; j++) {
+ c = columns[j];
+ if (c.resizable) {
+ if (x && c.maxWidth && (c.maxWidth - c.previousWidth < x)) {
+ x -= c.maxWidth - c.previousWidth;
+ c.width = c.maxWidth;
+ } else {
+ c.width = c.previousWidth + x;
+ x = 0;
+ }
}
- setColumns(reorderedColumns);
-
- trigger(self.onColumnsReordered, {});
- e.stopPropagation();
- setupColumnResize();
+ }
+ } else if (options.syncColumnCellResize) {
+ setCanvasWidth(originalCanvasWidth + d);
}
- });
- }
-
- function setupColumnResize() {
- var $col, j, c, pageX, columnElements, minPageX, maxPageX, firstResizable, lastResizable, originalCanvasWidth;
- columnElements = $headers.children();
- columnElements.find(".slick-resizable-handle").remove();
- columnElements.each(function(i,e) {
- if (columns[i].resizable) {
- if (firstResizable === undefined) { firstResizable = i; }
- lastResizable = i;
+ } else { // stretch column
+ x = d;
+ for (j = i; j >= 0; j--) {
+ c = columns[j];
+ if (c.resizable) {
+ if (x && c.maxWidth && (c.maxWidth - c.previousWidth < x)) {
+ x -= c.maxWidth - c.previousWidth;
+ c.width = c.maxWidth;
+ } else {
+ c.width = c.previousWidth + x;
+ x = 0;
+ }
+ }
}
- });
- if (firstResizable === undefined) {
- return;
- }
- columnElements.each(function(i,e) {
- if (i < firstResizable || (options.forceFitColumns && i >= lastResizable)) { return; }
- $col = $(e);
- $("<div class='slick-resizable-handle' />")
- .appendTo(e)
- .bind("dragstart", function(e,dd) {
- if (!getEditorLock().commitCurrentEdit()) { return false; }
- pageX = e.pageX;
- $(this).parent().addClass("slick-header-column-active");
- var shrinkLeewayOnRight = null, stretchLeewayOnRight = null;
- // lock each column's width option to current width
- columnElements.each(function(i,e) { columns[i].previousWidth = $(e).outerWidth(); });
- if (options.forceFitColumns) {
- shrinkLeewayOnRight = 0;
- stretchLeewayOnRight = 0;
- // colums on right affect maxPageX/minPageX
- for (j = i + 1; j < columnElements.length; j++) {
- c = columns[j];
- if (c.resizable) {
- if (stretchLeewayOnRight !== null) {
- if (c.maxWidth) {
- stretchLeewayOnRight += c.maxWidth - c.previousWidth;
- }
- else {
- stretchLeewayOnRight = null;
- }
- }
- shrinkLeewayOnRight += c.previousWidth - Math.max(c.minWidth || 0, absoluteColumnMinWidth);
- }
- }
- }
- var shrinkLeewayOnLeft = 0, stretchLeewayOnLeft = 0;
- for (j = 0; j <= i; j++) {
- // columns on left only affect minPageX
- c = columns[j];
- if (c.resizable) {
- if (stretchLeewayOnLeft !== null) {
- if (c.maxWidth) {
- stretchLeewayOnLeft += c.maxWidth - c.previousWidth;
- }
- else {
- stretchLeewayOnLeft = null;
- }
- }
- shrinkLeewayOnLeft += c.previousWidth - Math.max(c.minWidth || 0, absoluteColumnMinWidth);
- }
- }
- if (shrinkLeewayOnRight === null) { shrinkLeewayOnRight = 100000; }
- if (shrinkLeewayOnLeft === null) { shrinkLeewayOnLeft = 100000; }
- if (stretchLeewayOnRight === null) { stretchLeewayOnRight = 100000; }
- if (stretchLeewayOnLeft === null) { stretchLeewayOnLeft = 100000; }
- maxPageX = pageX + Math.min(shrinkLeewayOnRight, stretchLeewayOnLeft);
- minPageX = pageX - Math.min(shrinkLeewayOnLeft, stretchLeewayOnRight);
- originalCanvasWidth = $canvas.width();
- })
- .bind("drag", function(e,dd) {
- var actualMinWidth, d = Math.min(maxPageX, Math.max(minPageX, e.pageX)) - pageX, x, ci;
- if (d < 0) { // shrink column
- x = d;
- for (j = i; j >= 0; j--) {
- c = columns[j];
- if (c.resizable) {
- actualMinWidth = Math.max(c.minWidth || 0, absoluteColumnMinWidth);
- if (x && c.previousWidth + x < actualMinWidth) {
- x += c.previousWidth - actualMinWidth;
- c.width = actualMinWidth;
- } else {
- c.width = c.previousWidth + x;
- x = 0;
- }
- }
- }
-
- if (options.forceFitColumns) {
- x = -d;
- for (j = i + 1; j < columnElements.length; j++) {
- c = columns[j];
- if (c.resizable) {
- if (x && c.maxWidth && (c.maxWidth - c.previousWidth < x)) {
- x -= c.maxWidth - c.previousWidth;
- c.width = c.maxWidth;
- } else {
- c.width = c.previousWidth + x;
- x = 0;
- }
- }
- }
- } else if (options.syncColumnCellResize) {
- setCanvasWidth(originalCanvasWidth + d);
- }
- } else { // stretch column
- x = d;
- for (j = i; j >= 0; j--) {
- c = columns[j];
- if (c.resizable) {
- if (x && c.maxWidth && (c.maxWidth - c.previousWidth < x)) {
- x -= c.maxWidth - c.previousWidth;
- c.width = c.maxWidth;
- } else {
- c.width = c.previousWidth + x;
- x = 0;
- }
- }
- }
-
- if (options.forceFitColumns) {
- x = -d;
- for (j = i + 1; j < columnElements.length; j++) {
- c = columns[j];
- if (c.resizable) {
- actualMinWidth = Math.max(c.minWidth || 0, absoluteColumnMinWidth);
- if (x && c.previousWidth + x < actualMinWidth) {
- x += c.previousWidth - actualMinWidth;
- c.width = actualMinWidth;
- } else {
- c.width = c.previousWidth + x;
- x = 0;
- }
- }
- }
- } else if (options.syncColumnCellResize) {
- setCanvasWidth(originalCanvasWidth + d);
- }
- }
- applyColumnHeaderWidths();
- if (options.syncColumnCellResize) {
- applyColumnWidths();
- }
- })
- .bind("dragend", function(e,dd) {
- var newWidth;
- $(this).parent().removeClass("slick-header-column-active");
- for (j = 0; j < columnElements.length; j++) {
- c = columns[j];
- newWidth = $(columnElements[j]).outerWidth();
-
- if (c.previousWidth !== newWidth && c.rerenderOnResize) {
- invalidateAllRows();
- }
- }
- applyColumnWidths();
- resizeCanvas();
- trigger(self.onColumnsResized, {});
- });
- });
- }
-
- function getVBoxDelta($el) {
- var p = ["borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom"];
- var delta = 0;
- $.each(p, function(n,val) { delta += parseFloat($el.css(val)) || 0; });
- return delta;
- }
-
- function measureCellPaddingAndBorder() {
- var el;
- var h = ["borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight"];
- var v = ["borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom"];
-
- el = $("<div class='ui-state-default slick-header-column' style='visibility:hidden'>-</div>").appendTo($headers);
- headerColumnWidthDiff = headerColumnHeightDiff = 0;
- $.each(h, function(n,val) { headerColumnWidthDiff += parseFloat(el.css(val)) || 0; });
- $.each(v, function(n,val) { headerColumnHeightDiff += parseFloat(el.css(val)) || 0; });
- el.remove();
-
- var r = $("<div class='slick-row' />").appendTo($canvas);
- el = $("<div class='slick-cell' id='' style='visibility:hidden'>-</div>").appendTo(r);
- cellWidthDiff = cellHeightDiff = 0;
- $.each(h, function(n,val) { cellWidthDiff += parseFloat(el.css(val)) || 0; });
- $.each(v, function(n,val) { cellHeightDiff += parseFloat(el.css(val)) || 0; });
- r.remove();
-
- absoluteColumnMinWidth = Math.max(headerColumnWidthDiff,cellWidthDiff);
- }
-
- function createCssRules() {
- $style = $("<style type='text/css' rel='stylesheet' />").appendTo($("head"));
- var rowHeight = (options.rowHeight - cellHeightDiff);
-
- var rules = [
- "." + uid + " .slick-header-column { left: 1000px; }",
- "." + uid + " .slick-top-panel { height:" + options.topPanelHeight + "px; }",
- "." + uid + " .slick-headerrow-columns { height:" + options.headerRowHeight + "px; }",
- "." + uid + " .slick-cell { height:" + rowHeight + "px; }",
- "." + uid + " .slick-row { width:" + getRowWidth() + "px; height:" + options.rowHeight + "px; }"
- ];
-
- var rowWidth = getRowWidth();
- var x = 0, w;
- for (var i=0; i<columns.length; i++) {
- w = columns[i].width;
- rules.push("." + uid + " .l" + i + " { left: " + x + "px; }");
- rules.push("." + uid + " .r" + i + " { right: " + (rowWidth - x - w) + "px; }");
- x += columns[i].width;
- }
- if ($style[0].styleSheet) { // IE
- $style[0].styleSheet.cssText = rules.join(" ");
- }
- else {
- $style[0].appendChild(document.createTextNode(rules.join(" ")));
- }
-
- var sheets = document.styleSheets;
- for (var i=0; i<sheets.length; i++) {
- if ((sheets[i].ownerNode || sheets[i].owningElement) == $style[0]) {
- stylesheet = sheets[i];
- break;
+ if (options.forceFitColumns) {
+ x = -d;
+ for (j = i + 1; j < columnElements.length; j++) {
+ c = columns[j];
+ if (c.resizable) {
+ actualMinWidth = Math.max(c.minWidth || 0, absoluteColumnMinWidth);
+ if (x && c.previousWidth + x < actualMinWidth) {
+ x += c.previousWidth - actualMinWidth;
+ c.width = actualMinWidth;
+ } else {
+ c.width = c.previousWidth + x;
+ x = 0;
+ }
+ }
+ }
+ } else if (options.syncColumnCellResize) {
+ setCanvasWidth(originalCanvasWidth + d);
}
- }
- }
-
- function findCssRule(selector) {
- var rules = (stylesheet.cssRules || stylesheet.rules);
-
- for (var i=0; i<rules.length; i++) {
- if (rules[i].selectorText == selector)
- return rules[i];
- }
-
- return null;
- }
-
- function removeCssRules() {
- $style.remove();
- }
-
- function destroy() {
- getEditorLock().cancelCurrentEdit();
-
- trigger(self.onBeforeDestroy, {});
+ }
+ applyColumnHeaderWidths();
+ if (options.syncColumnCellResize) {
+ applyColumnWidths();
+ }
+ })
+ .bind("dragend", function (e, dd) {
+ var newWidth;
+ $(this).parent().removeClass("slick-header-column-active");
+ for (j = 0; j < columnElements.length; j++) {
+ c = columns[j];
+ newWidth = $(columnElements[j]).outerWidth();
+
+ if (c.previousWidth !== newWidth && c.rerenderOnResize) {
+ invalidateAllRows();
+ }
+ }
+ applyColumnWidths();
+ resizeCanvas();
+ trigger(self.onColumnsResized, {});
+ });
+ });
+ }
- for (var i = 0; i < plugins.length; i++) {
- unregisterPlugin(plugins[i]);
- }
+ function getVBoxDelta($el) {
+ var p = ["borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom"];
+ var delta = 0;
+ $.each(p, function (n, val) {
+ delta += parseFloat($el.css(val)) || 0;
+ });
+ return delta;
+ }
- if (options.enableColumnReorder && $headers.sortable)
- $headers.sortable("destroy");
+ function measureCellPaddingAndBorder() {
+ var el;
+ var h = ["borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight"];
+ var v = ["borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom"];
+
+ el = $("<div class='ui-state-default slick-header-column' style='visibility:hidden'>-</div>").appendTo($headers);
+ headerColumnWidthDiff = headerColumnHeightDiff = 0;
+ $.each(h, function (n, val) {
+ headerColumnWidthDiff += parseFloat(el.css(val)) || 0;
+ });
+ $.each(v, function (n, val) {
+ headerColumnHeightDiff += parseFloat(el.css(val)) || 0;
+ });
+ el.remove();
+
+ var r = $("<div class='slick-row' />").appendTo($canvas);
+ el = $("<div class='slick-cell' id='' style='visibility:hidden'>-</div>").appendTo(r);
+ cellWidthDiff = cellHeightDiff = 0;
+ $.each(h, function (n, val) {
+ cellWidthDiff += parseFloat(el.css(val)) || 0;
+ });
+ $.each(v, function (n, val) {
+ cellHeightDiff += parseFloat(el.css(val)) || 0;
+ });
+ r.remove();
+
+ absoluteColumnMinWidth = Math.max(headerColumnWidthDiff, cellWidthDiff);
+ }
- unbindAncestorScrollEvents();
- $container.unbind(".slickgrid");
- removeCssRules();
+ function createCssRules() {
+ $style = $("<style type='text/css' rel='stylesheet' />").appendTo($("head"));
+ var rowHeight = (options.rowHeight - cellHeightDiff);
+ var rowWidth = getRowWidth();
+ var rules = [
+ "." + uid + " .slick-header-column { left: 1000px; }",
+ "." + uid + " .slick-top-panel { height:" + options.topPanelHeight + "px; }",
+ "." + uid + " .slick-headerrow-columns { height:" + options.headerRowHeight + "px; }",
+ "." + uid + " .slick-cell { height:" + rowHeight + "px; }",
+ "." + uid + " .slick-row { width:" + getRowWidth() + "px; height:" + options.rowHeight + "px; }"
+ ];
+
+ var x = 0, w;
+ for (var i = 0; i < columns.length; i++) {
+ w = columns[i].width;
+ rules.push("." + uid + " .l" + i + " { left: " + x + "px; }");
+ rules.push("." + uid + " .r" + i + " { right: " + (rowWidth - x - w) + "px; }");
+ x += columns[i].width;
+ }
+
+ if ($style[0].styleSheet) { // IE
+ $style[0].styleSheet.cssText = rules.join(" ");
+ }
+ else {
+ $style[0].appendChild(document.createTextNode(rules.join(" ")));
+ }
+
+ var sheets = document.styleSheets;
+ for (var i = 0; i < sheets.length; i++) {
+ if ((sheets[i].ownerNode || sheets[i].owningElement) == $style[0]) {
+ stylesheet = sheets[i];
+ break;
+ }
+ }
+ }
- $canvas.unbind("draginit dragstart dragend drag");
- $container.empty().removeClass(uid);
+ function findCssRule(selector) {
+ var rules = (stylesheet.cssRules || stylesheet.rules);
+ for (var i = 0; i < rules.length; i++) {
+ if (rules[i].selectorText == selector) {
+ return rules[i];
}
+ }
+ return null;
+ }
+ function removeCssRules() {
+ $style.remove();
+ }
- //////////////////////////////////////////////////////////////////////////////////////////////
- // General
+ function destroy() {
+ getEditorLock().cancelCurrentEdit();
- function trigger(evt, args, e) {
- e = e || new Slick.EventData();
- args = args || {};
- args.grid = self;
- return evt.notify(args, e, self);
- }
+ trigger(self.onBeforeDestroy, {});
- function getEditorLock() {
- return options.editorLock;
- }
+ for (var i = 0; i < plugins.length; i++) {
+ unregisterPlugin(plugins[i]);
+ }
- function getEditController() {
- return editController;
- }
+ if (options.enableColumnReorder && $headers.sortable) {
+ $headers.sortable("destroy");
+ }
- function getColumnIndex(id) {
- return columnsById[id];
- }
+ unbindAncestorScrollEvents();
+ $container.unbind(".slickgrid");
+ removeCssRules();
- function autosizeColumns() {
- var i, c,
- widths = [],
- shrinkLeeway = 0,
- availWidth = (options.autoHeight ? viewportW : viewportW - scrollbarDimensions.width), // with AutoHeight, we do not need to accomodate the vertical scroll bar
- total = 0,
- existingTotal = 0;
+ $canvas.unbind("draginit dragstart dragend drag");
+ $container.empty().removeClass(uid);
+ }
- for (i = 0; i < columns.length; i++) {
- c = columns[i];
- widths.push(c.width);
- existingTotal += c.width;
- shrinkLeeway += c.width - Math.max(c.minWidth || 0, absoluteColumnMinWidth);
- }
- total = existingTotal;
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ // General
- invalidateAllRows();
+ function trigger(evt, args, e) {
+ e = e || new Slick.EventData();
+ args = args || {};
+ args.grid = self;
+ return evt.notify(args, e, self);
+ }
- // shrink
- while (total > availWidth) {
- if (!shrinkLeeway) { return; }
- var shrinkProportion = (total - availWidth) / shrinkLeeway;
- for (i = 0; i < columns.length && total > availWidth; i++) {
- c = columns[i];
- if (!c.resizable || c.minWidth === c.width || c.width === absoluteColumnMinWidth) { continue; }
- var shrinkSize = Math.floor(shrinkProportion * (c.width - Math.max(c.minWidth || 0, absoluteColumnMinWidth))) || 1;
- total -= shrinkSize;
- widths[i] -= shrinkSize;
- }
- }
+ function getEditorLock() {
+ return options.editorLock;
+ }
- // grow
- var previousTotal = total;
- while (total < availWidth) {
- var growProportion = availWidth / total;
- for (i = 0; i < columns.length && total < availWidth; i++) {
- c = columns[i];
- if (!c.resizable || c.maxWidth <= c.width) { continue; }
- var growSize = Math.min(Math.floor(growProportion * c.width) - c.width, (c.maxWidth - c.width) || 1000000) || 1;
- total += growSize;
- widths[i] += growSize;
- }
- if (previousTotal == total) break; // if total is not changing, will result in infinite loop
- previousTotal = total;
- }
+ function getEditController() {
+ return editController;
+ }
- for (i=0; i<columns.length; i++) {
- columns[i].width = widths[i];
- }
+ function getColumnIndex(id) {
+ return columnsById[id];
+ }
- applyColumnHeaderWidths();
- applyColumnWidths();
- resizeCanvas();
- }
+ function autosizeColumns() {
+ var i, c,
+ widths = [],
+ shrinkLeeway = 0,
+ // with AutoHeight, we do not need to accommodate the vertical scroll bar
+ availWidth = (options.autoHeight ? viewportW : viewportW - scrollbarDimensions.width),
+ total = 0,
+ existingTotal = 0;
+
+ for (i = 0; i < columns.length; i++) {
+ c = columns[i];
+ widths.push(c.width);
+ existingTotal += c.width;
+ shrinkLeeway += c.width - Math.max(c.minWidth || 0, absoluteColumnMinWidth);
+ }
+
+ total = existingTotal;
+
+ invalidateAllRows();
+
+ // shrink
+ while (total > availWidth) {
+ if (!shrinkLeeway) {
+ return;
+ }
+ var shrinkProportion = (total - availWidth) / shrinkLeeway;
+ for (i = 0; i < columns.length && total > availWidth; i++) {
+ c = columns[i];
+ if (!c.resizable || c.minWidth === c.width || c.width === absoluteColumnMinWidth) {
+ continue;
+ }
+ var shrinkSize = Math.floor(shrinkProportion * (c.width - Math.max(c.minWidth || 0, absoluteColumnMinWidth))) || 1;
+ total -= shrinkSize;
+ widths[i] -= shrinkSize;
+ }
+ }
+
+ // grow
+ var previousTotal = total;
+ while (total < availWidth) {
+ var growProportion = availWidth / total;
+ for (i = 0; i < columns.length && total < availWidth; i++) {
+ c = columns[i];
+ if (!c.resizable || c.maxWidth <= c.width) {
+ continue;
+ }
+ var growSize = Math.min(Math.floor(growProportion * c.width) - c.width, (c.maxWidth - c.width) || 1000000) || 1;
+ total += growSize;
+ widths[i] += growSize;
+ }
+ if (previousTotal == total) {
+ break;
+ } // if total is not changing, will result in infinite loop
+ previousTotal = total;
+ }
+
+ for (i = 0; i < columns.length; i++) {
+ columns[i].width = widths[i];
+ }
+
+ applyColumnHeaderWidths();
+ applyColumnWidths();
+ resizeCanvas();
+ }
- function applyColumnHeaderWidths() {
- var h;
- for (var i = 0, headers = $headers.children(), ii = headers.length; i < ii; i++) {
- h = $(headers[i]);
- if (h.width() !== columns[i].width - headerColumnWidthDiff) {
- h.width(columns[i].width - headerColumnWidthDiff);
- }
- }
+ function applyColumnHeaderWidths() {
+ var h;
+ for (var i = 0, headers = $headers.children(), ii = headers.length; i < ii; i++) {
+ h = $(headers[i]);
+ if (h.width() !== columns[i].width - headerColumnWidthDiff) {
+ h.width(columns[i].width - headerColumnWidthDiff);
}
+ }
+ }
- function applyColumnWidths() {
- var rowWidth = getRowWidth();
- var x = 0, w, rule;
- for (var i = 0; i < columns.length; i++) {
- w = columns[i].width;
+ function applyColumnWidths() {
+ var rowWidth = getRowWidth();
+ var x = 0, w, rule;
+ for (var i = 0; i < columns.length; i++) {
+ w = columns[i].width;
- rule = findCssRule("." + uid + " .l" + i);
- rule.style.left = x + "px";
+ rule = findCssRule("." + uid + " .l" + i);
+ rule.style.left = x + "px";
- rule = findCssRule("." + uid + " .r" + i);
- rule.style.right = (rowWidth - x - w) + "px";
+ rule = findCssRule("." + uid + " .r" + i);
+ rule.style.right = (rowWidth - x - w) + "px";
- x += columns[i].width;
- }
+ x += columns[i].width;
+ }
- rule = findCssRule("." + uid + " .slick-row");
- rule.style.width = rowWidth + "px";
- }
+ rule = findCssRule("." + uid + " .slick-row");
+ rule.style.width = rowWidth + "px";
+ }
- function setSortColumn(columnId, ascending) {
- sortColumnId = columnId;
- sortAsc = ascending;
- var columnIndex = getColumnIndex(sortColumnId);
+ function setSortColumn(columnId, ascending) {
+ sortColumnId = columnId;
+ sortAsc = ascending;
+ var columnIndex = getColumnIndex(sortColumnId);
- $headers.children().removeClass("slick-header-column-sorted");
- $headers.find(".slick-sort-indicator").removeClass("slick-sort-indicator-asc slick-sort-indicator-desc");
+ $headers.children().removeClass("slick-header-column-sorted");
+ $headers.find(".slick-sort-indicator").removeClass("slick-sort-indicator-asc slick-sort-indicator-desc");
- if (columnIndex != null) {
- $headers.children().eq(columnIndex)
- .addClass("slick-header-column-sorted")
- .find(".slick-sort-indicator")
- .addClass(sortAsc ? "slick-sort-indicator-asc" : "slick-sort-indicator-desc");
- }
- }
+ if (columnIndex != null) {
+ $headers.children().eq(columnIndex)
+ .addClass("slick-header-column-sorted")
+ .find(".slick-sort-indicator")
+ .addClass(sortAsc ? "slick-sort-indicator-asc" : "slick-sort-indicator-desc");
+ }
+ }
- function handleSelectedRangesChanged(e, ranges) {
- selectedRows = [];
- var hash = {};
- for (var i = 0; i < ranges.length; i++) {
- for (var j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
- if (!hash[j]) { // prevent duplicates
- selectedRows.push(j);
- }
- hash[j] = {};
- for (var k = ranges[i].fromCell; k <= ranges[i].toCell; k++) {
- if (canCellBeSelected(j, k)) {
- hash[j][columns[k].id] = options.selectedCellCssClass;
- }
- }
- }
+ function handleSelectedRangesChanged(e, ranges) {
+ selectedRows = [];
+ var hash = {};
+ for (var i = 0; i < ranges.length; i++) {
+ for (var j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
+ if (!hash[j]) { // prevent duplicates
+ selectedRows.push(j);
+ }
+ hash[j] = {};
+ for (var k = ranges[i].fromCell; k <= ranges[i].toCell; k++) {
+ if (canCellBeSelected(j, k)) {
+ hash[j][columns[k].id] = options.selectedCellCssClass;
}
-
- setCellCssStyles(options.selectedCellCssClass, hash);
-
- trigger(self.onSelectedRowsChanged, {rows:getSelectedRows()}, e);
- }
-
- function getColumns() {
- return columns;
- }
-
- function setColumns(columnDefinitions) {
- columns = columnDefinitions;
- invalidateAllRows();
- createColumnHeaders();
- removeCssRules();
- createCssRules();
- resizeAndRender();
- handleScroll();
+ }
}
+ }
- function getOptions() {
- return options;
- }
+ setCellCssStyles(options.selectedCellCssClass, hash);
- function setOptions(args) {
- if (!getEditorLock().commitCurrentEdit()) {
- return;
- }
+ trigger(self.onSelectedRowsChanged, {rows:getSelectedRows()}, e);
+ }
- makeActiveCellNormal();
+ function getColumns() {
+ return columns;
+ }
- if (options.enableAddRow !== args.enableAddRow) {
- invalidateRow(getDataLength());
- }
+ function setColumns(columnDefinitions) {
+ columns = columnDefinitions;
+ invalidateAllRows();
+ createColumnHeaders();
+ removeCssRules();
+ createCssRules();
+ resizeAndRender();
+ handleScroll();
+ }
- options = $.extend(options,args);
+ function getOptions() {
+ return options;
+ }
- render();
- }
+ function setOptions(args) {
+ if (!getEditorLock().commitCurrentEdit()) {
+ return;
+ }
- function setData(newData,scrollToTop) {
- invalidateAllRows();
- data = newData;
- if (scrollToTop)
- scrollTo(0);
- }
+ makeActiveCellNormal();
- function getData() {
- return data;
- }
+ if (options.enableAddRow !== args.enableAddRow) {
+ invalidateRow(getDataLength());
+ }
- function getDataLength() {
- if (data.getLength) {
- return data.getLength();
- }
- else {
- return data.length;
- }
- }
+ options = $.extend(options, args);
- function getDataItem(i) {
- if (data.getItem) {
- return data.getItem(i);
- }
- else {
- return data[i];
- }
- }
-
- function getTopPanel() {
- return $topPanel[0];
- }
-
- function showTopPanel() {
- options.showTopPanel = true;
- $topPanelScroller.slideDown("fast", resizeCanvas);
- }
+ render();
+ }
- function hideTopPanel() {
- options.showTopPanel = false;
- $topPanelScroller.slideUp("fast", resizeCanvas);
- }
+ function setData(newData, scrollToTop) {
+ invalidateAllRows();
+ data = newData;
+ if (scrollToTop) {
+ scrollTo(0);
+ }
+ }
- function showHeaderRowColumns() {
- options.showHeaderRow = true;
- $headerRowScroller.slideDown("fast", resizeCanvas);
- }
+ function getData() {
+ return data;
+ }
- function hideHeaderRowColumns() {
- options.showHeaderRow = false;
- $headerRowScroller.slideUp("fast", resizeCanvas);
- }
+ function getDataLength() {
+ if (data.getLength) {
+ return data.getLength();
+ } else {
+ return data.length;
+ }
+ }
- //////////////////////////////////////////////////////////////////////////////////////////////
- // Rendering / Scrolling
+ function getDataItem(i) {
+ if (data.getItem) {
+ return data.getItem(i);
+ } else {
+ return data[i];
+ }
+ }
- function scrollTo(y) {
- var oldOffset = offset;
+ function getTopPanel() {
+ return $topPanel[0];
+ }
- page = Math.min(n-1, Math.floor(y / ph));
- offset = Math.round(page * cj);
- var newScrollTop = y - offset;
+ function showTopPanel() {
+ options.showTopPanel = true;
+ $topPanelScroller.slideDown("fast", resizeCanvas);
+ }
- if (offset != oldOffset) {
- var range = getVisibleRange(newScrollTop);
- cleanupRows(range.top,range.bottom);
- updateRowPositions();
- }
+ function hideTopPanel() {
+ options.showTopPanel = false;
+ $topPanelScroller.slideUp("fast", resizeCanvas);
+ }
- if (prevScrollTop != newScrollTop) {
- scrollDir = (prevScrollTop + oldOffset < newScrollTop + offset) ? 1 : -1;
- $viewport[0].scrollTop = (lastRenderedScrollTop = scrollTop = prevScrollTop = newScrollTop);
+ function showHeaderRowColumns() {
+ options.showHeaderRow = true;
+ $headerRowScroller.slideDown("fast", resizeCanvas);
+ }
- trigger(self.onViewportChanged, {});
- }
- }
+ function hideHeaderRowColumns() {
+ options.showHeaderRow = false;
+ $headerRowScroller.slideUp("fast", resizeCanvas);
+ }
- function defaultFormatter(row, cell, value, columnDef, dataContext) {
- return (value === null || value === undefined) ? "" : value;
- }
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ // Rendering / Scrolling
- function getFormatter(row, column) {
- var rowMetadata = data.getItemMetadata && data.getItemMetadata(row);
+ function scrollTo(y) {
+ var oldOffset = offset;
- // look up by id, then index
- var columnOverrides = rowMetadata &&
- rowMetadata.columns &&
- (rowMetadata.columns[column.id] || rowMetadata.columns[getColumnIndex(column.id)]);
+ page = Math.min(n - 1, Math.floor(y / ph));
+ offset = Math.round(page * cj);
+ var newScrollTop = y - offset;
- return (columnOverrides && columnOverrides.formatter) ||
- (rowMetadata && rowMetadata.formatter) ||
- column.formatter ||
- (options.formatterFactory && options.formatterFactory.getFormatter(column)) ||
- defaultFormatter;
- }
+ if (offset != oldOffset) {
+ var range = getVisibleRange(newScrollTop);
+ cleanupRows(range.top, range.bottom);
+ updateRowPositions();
+ }
- function getEditor(row, cell) {
- var column = columns[cell];
- var rowMetadata = data.getItemMetadata && data.getItemMetadata(row);
- var columnMetadata = rowMetadata && rowMetadata.columns;
+ if (prevScrollTop != newScrollTop) {
+ scrollDir = (prevScrollTop + oldOffset < newScrollTop + offset) ? 1 : -1;
+ $viewport[0].scrollTop = (lastRenderedScrollTop = scrollTop = prevScrollTop = newScrollTop);
- if (columnMetadata && columnMetadata[column.id] && columnMetadata[column.id].editor !== undefined) {
- return columnMetadata[column.id].editor;
- }
- if (columnMetadata && columnMetadata[cell] && columnMetadata[cell].editor !== undefined) {
- return columnMetadata[cell].editor;
- }
+ trigger(self.onViewportChanged, {});
+ }
+ }
- return column.editor || (options.editorFactory && options.editorFactory.getEditor(column));
- }
+ function defaultFormatter(row, cell, value, columnDef, dataContext) {
+ return (value === null || value === undefined) ? "" : value;
+ }
- function getDataItemValueForColumn(item, columnDef) {
- if (options.dataItemColumnValueExtractor) {
- return options.dataItemColumnValueExtractor(item, columnDef);
- }
- return item[columnDef.field];
- }
+ function getFormatter(row, column) {
+ var rowMetadata = data.getItemMetadata && data.getItemMetadata(row);
- function appendRowHtml(stringArray, row) {
- var d = getDataItem(row);
- var dataLoading = row < getDataLength() && !d;
- var cellCss;
- var rowCss = "slick-row " +
- (dataLoading ? " loading" : "") +
- (row % 2 == 1 ? ' odd' : ' even');
+ // look up by id, then index
+ var columnOverrides = rowMetadata &&
+ rowMetadata.columns &&
+ (rowMetadata.columns[column.id] || rowMetadata.columns[getColumnIndex(column.id)]);
- var metadata = data.getItemMetadata && data.getItemMetadata(row);
+ return (columnOverrides && columnOverrides.formatter) ||
+ (rowMetadata && rowMetadata.formatter) ||
+ column.formatter ||
+ (options.formatterFactory && options.formatterFactory.getFormatter(column)) ||
+ defaultFormatter;
+ }
- if (metadata && metadata.cssClasses) {
- rowCss += " " + metadata.cssClasses;
- }
+ function getEditor(row, cell) {
+ var column = columns[cell];
+ var rowMetadata = data.getItemMetadata && data.getItemMetadata(row);
+ var columnMetadata = rowMetadata && rowMetadata.columns;
- stringArray.push("<div class='ui-widget-content " + rowCss + "' row='" + row + "' style='top:" + (options.rowHeight*row-offset) + "px'>");
+ if (columnMetadata && columnMetadata[column.id] && columnMetadata[column.id].editor !== undefined) {
+ return columnMetadata[column.id].editor;
+ }
+ if (columnMetadata && columnMetadata[cell] && columnMetadata[cell].editor !== undefined) {
+ return columnMetadata[cell].editor;
+ }
- var colspan, m;
- for (var i=0, cols=columns.length; i<cols; i++) {
- m = columns[i];
- colspan = getColspan(row, i); // TODO: don't calc unless we have to
- cellCss = "slick-cell l" + i + " r" + Math.min(columns.length -1, i + colspan - 1) + (m.cssClass ? " " + m.cssClass : "");
- if (row === activeRow && i === activeCell) {
- cellCss += (" active");
- }
+ return column.editor || (options.editorFactory && options.editorFactory.getEditor(column));
+ }
- // TODO: merge them together in the setter
- for (var key in cellCssClasses) {
- if (cellCssClasses[key][row] && cellCssClasses[key][row][m.id]) {
- cellCss += (" " + cellCssClasses[key][row][m.id]);
- }
- }
+ function getDataItemValueForColumn(item, columnDef) {
+ if (options.dataItemColumnValueExtractor) {
+ return options.dataItemColumnValueExtractor(item, columnDef);
+ }
+ return item[columnDef.field];
+ }
- stringArray.push("<div class='" + cellCss + "'>");
+ function appendRowHtml(stringArray, row) {
+ var d = getDataItem(row);
+ var dataLoading = row < getDataLength() && !d;
+ var cellCss;
+ var rowCss = "slick-row " +
+ (dataLoading ? " loading" : "") +
+ (row % 2 == 1 ? " odd" : " even");
- // if there is a corresponding row (if not, this is the Add New row or this data hasn't been loaded yet)
- if (d) {
- stringArray.push(getFormatter(row, m)(row, i, getDataItemValueForColumn(d, m), m, d));
- }
+ var metadata = data.getItemMetadata && data.getItemMetadata(row);
- stringArray.push("</div>");
+ if (metadata && metadata.cssClasses) {
+ rowCss += " " + metadata.cssClasses;
+ }
- if (colspan) {
- i += (colspan - 1);
- }
- }
+ stringArray.push("<div class='ui-widget-content " + rowCss + "' row='" + row + "' style='top:" + (options.rowHeight * row - offset) + "px'>");
- stringArray.push("</div>");
+ var colspan, m;
+ for (var i = 0, cols = columns.length; i < cols; i++) {
+ m = columns[i];
+ colspan = getColspan(row, i); // TODO: don't calc unless we have to
+ cellCss = "slick-cell l" + i + " r" + Math.min(columns.length - 1, i + colspan - 1) + (m.cssClass ? " " + m.cssClass : "");
+ if (row === activeRow && i === activeCell) {
+ cellCss += (" active");
}
- function cleanupRows(rangeToKeep) {
- for (var i in rowsCache) {
- if (((i = parseInt(i, 10)) !== activeRow) && (i < rangeToKeep.top || i > rangeToKeep.bottom)) {
- removeRowFromCache(i);
- }
- }
+ // TODO: merge them together in the setter
+ for (var key in cellCssClasses) {
+ if (cellCssClasses[key][row] && cellCssClasses[key][row][m.id]) {
+ cellCss += (" " + cellCssClasses[key][row][m.id]);
+ }
}
- function invalidate() {
- updateRowCount();
- invalidateAllRows();
- render();
- }
+ stringArray.push("<div class='" + cellCss + "'>");
- function invalidateAllRows() {
- if (currentEditor) {
- makeActiveCellNormal();
- }
- for (var row in rowsCache) {
- removeRowFromCache(row);
- }
+ // if there is a corresponding row (if not, this is the Add New row or this data hasn't been loaded yet)
+ if (d) {
+ stringArray.push(getFormatter(row, m)(row, i, getDataItemValueForColumn(d, m), m, d));
}
- function removeRowFromCache(row) {
- var node = rowsCache[row];
- if (!node) { return; }
- $canvas[0].removeChild(node);
+ stringArray.push("</div>");
- delete rowsCache[row];
- delete postProcessedRows[row];
- renderedRows--;
- counter_rows_removed++;
+ if (colspan) {
+ i += (colspan - 1);
}
+ }
- function invalidateRows(rows) {
- var i, rl;
- if (!rows || !rows.length) { return; }
- scrollDir = 0;
- for (i=0, rl=rows.length; i<rl; i++) {
- if (currentEditor && activeRow === i) {
- makeActiveCellNormal();
- }
-
- if (rowsCache[rows[i]]) {
- removeRowFromCache(rows[i]);
- }
- }
- }
+ stringArray.push("</div>");
+ }
- function invalidateRow(row) {
- invalidateRows([row]);
+ function cleanupRows(rangeToKeep) {
+ for (var i in rowsCache) {
+ if (((i = parseInt(i, 10)) !== activeRow) && (i < rangeToKeep.top || i > rangeToKeep.bottom)) {
+ removeRowFromCache(i);
}
+ }
+ }
- function updateCell(row,cell) {
- var cellNode = getCellNode(row,cell);
- if (!cellNode) {
- return;
- }
-
- var m = columns[cell], d = getDataItem(row);
- if (currentEditor && activeRow === row && activeCell === cell) {
- currentEditor.loadValue(d);
- }
- else {
- cellNode.innerHTML = d ? getFormatter(row, m)(row, cell, getDataItemValueForColumn(d, m), m, d) : "";
- invalidatePostProcessingResults(row);
- }
- }
+ function invalidate() {
+ updateRowCount();
+ invalidateAllRows();
+ render();
+ }
- function updateRow(row) {
- if (!rowsCache[row]) { return; }
+ function invalidateAllRows() {
+ if (currentEditor) {
+ makeActiveCellNormal();
+ }
+ for (var row in rowsCache) {
+ removeRowFromCache(row);
+ }
+ }
- $(rowsCache[row]).children().each(function(i) {
- var m = columns[i], d = getDataItem(row);
- if (row === activeRow && i === activeCell && currentEditor) {
- currentEditor.loadValue(getDataItem(activeRow));
- }
- else if (d) {
- this.innerHTML = getFormatter(row, m)(row, i, getDataItemValueForColumn(d, m), m, getDataItem(row));
- }
- else {
- this.innerHTML = "";
- }
- });
+ function removeRowFromCache(row) {
+ var node = rowsCache[row];
+ if (!node) {
+ return;
+ }
+ $canvas[0].removeChild(node);
+ delete rowsCache[row];
+ delete postProcessedRows[row];
+ renderedRows--;
+ counter_rows_removed++;
+ }
- invalidatePostProcessingResults(row);
+ function invalidateRows(rows) {
+ var i, rl;
+ if (!rows || !rows.length) {
+ return;
+ }
+ scrollDir = 0;
+ for (i = 0, rl = rows.length; i < rl; i++) {
+ if (currentEditor && activeRow === i) {
+ makeActiveCellNormal();
}
-
- function getViewportHeight() {
- return parseFloat($.css($container[0], "height", true)) -
- options.headerHeight -
- getVBoxDelta($headers) -
- (options.showTopPanel ? options.topPanelHeight + getVBoxDelta($topPanelScroller) : 0) -
- (options.showHeaderRow ? options.headerRowHeight + getVBoxDelta($headerRowScroller) : 0);
+ if (rowsCache[rows[i]]) {
+ removeRowFromCache(rows[i]);
}
+ }
+ }
- function resizeCanvas() {
- if (options.autoHeight) {
- viewportH = options.rowHeight * (getDataLength() + (options.enableAddRow ? 1 : 0) + (options.leaveSpaceForNewRows? numVisibleRows - 1 : 0));
- }
- else {
- viewportH = getViewportHeight();
- }
+ function invalidateRow(row) {
+ invalidateRows([row]);
+ }
- numVisibleRows = Math.ceil(viewportH / options.rowHeight);
- viewportW = parseFloat($.css($container[0], "width", true));
- $viewport.height(viewportH);
+ function updateCell(row, cell) {
+ var cellNode = getCellNode(row, cell);
+ if (!cellNode) {
+ return;
+ }
+
+ var m = columns[cell], d = getDataItem(row);
+ if (currentEditor && activeRow === row && activeCell === cell) {
+ currentEditor.loadValue(d);
+ } else {
+ cellNode.innerHTML = d ? getFormatter(row, m)(row, cell, getDataItemValueForColumn(d, m), m, d) : "";
+ invalidatePostProcessingResults(row);
+ }
+ }
- var w = 0, i = columns.length;
- while (i--) {
- w += columns[i].width;
- }
- setCanvasWidth(w);
+ function updateRow(row) {
+ if (!rowsCache[row]) {
+ return;
+ }
- updateRowCount();
- render();
+ $(rowsCache[row]).children().each(function (i) {
+ var m = columns[i], d = getDataItem(row);
+ if (row === activeRow && i === activeCell && currentEditor) {
+ currentEditor.loadValue(getDataItem(activeRow));
+ } else if (d) {
+ this.innerHTML = getFormatter(row, m)(row, i, getDataItemValueForColumn(d, m), m, getDataItem(row));
+ } else {
+ this.innerHTML = "";
}
+ });
- function resizeAndRender() {
- if (options.forceFitColumns) {
- autosizeColumns();
- } else {
- resizeCanvas();
- }
- }
-
- function updateRowCount() {
- var newRowCount = getDataLength() + (options.enableAddRow?1:0) + (options.leaveSpaceForNewRows?numVisibleRows-1:0);
- var oldH = h;
-
- // remove the rows that are now outside of the data range
- // this helps avoid redundant calls to .removeRow() when the size of the data decreased by thousands of rows
- var l = options.enableAddRow ? getDataLength() : getDataLength() - 1;
- for (var i in rowsCache) {
- if (i >= l) {
- removeRowFromCache(i);
- }
- }
- th = Math.max(options.rowHeight * newRowCount, viewportH - scrollbarDimensions.height);
- if (th < maxSupportedCssHeight) {
- // just one page
- h = ph = th;
- n = 1;
- cj = 0;
- }
- else {
- // break into pages
- h = maxSupportedCssHeight;
- ph = h / 100;
- n = Math.floor(th / ph);
- cj = (th - h) / (n - 1);
- }
+ invalidatePostProcessingResults(row);
+ }
- if (h !== oldH) {
- $canvas.css("height",h);
- scrollTop = $viewport[0].scrollTop;
- }
+ function getViewportHeight() {
+ return parseFloat($.css($container[0], "height", true)) -
+ options.headerHeight -
+ getVBoxDelta($headers) -
+ (options.showTopPanel ? options.topPanelHeight + getVBoxDelta($topPanelScroller) : 0) -
+ (options.showHeaderRow ? options.headerRowHeight + getVBoxDelta($headerRowScroller) : 0);
+ }
- var oldScrollTopInRange = (scrollTop + offset <= th - viewportH);
+ function resizeCanvas() {
+ if (options.autoHeight) {
+ viewportH = options.rowHeight * (getDataLength() + (options.enableAddRow ? 1 : 0) + (options.leaveSpaceForNewRows ? numVisibleRows - 1 : 0));
+ } else {
+ viewportH = getViewportHeight();
+ }
+
+ numVisibleRows = Math.ceil(viewportH / options.rowHeight);
+ viewportW = parseFloat($.css($container[0], "width", true));
+ $viewport.height(viewportH);
+
+ var w = 0, i = columns.length;
+ while (i--) {
+ w += columns[i].width;
+ }
+ setCanvasWidth(w);
+ updateRowCount();
+ render();
+ }
- if (th == 0 || scrollTop == 0) {
- page = offset = 0;
- }
- else if (oldScrollTopInRange) {
- // maintain virtual position
- scrollTo(scrollTop+offset);
- }
- else {
- // scroll to bottom
- scrollTo(th-viewportH);
- }
+ function resizeAndRender() {
+ if (options.forceFitColumns) {
+ autosizeColumns();
+ } else {
+ resizeCanvas();
+ }
+ }
- if (h != oldH && options.autoHeight) {
- resizeCanvas();
- }
- }
+ function updateRowCount() {
+ var newRowCount = getDataLength() + (options.enableAddRow ? 1 : 0) +
+ (options.leaveSpaceForNewRows ? numVisibleRows - 1 : 0);
+ var oldH = h;
+
+ // remove the rows that are now outside of the data range
+ // this helps avoid redundant calls to .removeRow() when the size of the data decreased by thousands of rows
+ var l = options.enableAddRow ? getDataLength() : getDataLength() - 1;
+ for (var i in rowsCache) {
+ if (i >= l) {
+ removeRowFromCache(i);
+ }
+ }
+ th = Math.max(options.rowHeight * newRowCount, viewportH - scrollbarDimensions.height);
+ if (th < maxSupportedCssHeight) {
+ // just one page
+ h = ph = th;
+ n = 1;
+ cj = 0;
+ } else {
+ // break into pages
+ h = maxSupportedCssHeight;
+ ph = h / 100;
+ n = Math.floor(th / ph);
+ cj = (th - h) / (n - 1);
+ }
+
+ if (h !== oldH) {
+ $canvas.css("height", h);
+ scrollTop = $viewport[0].scrollTop;
+ }
+
+ var oldScrollTopInRange = (scrollTop + offset <= th - viewportH);
+
+ if (th == 0 || scrollTop == 0) {
+ page = offset = 0;
+ } else if (oldScrollTopInRange) {
+ // maintain virtual position
+ scrollTo(scrollTop + offset);
+ } else {
+ // scroll to bottom
+ scrollTo(th - viewportH);
+ }
+
+ if (h != oldH && options.autoHeight) {
+ resizeCanvas();
+ }
+ }
- function getVisibleRange(viewportTop) {
- if (viewportTop == null)
- viewportTop = scrollTop;
+ function getVisibleRange(viewportTop) {
+ if (viewportTop == null) {
+ viewportTop = scrollTop;
+ }
- return {
- top: Math.floor((scrollTop+offset)/options.rowHeight),
- bottom: Math.ceil((scrollTop+offset+viewportH)/options.rowHeight)
- };
- }
+ return {
+ top:Math.floor((viewportTop + offset) / options.rowHeight),
+ bottom:Math.ceil((viewportTop + offset + viewportH) / options.rowHeight)
+ };
+ }
- function getRenderedRange(viewportTop) {
- var range = getVisibleRange(viewportTop);
- var buffer = Math.round(viewportH/options.rowHeight);
- var minBuffer = 3;
+ function getRenderedRange(viewportTop) {
+ var range = getVisibleRange(viewportTop);
+ var buffer = Math.round(viewportH / options.rowHeight);
+ var minBuffer = 3;
+
+ if (scrollDir == -1) {
+ range.top -= buffer;
+ range.bottom += minBuffer;
+ } else if (scrollDir == 1) {
+ range.top -= minBuffer;
+ range.bottom += buffer;
+ } else {
+ range.top -= minBuffer;
+ range.bottom += minBuffer;
+ }
+
+ range.top = Math.max(0, range.top);
+ range.bottom = Math.min(options.enableAddRow ? getDataLength() : getDataLength() - 1, range.bottom);
+
+ return range;
+ }
- if (scrollDir == -1) {
- range.top -= buffer;
- range.bottom += minBuffer;
- }
- else if (scrollDir == 1) {
- range.top -= minBuffer;
- range.bottom += buffer;
- }
- else {
- range.top -= minBuffer;
- range.bottom += minBuffer;
- }
+ function renderRows(range) {
+ var i, l,
+ parentNode = $canvas[0],
+ rowsBefore = renderedRows,
+ stringArray = [],
+ rows = [],
+ startTimestamp = new Date(),
+ needToReselectCell = false;
+
+ for (i = range.top; i <= range.bottom; i++) {
+ if (rowsCache[i]) {
+ continue;
+ }
+ renderedRows++;
+ rows.push(i);
+ appendRowHtml(stringArray, i);
+ if (activeCellNode && activeRow === i) {
+ needToReselectCell = true;
+ }
+ counter_rows_rendered++;
+ }
+
+ var x = document.createElement("div");
+ x.innerHTML = stringArray.join("");
+
+ for (i = 0, l = x.childNodes.length; i < l; i++) {
+ rowsCache[rows[i]] = parentNode.appendChild(x.firstChild);
+ }
+
+ if (needToReselectCell) {
+ activeCellNode = getCellNode(activeRow, activeCell);
+ }
+
+ if (renderedRows - rowsBefore > 5) {
+ avgRowRenderTime = (new Date() - startTimestamp) / (renderedRows - rowsBefore);
+ }
+ }
- range.top = Math.max(0,range.top);
- range.bottom = Math.min(options.enableAddRow ? getDataLength() : getDataLength() - 1,range.bottom);
+ function startPostProcessing() {
+ if (!options.enableAsyncPostRender) {
+ return;
+ }
+ clearTimeout(h_postrender);
+ h_postrender = setTimeout(asyncPostProcessRows, options.asyncPostRenderDelay);
+ }
- return range;
- }
+ function invalidatePostProcessingResults(row) {
+ delete postProcessedRows[row];
+ postProcessFromRow = Math.min(postProcessFromRow, row);
+ postProcessToRow = Math.max(postProcessToRow, row);
+ startPostProcessing();
+ }
- function renderRows(range) {
- var i, l,
- parentNode = $canvas[0],
- rowsBefore = renderedRows,
- stringArray = [],
- rows = [],
- startTimestamp = new Date(),
- needToReselectCell = false;
+ function updateRowPositions() {
+ for (var row in rowsCache) {
+ rowsCache[row].style.top = (row * options.rowHeight - offset) + "px";
+ }
+ }
- for (i = range.top; i <= range.bottom; i++) {
- if (rowsCache[i]) { continue; }
- renderedRows++;
- rows.push(i);
- appendRowHtml(stringArray,i);
- if (activeCellNode && activeRow === i) {
- needToReselectCell = true;
- }
- counter_rows_rendered++;
- }
+ function render() {
+ var visible = getVisibleRange();
+ var rendered = getRenderedRange();
- var x = document.createElement("div");
- x.innerHTML = stringArray.join("");
+ // remove rows no longer in the viewport
+ cleanupRows(rendered);
- for (i = 0, l = x.childNodes.length; i < l; i++) {
- rowsCache[rows[i]] = parentNode.appendChild(x.firstChild);
- }
+ // add new rows
+ renderRows(rendered);
- if (needToReselectCell) {
- activeCellNode = getCellNode(activeRow,activeCell);
- }
+ postProcessFromRow = visible.top;
+ postProcessToRow = Math.min(options.enableAddRow ? getDataLength() : getDataLength() - 1, visible.bottom);
+ startPostProcessing();
- if (renderedRows - rowsBefore > 5) {
- avgRowRenderTime = (new Date() - startTimestamp) / (renderedRows - rowsBefore);
- }
- }
+ lastRenderedScrollTop = scrollTop;
+ h_render = null;
+ }
- function startPostProcessing() {
- if (!options.enableAsyncPostRender) { return; }
- clearTimeout(h_postrender);
- h_postrender = setTimeout(asyncPostProcessRows, options.asyncPostRenderDelay);
+ function handleScroll() {
+ scrollTop = $viewport[0].scrollTop;
+ var scrollLeft = $viewport[0].scrollLeft;
+ var scrollDist = Math.abs(scrollTop - prevScrollTop);
+
+ if (scrollLeft !== prevScrollLeft) {
+ prevScrollLeft = scrollLeft;
+ $headerScroller[0].scrollLeft = scrollLeft;
+ $topPanelScroller[0].scrollLeft = scrollLeft;
+ $headerRowScroller[0].scrollLeft = scrollLeft;
+ }
+
+ if (scrollDist) {
+ scrollDir = prevScrollTop < scrollTop ? 1 : -1;
+ prevScrollTop = scrollTop;
+
+ // switch virtual pages if needed
+ if (scrollDist < viewportH) {
+ scrollTo(scrollTop + offset);
+ } else {
+ var oldOffset = offset;
+ page = Math.min(n - 1, Math.floor(scrollTop * ((th - viewportH) / (h - viewportH)) * (1 / ph)));
+ offset = Math.round(page * cj);
+ if (oldOffset != offset) {
+ invalidateAllRows();
+ }
}
- function invalidatePostProcessingResults(row) {
- delete postProcessedRows[row];
- postProcessFromRow = Math.min(postProcessFromRow,row);
- postProcessToRow = Math.max(postProcessToRow,row);
- startPostProcessing();
+ if (h_render) {
+ clearTimeout(h_render);
}
- function updateRowPositions() {
- for (var row in rowsCache) {
- rowsCache[row].style.top = (row*options.rowHeight-offset) + "px";
- }
+ if (Math.abs(lastRenderedScrollTop - scrollTop) < viewportH) {
+ render();
+ } else {
+ h_render = setTimeout(render, 50);
}
- function render() {
- var visible = getVisibleRange();
- var rendered = getRenderedRange();
-
- // remove rows no longer in the viewport
- cleanupRows(rendered);
-
- // add new rows
- renderRows(rendered);
+ trigger(self.onViewportChanged, {});
+ }
- postProcessFromRow = visible.top;
- postProcessToRow = Math.min(options.enableAddRow ? getDataLength() : getDataLength() - 1, visible.bottom);
- startPostProcessing();
+ trigger(self.onScroll, {scrollLeft:scrollLeft, scrollTop:scrollTop});
+ }
- lastRenderedScrollTop = scrollTop;
- h_render = null;
+ function asyncPostProcessRows() {
+ while (postProcessFromRow <= postProcessToRow) {
+ var row = (scrollDir >= 0) ? postProcessFromRow++ : postProcessToRow--;
+ var rowNode = rowsCache[row];
+ if (!rowNode || postProcessedRows[row] || row >= getDataLength()) {
+ continue;
}
- function handleScroll() {
- scrollTop = $viewport[0].scrollTop;
- var scrollLeft = $viewport[0].scrollLeft;
- var scrollDist = Math.abs(scrollTop - prevScrollTop);
-
- if (scrollLeft !== prevScrollLeft) {
- prevScrollLeft = scrollLeft;
- $headerScroller[0].scrollLeft = scrollLeft;
- $topPanelScroller[0].scrollLeft = scrollLeft;
- $headerRowScroller[0].scrollLeft = scrollLeft;
- }
-
- if (scrollDist) {
- scrollDir = prevScrollTop < scrollTop ? 1 : -1;
- prevScrollTop = scrollTop;
-
- // switch virtual pages if needed
- if (scrollDist < viewportH) {
- scrollTo(scrollTop + offset);
- }
- else {
- var oldOffset = offset;
- page = Math.min(n - 1, Math.floor(scrollTop * ((th - viewportH) / (h - viewportH)) * (1 / ph)));
- offset = Math.round(page * cj);
- if (oldOffset != offset)
- invalidateAllRows();
- }
-
- if (h_render)
- clearTimeout(h_render);
-
- if (Math.abs(lastRenderedScrollTop - scrollTop) < viewportH)
- render();
- else
- h_render = setTimeout(render, 50);
-
- trigger(self.onViewportChanged, {});
- }
-
- trigger(self.onScroll, {scrollLeft:scrollLeft, scrollTop:scrollTop});
+ var d = getDataItem(row), cellNodes = rowNode.childNodes;
+ for (var i = 0, j = 0, l = columns.length; i < l; ++i) {
+ var m = columns[i];
+ if (m.asyncPostRender) {
+ m.asyncPostRender(cellNodes[j], postProcessFromRow, d, m);
+ }
+ ++j;
}
- function asyncPostProcessRows() {
- while (postProcessFromRow <= postProcessToRow) {
- var row = (scrollDir >= 0) ? postProcessFromRow++ : postProcessToRow--;
- var rowNode = rowsCache[row];
- if (!rowNode || postProcessedRows[row] || row>=getDataLength()) { continue; }
-
- var d = getDataItem(row), cellNodes = rowNode.childNodes;
- for (var i=0, j=0, l=columns.length; i<l; ++i) {
- var m = columns[i];
- if (m.asyncPostRender) { m.asyncPostRender(cellNodes[j], postProcessFromRow, d, m); }
- ++j;
- }
-
- postProcessedRows[row] = true;
- h_postrender = setTimeout(asyncPostProcessRows, options.asyncPostRenderDelay);
- return;
- }
- }
+ postProcessedRows[row] = true;
+ h_postrender = setTimeout(asyncPostProcessRows, options.asyncPostRenderDelay);
+ return;
+ }
+ }
- function addCellCssStyles(key,hash) {
- if (cellCssClasses[key]) {
- throw "addCellCssStyles: cell CSS hash with key '" + key + "' already exists.";
- }
+ function addCellCssStyles(key, hash) {
+ if (cellCssClasses[key]) {
+ throw "addCellCssStyles: cell CSS hash with key '" + key + "' already exists.";
+ }
- cellCssClasses[key] = hash;
+ cellCssClasses[key] = hash;
- 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]);
- }
- }
- }
+ 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]);
}
+ }
}
+ }
+ }
- function removeCellCssStyles(key) {
- if (!cellCssClasses[key]) {
- return;
- }
+ 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]);
- }
- }
- }
+ 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]);
}
-
- delete cellCssClasses[key];
- }
-
- function setCellCssStyles(key,hash) {
- removeCellCssStyles(key);
- addCellCssStyles(key,hash);
+ }
}
+ }
- function flashCell(row, cell, speed) {
- speed = speed || 100;
- if (rowsCache[row]) {
- var $cell = $(getCellNode(row,cell));
+ delete cellCssClasses[key];
+ }
- function toggleCellClass(times) {
- if (!times) return;
- setTimeout(function() {
- $cell.queue(function() {
- $cell.toggleClass(options.cellFlashingCssClass).dequeue();
- toggleCellClass(times-1);
- });
- },
- speed);
- }
+ function setCellCssStyles(key, hash) {
+ removeCellCssStyles(key);
+ addCellCssStyles(key, hash);
+ }
- toggleCellClass(4);
- }
+ function flashCell(row, cell, speed) {
+ speed = speed || 100;
+ if (rowsCache[row]) {
+ var $cell = $(getCellNode(row, cell));
+
+ function toggleCellClass(times) {
+ if (!times) {
+ return;
+ }
+ setTimeout(function () {
+ $cell.queue(function () {
+ $cell.toggleClass(options.cellFlashingCssClass).dequeue();
+ toggleCellClass(times - 1);
+ });
+ },
+ speed);
}
- //////////////////////////////////////////////////////////////////////////////////////////////
- // Interactivity
-
- function handleDragInit(e,dd) {
- var cell = getCellFromEvent(e);
- if (!cell || !cellExists(cell.row, cell.cell)) {
- return false;
- }
-
- retval = trigger(self.onDragInit, dd, e);
- if (e.isImmediatePropagationStopped()) {
- return retval;
- }
-
- // if nobody claims to be handling drag'n'drop by stopping immediate propagation,
- // cancel out of it
- return false;
- }
+ toggleCellClass(4);
+ }
+ }
- function handleDragStart(e,dd) {
- var cell = getCellFromEvent(e);
- if (!cell || !cellExists(cell.row, cell.cell)) {
- return false;
- }
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ // Interactivity
+
+ function handleDragInit(e, dd) {
+ var cell = getCellFromEvent(e);
+ if (!cell || !cellExists(cell.row, cell.cell)) {
+ return false;
+ }
+
+ retval = trigger(self.onDragInit, dd, e);
+ if (e.isImmediatePropagationStopped()) {
+ return retval;
+ }
+
+ // if nobody claims to be handling drag'n'drop by stopping immediate propagation,
+ // cancel out of it
+ return false;
+ }
- var retval = trigger(self.onDragStart, dd, e);
- if (e.isImmediatePropagationStopped()) {
- return retval;
- }
+ function handleDragStart(e, dd) {
+ var cell = getCellFromEvent(e);
+ if (!cell || !cellExists(cell.row, cell.cell)) {
+ return false;
+ }
- return false;
- }
+ var retval = trigger(self.onDragStart, dd, e);
+ if (e.isImmediatePropagationStopped()) {
+ return retval;
+ }
- function handleDrag(e,dd) {
- return trigger(self.onDrag, dd, e);
- }
+ return false;
+ }
- function handleDragEnd(e,dd) {
- trigger(self.onDragEnd, dd, e);
- }
+ function handleDrag(e, dd) {
+ return trigger(self.onDrag, dd, e);
+ }
- function handleKeyDown(e) {
- trigger(self.onKeyDown, {}, e);
- var handled = e.isImmediatePropagationStopped();
+ function handleDragEnd(e, dd) {
+ trigger(self.onDragEnd, dd, e);
+ }
- if (!handled) {
- if (!e.shiftKey && !e.altKey && !e.ctrlKey) {
- if (e.which == 27) {
- if (!getEditorLock().isActive()) {
- return; // no editing mode to cancel, allow bubbling and default processing (exit without cancelling the event)
- }
- cancelEditAndSetFocus();
- }
- else if (e.which == 37) {
- navigateLeft();
- }
- else if (e.which == 39) {
- navigateRight();
- }
- else if (e.which == 38) {
- navigateUp();
- }
- else if (e.which == 40) {
- navigateDown();
- }
- else if (e.which == 9) {
- navigateNext();
- }
- else if (e.which == 13) {
- if (options.editable) {
- if (currentEditor) {
- // adding new row
- if (activeRow === getDataLength()) {
- navigateDown();
- }
- else {
- commitEditAndSetFocus();
- }
- } else {
- if (getEditorLock().commitCurrentEdit()) {
- makeActiveCellEditable();
- }
- }
- }
- }
- else
- return;
+ function handleKeyDown(e) {
+ trigger(self.onKeyDown, {}, e);
+ var handled = e.isImmediatePropagationStopped();
+
+ if (!handled) {
+ if (!e.shiftKey && !e.altKey && !e.ctrlKey) {
+ if (e.which == 27) {
+ if (!getEditorLock().isActive()) {
+ return; // no editing mode to cancel, allow bubbling and default processing (exit without cancelling the event)
+ }
+ cancelEditAndSetFocus();
+ } else if (e.which == 37) {
+ navigateLeft();
+ } else if (e.which == 39) {
+ navigateRight();
+ } else if (e.which == 38) {
+ navigateUp();
+ } else if (e.which == 40) {
+ navigateDown();
+ } else if (e.which == 9) {
+ navigateNext();
+ } else if (e.which == 13) {
+ if (options.editable) {
+ if (currentEditor) {
+ // adding new row
+ if (activeRow === getDataLength()) {
+ navigateDown();
}
- else if (e.which == 9 && e.shiftKey && !e.ctrlKey && !e.altKey) {
- navigatePrev();
+ else {
+ commitEditAndSetFocus();
}
- else
- return;
- }
-
- // the event has been handled so don't let parent element (bubbling/propagation) or browser (default) handle it
- e.stopPropagation();
- e.preventDefault();
- try {
- e.originalEvent.keyCode = 0; // prevent default behaviour for special keys in IE browsers (F3, F5, etc.)
- }
- catch (error) {} // ignore exceptions - setting the original event's keycode throws access denied exception for "Ctrl" (hitting control key only, nothing else), "Shift" (maybe others)
- }
-
- function handleClick(e) {
- var cell = getCellFromEvent(e);
- if (!cell || (currentEditor !== null && activeRow == cell.row && activeCell == cell.cell)) {
- return;
- }
-
- trigger(self.onClick, {row:cell.row, cell:cell.cell}, e);
- if (e.isImmediatePropagationStopped()) {
- return;
- }
-
- if (canCellBeActive(cell.row, cell.cell)) {
- if (!getEditorLock().isActive() || getEditorLock().commitCurrentEdit()) {
- scrollRowIntoView(cell.row,false);
- setActiveCellInternal(getCellNode(cell.row,cell.cell), (cell.row === getDataLength()) || options.autoEdit);
+ } else {
+ if (getEditorLock().commitCurrentEdit()) {
+ makeActiveCellEditable();
}
- }
- }
-
- function handleContextMenu(e) {
- var $cell = $(e.target).closest(".slick-cell", $canvas);
- if ($cell.length === 0) { return; }
-
- // are we editing this cell?
- if (activeCellNode === $cell[0] && currentEditor !== null) { return; }
-
- trigger(self.onContextMenu, {}, e);
- }
-
- function handleDblClick(e) {
- var cell = getCellFromEvent(e);
- if (!cell || (currentEditor !== null && activeRow == cell.row && activeCell == cell.cell)) {
- return;
- }
-
- trigger(self.onDblClick, {row:cell.row, cell:cell.cell}, e);
- if (e.isImmediatePropagationStopped()) {
- return;
- }
-
- if (options.editable) {
- gotoCell(cell.row, cell.cell, true);
- }
- }
-
- function handleHeaderContextMenu(e) {
- var $header = $(e.target).closest(".slick-header-column", ".slick-header-columns");
- var column = $header && columns[self.getColumnIndex($header.data("fieldId"))];
- trigger(self.onHeaderContextMenu, {column: column}, e);
- }
-
- function handleHeaderClick(e) {
- var $header = $(e.target).closest(".slick-header-column", ".slick-header-columns");
- var column = $header && columns[self.getColumnIndex($header.data("fieldId"))];
- trigger(self.onHeaderClick, {column: column}, e);
- }
+ }
+ }
+ } else {
+ return;
+ }
+ } else if (e.which == 9 && e.shiftKey && !e.ctrlKey && !e.altKey) {
+ navigatePrev();
+ } else {
+ return;
+ }
+ }
+
+ // the event has been handled so don't let parent element (bubbling/propagation) or browser (default) handle it
+ e.stopPropagation();
+ e.preventDefault();
+ try {
+ e.originalEvent.keyCode = 0; // prevent default behaviour for special keys in IE browsers (F3, F5, etc.)
+ }
+ // ignore exceptions - setting the original event's keycode throws access denied exception for "Ctrl"
+ // (hitting control key only, nothing else), "Shift" (maybe others)
+ catch (error) {
+ }
+ }
- function handleMouseEnter(e) {
- trigger(self.onMouseEnter, {}, e);
- }
+ function handleClick(e) {
+ var cell = getCellFromEvent(e);
+ if (!cell || (currentEditor !== null && activeRow == cell.row && activeCell == cell.cell)) {
+ return;
+ }
- function handleMouseLeave(e) {
- trigger(self.onMouseLeave, {}, e);
- }
+ trigger(self.onClick, {row:cell.row, cell:cell.cell}, e);
+ if (e.isImmediatePropagationStopped()) {
+ return;
+ }
- function cellExists(row,cell) {
- return !(row < 0 || row >= getDataLength() || cell < 0 || cell >= columns.length);
+ if (canCellBeActive(cell.row, cell.cell)) {
+ if (!getEditorLock().isActive() || getEditorLock().commitCurrentEdit()) {
+ scrollRowIntoView(cell.row, false);
+ setActiveCellInternal(getCellNode(cell.row, cell.cell), (cell.row === getDataLength()) || options.autoEdit);
}
+ }
+ }
- function getCellFromPoint(x,y) {
- var row = Math.floor((y+offset)/options.rowHeight);
- var cell = 0;
-
- var w = 0;
- for (var i=0; i<columns.length && w<x; i++) {
- w += columns[i].width;
- cell++;
- }
-
- if (cell < 0) {
- cell = 0;
- }
-
- return {row:row,cell:cell-1};
- }
+ function handleContextMenu(e) {
+ var $cell = $(e.target).closest(".slick-cell", $canvas);
+ if ($cell.length === 0) {
+ return;
+ }
- function getCellFromNode(node) {
- // read column number from .l1 or .c1 CSS classes
- var cls = /l\d+/.exec(node.className) || /c\d+/.exec(node.className);
- if (!cls)
- throw "getCellFromNode: cannot get cell - " + node.className;
- return parseInt(cls[0].substr(1, cls[0].length-1), 10);
- }
+ // are we editing this cell?
+ if (activeCellNode === $cell[0] && currentEditor !== null) {
+ return;
+ }
- function getCellFromEvent(e) {
- var $cell = $(e.target).closest(".slick-cell", $canvas);
- if (!$cell.length)
- return null;
+ trigger(self.onContextMenu, {}, e);
+ }
- return {
- row: $cell.parent().attr("row") | 0,
- cell: getCellFromNode($cell[0])
- };
- }
+ function handleDblClick(e) {
+ var cell = getCellFromEvent(e);
+ if (!cell || (currentEditor !== null && activeRow == cell.row && activeCell == cell.cell)) {
+ return;
+ }
- function getCellNodeBox(row,cell) {
- if (!cellExists(row,cell))
- return null;
+ trigger(self.onDblClick, {row:cell.row, cell:cell.cell}, e);
+ if (e.isImmediatePropagationStopped()) {
+ return;
+ }
- var y1 = row * options.rowHeight - offset;
- var y2 = y1 + options.rowHeight - 1;
- var x1 = 0;
- for (var i=0; i<cell; i++) {
- x1 += columns[i].width;
- }
- var x2 = x1 + columns[cell].width;
+ if (options.editable) {
+ gotoCell(cell.row, cell.cell, true);
+ }
+ }
- return {
- top: y1,
- left: x1,
- bottom: y2,
- right: x2
- };
- }
+ function handleHeaderContextMenu(e) {
+ var $header = $(e.target).closest(".slick-header-column", ".slick-header-columns");
+ var column = $header && columns[self.getColumnIndex($header.data("fieldId"))];
+ trigger(self.onHeaderContextMenu, {column:column}, e);
+ }
- //////////////////////////////////////////////////////////////////////////////////////////////
- // Cell switching
+ function handleHeaderClick(e) {
+ var $header = $(e.target).closest(".slick-header-column", ".slick-header-columns");
+ var column = $header && columns[self.getColumnIndex($header.data("fieldId"))];
+ trigger(self.onHeaderClick, {column:column}, e);
+ }
- function resetActiveCell() {
- setActiveCellInternal(null,false);
- }
+ function handleMouseEnter(e) {
+ trigger(self.onMouseEnter, {}, e);
+ }
- function setFocus() {
- // IE tries to scroll the viewport so that the item being focused is aligned to the left border
- // IE-specific .setActive() sets the focus, but doesn't scroll
- if ($.browser.msie) {
- $canvas[0].setActive();
- }
- else {
- $canvas[0].focus();
- }
- }
+ function handleMouseLeave(e) {
+ trigger(self.onMouseLeave, {}, e);
+ }
- function scrollActiveCellIntoView() {
- if (activeCellNode) {
- var left = $(activeCellNode).position().left,
- right = left + $(activeCellNode).outerWidth(),
- scrollLeft = $viewport.scrollLeft(),
- scrollRight = scrollLeft + $viewport.width();
+ function cellExists(row, cell) {
+ return !(row < 0 || row >= getDataLength() || cell < 0 || cell >= columns.length);
+ }
- if (left < scrollLeft)
- $viewport.scrollLeft(left);
- else if (right > scrollRight)
- $viewport.scrollLeft(Math.min(left, right - $viewport[0].clientWidth));
- }
- }
+ function getCellFromPoint(x, y) {
+ var row = Math.floor((y + offset) / options.rowHeight);
+ var cell = 0;
- function setActiveCellInternal(newCell, editMode) {
- if (activeCellNode !== null) {
- makeActiveCellNormal();
- $(activeCellNode).removeClass("active");
- }
+ var w = 0;
+ for (var i = 0; i < columns.length && w < x; i++) {
+ w += columns[i].width;
+ cell++;
+ }
- var activeCellChanged = (activeCellNode !== newCell);
- activeCellNode = newCell;
+ if (cell < 0) {
+ cell = 0;
+ }
- if (activeCellNode != null) {
- activeRow = parseInt($(activeCellNode).parent().attr("row"));
- activeCell = activePosX = getCellFromNode(activeCellNode);
+ return {row:row, cell:cell - 1};
+ }
- $(activeCellNode).addClass("active");
+ function getCellFromNode(node) {
+ // read column number from .l1 or .c1 CSS classes
+ var cls = /l\d+/.exec(node.className) || /c\d+/.exec(node.className);
+ if (!cls) {
+ throw "getCellFromNode: cannot get cell - " + node.className;
+ }
+ return parseInt(cls[0].substr(1, cls[0].length - 1), 10);
+ }
- if (options.editable && editMode && isCellPotentiallyEditable(activeRow,activeCell)) {
- clearTimeout(h_editorLoader);
+ function getCellFromEvent(e) {
+ var $cell = $(e.target).closest(".slick-cell", $canvas);
+ if (!$cell.length) {
+ return null;
+ }
- if (options.asyncEditorLoading) {
- h_editorLoader = setTimeout(function() { makeActiveCellEditable(); }, options.asyncEditorLoadDelay);
- }
- else {
- makeActiveCellEditable();
- }
- }
- else {
- setFocus();
- }
- }
- else {
- activeRow = activeCell = null;
- }
+ return {
+ row:$cell.parent().attr("row") | 0,
+ cell:getCellFromNode($cell[0])
+ };
+ }
- if (activeCellChanged) {
- scrollActiveCellIntoView();
- trigger(self.onActiveCellChanged, getActiveCell());
- }
- }
+ function getCellNodeBox(row, cell) {
+ if (!cellExists(row, cell)) {
+ return null;
+ }
+
+ var y1 = row * options.rowHeight - offset;
+ var y2 = y1 + options.rowHeight - 1;
+ var x1 = 0;
+ for (var i = 0; i < cell; i++) {
+ x1 += columns[i].width;
+ }
+ var x2 = x1 + columns[cell].width;
+
+ return {
+ top:y1,
+ left:x1,
+ bottom:y2,
+ right:x2
+ };
+ }
- function clearTextSelection() {
- if (document.selection && document.selection.empty) {
- document.selection.empty();
- }
- else if (window.getSelection) {
- var sel = window.getSelection();
- if (sel && sel.removeAllRanges) {
- sel.removeAllRanges();
- }
- }
- }
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ // Cell switching
- function isCellPotentiallyEditable(row, cell) {
- // is the data for this row loaded?
- if (row < getDataLength() && !getDataItem(row)) {
- return false;
- }
+ function resetActiveCell() {
+ setActiveCellInternal(null, false);
+ }
- // are we in the Add New row? can we create new from this cell?
- if (columns[cell].cannotTriggerInsert && row >= getDataLength()) {
- return false;
- }
+ function setFocus() {
+ // IE tries to scroll the viewport so that the item being focused is aligned to the left border
+ // IE-specific .setActive() sets the focus, but doesn't scroll
+ if ($.browser.msie) {
+ $canvas[0].setActive();
+ } else {
+ $canvas[0].focus();
+ }
+ }
- // does this cell have an editor?
- if (!getEditor(row, cell)) {
- return false;
- }
+ function scrollActiveCellIntoView() {
+ if (activeCellNode) {
+ var left = $(activeCellNode).position().left,
+ right = left + $(activeCellNode).outerWidth(),
+ scrollLeft = $viewport.scrollLeft(),
+ scrollRight = scrollLeft + $viewport.width();
- return true;
+ if (left < scrollLeft) {
+ $viewport.scrollLeft(left);
+ } else if (right > scrollRight) {
+ $viewport.scrollLeft(Math.min(left, right - $viewport[0].clientWidth));
}
+ }
+ }
- function makeActiveCellNormal() {
- if (!currentEditor) { return; }
- trigger(self.onBeforeCellEditorDestroy, {editor:currentEditor});
- currentEditor.destroy();
- currentEditor = null;
-
- if (activeCellNode) {
- var d = getDataItem(activeRow);
-
- $(activeCellNode).removeClass("editable invalid");
-
- if (d) {
- var column = columns[activeCell];
- activeCellNode.innerHTML = getFormatter(activeRow, column)(activeRow, activeCell, getDataItemValueForColumn(d, column), column, getDataItem(activeRow));
- invalidatePostProcessingResults(activeRow);
- }
- }
-
- // if there previously was text selected on a page (such as selected text in the edit cell just removed),
- // IE can't set focus to anything else correctly
- if ($.browser.msie) { clearTextSelection(); }
+ function setActiveCellInternal(newCell, editMode) {
+ if (activeCellNode !== null) {
+ makeActiveCellNormal();
+ $(activeCellNode).removeClass("active");
+ }
+
+ var activeCellChanged = (activeCellNode !== newCell);
+ activeCellNode = newCell;
+
+ if (activeCellNode != null) {
+ activeRow = parseInt($(activeCellNode).parent().attr("row"));
+ activeCell = activePosX = getCellFromNode(activeCellNode);
+
+ $(activeCellNode).addClass("active");
+
+ if (options.editable && editMode && isCellPotentiallyEditable(activeRow, activeCell)) {
+ clearTimeout(h_editorLoader);
+
+ if (options.asyncEditorLoading) {
+ h_editorLoader = setTimeout(function () {
+ makeActiveCellEditable();
+ }, options.asyncEditorLoadDelay);
+ } else {
+ makeActiveCellEditable();
+ }
+ } else {
+ setFocus();
+ }
+ } else {
+ activeRow = activeCell = null;
+ }
+
+ if (activeCellChanged) {
+ scrollActiveCellIntoView();
+ trigger(self.onActiveCellChanged, getActiveCell());
+ }
+ }
- getEditorLock().deactivate(editController);
+ function clearTextSelection() {
+ if (document.selection && document.selection.empty) {
+ document.selection.empty();
+ } else if (window.getSelection) {
+ var sel = window.getSelection();
+ if (sel && sel.removeAllRanges) {
+ sel.removeAllRanges();
}
+ }
+ }
- function makeActiveCellEditable(editor) {
- if (!activeCellNode) { return; }
- if (!options.editable) {
- throw "Grid : makeActiveCellEditable : should never get called when options.editable is false";
- }
-
- // cancel pending async call if there is one
- clearTimeout(h_editorLoader);
-
- if (!isCellPotentiallyEditable(activeRow,activeCell)) {
- return;
- }
+ function isCellPotentiallyEditable(row, cell) {
+ // is the data for this row loaded?
+ if (row < getDataLength() && !getDataItem(row)) {
+ return false;
+ }
- var columnDef = columns[activeCell];
- var item = getDataItem(activeRow);
+ // are we in the Add New row? can we create new from this cell?
+ if (columns[cell].cannotTriggerInsert && row >= getDataLength()) {
+ return false;
+ }
- if (trigger(self.onBeforeEditCell, {row:activeRow, cell:activeCell, item:item, column:columnDef}) === false) {
- setFocus();
- return;
- }
+ // does this cell have an editor?
+ if (!getEditor(row, cell)) {
+ return false;
+ }
- getEditorLock().activate(editController);
- $(activeCellNode).addClass("editable");
-
- // don't clear the cell if a custom editor is passed through
- if (!editor) {
- activeCellNode.innerHTML = "";
- }
-
- currentEditor = new (editor || getEditor(activeRow, activeCell))({
- grid: self,
- gridPosition: absBox($container[0]),
- position: absBox(activeCellNode),
- container: activeCellNode,
- column: columnDef,
- item: item || {},
- commitChanges: commitEditAndSetFocus,
- cancelChanges: cancelEditAndSetFocus
- });
+ return true;
+ }
- if (item)
- currentEditor.loadValue(item);
+ function makeActiveCellNormal() {
+ if (!currentEditor) {
+ return;
+ }
+ trigger(self.onBeforeCellEditorDestroy, {editor:currentEditor});
+ currentEditor.destroy();
+ currentEditor = null;
+
+ if (activeCellNode) {
+ var d = getDataItem(activeRow);
+ $(activeCellNode).removeClass("editable invalid");
+ if (d) {
+ var column = columns[activeCell];
+ var formatter = getFormatter(activeRow, column);
+ activeCellNode.innerHTML = formatter(activeRow, activeCell, getDataItemValueForColumn(d, column), column, getDataItem(activeRow));
+ invalidatePostProcessingResults(activeRow);
+ }
+ }
+
+ // if there previously was text selected on a page (such as selected text in the edit cell just removed),
+ // IE can't set focus to anything else correctly
+ if ($.browser.msie) {
+ clearTextSelection();
+ }
+
+ getEditorLock().deactivate(editController);
+ }
- serializedEditorValue = currentEditor.serializeValue();
+ function makeActiveCellEditable(editor) {
+ if (!activeCellNode) {
+ return;
+ }
+ if (!options.editable) {
+ throw "Grid : makeActiveCellEditable : should never get called when options.editable is false";
+ }
+
+ // cancel pending async call if there is one
+ clearTimeout(h_editorLoader);
+
+ if (!isCellPotentiallyEditable(activeRow, activeCell)) {
+ return;
+ }
+
+ var columnDef = columns[activeCell];
+ var item = getDataItem(activeRow);
+
+ if (trigger(self.onBeforeEditCell, {row:activeRow, cell:activeCell, item:item, column:columnDef}) === false) {
+ setFocus();
+ return;
+ }
+
+ getEditorLock().activate(editController);
+ $(activeCellNode).addClass("editable");
+
+ // don't clear the cell if a custom editor is passed through
+ if (!editor) {
+ activeCellNode.innerHTML = "";
+ }
+
+ currentEditor = new (editor || getEditor(activeRow, activeCell))({
+ grid:self,
+ gridPosition:absBox($container[0]),
+ position:absBox(activeCellNode),
+ container:activeCellNode,
+ column:columnDef,
+ item:item || {},
+ commitChanges:commitEditAndSetFocus,
+ cancelChanges:cancelEditAndSetFocus
+ });
+
+ if (item) {
+ currentEditor.loadValue(item);
+ }
+
+ serializedEditorValue = currentEditor.serializeValue();
+
+ if (currentEditor.position) {
+ handleActiveCellPositionChange();
+ }
+ }
- if (currentEditor.position)
- handleActiveCellPositionChange();
+ function commitEditAndSetFocus() {
+ // if the commit fails, it would do so due to a validation error
+ // if so, do not steal the focus from the editor
+ if (getEditorLock().commitCurrentEdit()) {
+ setFocus();
+ if (options.autoEdit) {
+ navigateDown();
}
+ }
+ }
- function commitEditAndSetFocus() {
- // if the commit fails, it would do so due to a validation error
- // if so, do not steal the focus from the editor
- if (getEditorLock().commitCurrentEdit()) {
- setFocus();
+ function cancelEditAndSetFocus() {
+ if (getEditorLock().cancelCurrentEdit()) {
+ setFocus();
+ }
+ }
- if (options.autoEdit) {
- navigateDown();
- }
- }
- }
+ function absBox(elem) {
+ var box = {
+ top:elem.offsetTop,
+ left:elem.offsetLeft,
+ bottom:0,
+ right:0,
+ width:$(elem).outerWidth(),
+ height:$(elem).outerHeight(),
+ visible:true};
+ box.bottom = box.top + box.height;
+ box.right = box.left + box.width;
- function cancelEditAndSetFocus() {
- if (getEditorLock().cancelCurrentEdit()) {
- setFocus();
- }
+ // walk up the tree
+ var offsetParent = elem.offsetParent;
+ while ((elem = elem.parentNode) != document.body) {
+ if (box.visible && elem.scrollHeight != elem.offsetHeight && $(elem).css("overflowY") != "visible") {
+ box.visible = box.bottom > elem.scrollTop && box.top < elem.scrollTop + elem.clientHeight;
}
- function absBox(elem) {
- var box = {top:elem.offsetTop, left:elem.offsetLeft, bottom:0, right:0, width:$(elem).outerWidth(), height:$(elem).outerHeight(), visible:true};
- box.bottom = box.top + box.height;
- box.right = box.left + box.width;
-
- // walk up the tree
- var offsetParent = elem.offsetParent;
- while ((elem = elem.parentNode) != document.body) {
- if (box.visible && elem.scrollHeight != elem.offsetHeight && $(elem).css("overflowY") != "visible")
- box.visible = box.bottom > elem.scrollTop && box.top < elem.scrollTop + elem.clientHeight;
-
- if (box.visible && elem.scrollWidth != elem.offsetWidth && $(elem).css("overflowX") != "visible")
- box.visible = box.right > elem.scrollLeft && box.left < elem.scrollLeft + elem.clientWidth;
-
- box.left -= elem.scrollLeft;
- box.top -= elem.scrollTop;
-
- if (elem === offsetParent) {
- box.left += elem.offsetLeft;
- box.top += elem.offsetTop;
- offsetParent = elem.offsetParent;
- }
-
- box.bottom = box.top + box.height;
- box.right = box.left + box.width;
- }
-
- return box;
+ if (box.visible && elem.scrollWidth != elem.offsetWidth && $(elem).css("overflowX") != "visible") {
+ box.visible = box.right > elem.scrollLeft && box.left < elem.scrollLeft + elem.clientWidth;
}
- function getActiveCellPosition(){
- return absBox(activeCellNode);
- }
+ box.left -= elem.scrollLeft;
+ box.top -= elem.scrollTop;
- function getGridPosition(){
- return absBox($container[0])
+ if (elem === offsetParent) {
+ box.left += elem.offsetLeft;
+ box.top += elem.offsetTop;
+ offsetParent = elem.offsetParent;
}
- function handleActiveCellPositionChange() {
- if (!activeCellNode) return;
- var cellBox;
+ box.bottom = box.top + box.height;
+ box.right = box.left + box.width;
+ }
- trigger(self.onActiveCellPositionChanged, {});
+ return box;
+ }
- if (currentEditor) {
- cellBox = cellBox || getActiveCellPosition();
- if (currentEditor.show && currentEditor.hide) {
- if (!cellBox.visible)
- currentEditor.hide();
- else
- currentEditor.show();
- }
+ function getActiveCellPosition() {
+ return absBox(activeCellNode);
+ }
- if (currentEditor.position)
- currentEditor.position(cellBox);
- }
- }
+ function getGridPosition() {
+ return absBox($container[0])
+ }
- function getCellEditor() {
- return currentEditor;
- }
+ function handleActiveCellPositionChange() {
+ if (!activeCellNode) {
+ return;
+ }
- function getActiveCell() {
- if (!activeCellNode)
- return null;
- else
- return {row: activeRow, cell: activeCell};
- }
+ trigger(self.onActiveCellPositionChanged, {});
- function getActiveCellNode() {
- return activeCellNode;
+ if (currentEditor) {
+ var cellBox = getActiveCellPosition();
+ if (currentEditor.show && currentEditor.hide) {
+ if (!cellBox.visible) {
+ currentEditor.hide();
+ } else {
+ currentEditor.show();
+ }
}
- function scrollRowIntoView(row, doPaging) {
- var rowAtTop = row * options.rowHeight;
- var rowAtBottom = (row + 1) * options.rowHeight - viewportH + (viewportHasHScroll?scrollbarDimensions.height:0);
-
- // need to page down?
- if ((row + 1) * options.rowHeight > scrollTop + viewportH + offset) {
- scrollTo(doPaging ? rowAtTop : rowAtBottom);
- render();
- }
-
- // or page up?
- else if (row * options.rowHeight < scrollTop + offset) {
- scrollTo(doPaging ? rowAtBottom : rowAtTop);
- render();
- }
+ if (currentEditor.position) {
+ currentEditor.position(cellBox);
}
+ }
+ }
- function getColspan(row, cell) {
- var metadata = data.getItemMetadata && data.getItemMetadata(row);
- if (!metadata || !metadata.columns) {
- return 1;
- }
+ function getCellEditor() {
+ return currentEditor;
+ }
- var columnData = metadata.columns[columns[cell].id] || metadata.columns[cell];
- var colspan = (columnData && columnData.colspan);
- if (colspan === "*") {
- colspan = columns.length - cell;
- }
- return (colspan || 1);
- }
+ function getActiveCell() {
+ if (!activeCellNode) {
+ return null;
+ } else {
+ return {row:activeRow, cell:activeCell};
+ }
+ }
- function findFirstFocusableCell(row) {
- var cell = 0;
- while (cell < columns.length) {
- if (canCellBeActive(row, cell)) {
- return cell;
- }
- cell += getColspan(row, cell);
- }
- return null;
- }
+ function getActiveCellNode() {
+ return activeCellNode;
+ }
- function findLastFocusableCell(row) {
- var cell = 0;
- var lastFocusableCell = null;
- while (cell < columns.length) {
- if (canCellBeActive(row, cell)) {
- lastFocusableCell = cell;
- }
- cell += getColspan(row, cell);
- }
- return lastFocusableCell;
- }
+ function scrollRowIntoView(row, doPaging) {
+ var rowAtTop = row * options.rowHeight;
+ var rowAtBottom = (row + 1) * options.rowHeight - viewportH + (viewportHasHScroll ? scrollbarDimensions.height : 0);
+
+ // need to page down?
+ if ((row + 1) * options.rowHeight > scrollTop + viewportH + offset) {
+ scrollTo(doPaging ? rowAtTop : rowAtBottom);
+ render();
+ }
+ // or page up?
+ else if (row * options.rowHeight < scrollTop + offset) {
+ scrollTo(doPaging ? rowAtBottom : rowAtTop);
+ render();
+ }
+ }
- function gotoRight(row, cell, posX) {
- if (cell >= columns.length) {
- return null;
- }
+ function getColspan(row, cell) {
+ var metadata = data.getItemMetadata && data.getItemMetadata(row);
+ if (!metadata || !metadata.columns) {
+ return 1;
+ }
+
+ var columnData = metadata.columns[columns[cell].id] || metadata.columns[cell];
+ var colspan = (columnData && columnData.colspan);
+ if (colspan === "*") {
+ colspan = columns.length - cell;
+ }
+ return (colspan || 1);
+ }
- do {
- cell += getColspan(row, cell);
- }
- while (cell < columns.length && !canCellBeActive(row, cell));
-
- if (cell < columns.length) {
- return {
- "row": row,
- "cell": cell,
- "posX": cell
- };
- }
- return null;
+ function findFirstFocusableCell(row) {
+ var cell = 0;
+ while (cell < columns.length) {
+ if (canCellBeActive(row, cell)) {
+ return cell;
}
+ cell += getColspan(row, cell);
+ }
+ return null;
+ }
- function gotoLeft(row, cell, posX) {
- if (cell <= 0) {
- return null;
- }
-
- var firstFocusableCell = findFirstFocusableCell(row);
- if (firstFocusableCell === null || firstFocusableCell >= cell) {
- return null;
- }
-
- var prev = {
- "row": row,
- "cell": firstFocusableCell,
- "posX": firstFocusableCell
- };
- var pos;
- while (true) {
- pos = gotoRight(prev.row, prev.cell, prev.posX);
- if (!pos) {
- return null;
- }
- if (pos.cell >= cell) {
- return prev;
- }
- prev = pos;
- }
+ function findLastFocusableCell(row) {
+ var cell = 0;
+ var lastFocusableCell = null;
+ while (cell < columns.length) {
+ if (canCellBeActive(row, cell)) {
+ lastFocusableCell = cell;
}
+ cell += getColspan(row, cell);
+ }
+ return lastFocusableCell;
+ }
- function gotoDown(row, cell, posX) {
- var prevCell;
- while (true) {
- if (++row >= getDataLength() + (options.enableAddRow ? 1 : 0)) {
- return null;
- }
+ function gotoRight(row, cell, posX) {
+ if (cell >= columns.length) {
+ return null;
+ }
+
+ do {
+ cell += getColspan(row, cell);
+ }
+ while (cell < columns.length && !canCellBeActive(row, cell));
+
+ if (cell < columns.length) {
+ return {
+ "row":row,
+ "cell":cell,
+ "posX":cell
+ };
+ }
+ return null;
+ }
- prevCell = cell = 0;
- while (cell <= posX) {
- prevCell = cell;
- cell += getColspan(row, cell);
- }
+ function gotoLeft(row, cell, posX) {
+ if (cell <= 0) {
+ return null;
+ }
+
+ var firstFocusableCell = findFirstFocusableCell(row);
+ if (firstFocusableCell === null || firstFocusableCell >= cell) {
+ return null;
+ }
+
+ var prev = {
+ "row":row,
+ "cell":firstFocusableCell,
+ "posX":firstFocusableCell
+ };
+ var pos;
+ while (true) {
+ pos = gotoRight(prev.row, prev.cell, prev.posX);
+ if (!pos) {
+ return null;
+ }
+ if (pos.cell >= cell) {
+ return prev;
+ }
+ prev = pos;
+ }
+ }
- if (canCellBeActive(row, prevCell)) {
- return {
- "row": row,
- "cell": prevCell,
- "posX": posX
- };
- }
- }
+ function gotoDown(row, cell, posX) {
+ var prevCell;
+ while (true) {
+ if (++row >= getDataLength() + (options.enableAddRow ? 1 : 0)) {
+ return null;
}
- function gotoUp(row, cell, posX) {
- var prevCell;
- while (true) {
- if (--row < 0) {
- return null;
- }
-
- prevCell = cell = 0;
- while (cell <= posX) {
- prevCell = cell;
- cell += getColspan(row, cell);
- }
-
- if (canCellBeActive(row, prevCell)) {
- return {
- "row": row,
- "cell": prevCell,
- "posX": posX
- };
- }
- }
+ prevCell = cell = 0;
+ while (cell <= posX) {
+ prevCell = cell;
+ cell += getColspan(row, cell);
}
- function gotoNext(row, cell, posX) {
- var pos = gotoRight(row, cell, posX);
- if (pos) {
- return pos;
- }
-
- var firstFocusableCell = null;
- while (++row < getDataLength() + (options.enableAddRow ? 1 : 0)) {
- firstFocusableCell = findFirstFocusableCell(row);
- if (firstFocusableCell !== null) {
- return {
- "row": row,
- "cell": firstFocusableCell,
- "posX": firstFocusableCell
- };
- }
- }
- return null;
+ if (canCellBeActive(row, prevCell)) {
+ return {
+ "row":row,
+ "cell":prevCell,
+ "posX":posX
+ };
}
+ }
+ }
- function gotoPrev(row, cell, posX) {
- var pos;
- var lastSelectableCell;
- while (!pos) {
- pos = gotoLeft(row, cell, posX);
- if (pos) {
- break;
- }
- if (--row < 0) {
- return null;
- }
-
- cell = 0;
- lastSelectableCell = findLastFocusableCell(row);
- if (lastSelectableCell !== null) {
- pos = {
- "row": row,
- "cell": lastSelectableCell,
- "posX": lastSelectableCell
- };
- }
- }
- return pos;
+ function gotoUp(row, cell, posX) {
+ var prevCell;
+ while (true) {
+ if (--row < 0) {
+ return null;
}
- function navigateRight() {
- navigate("right");
+ prevCell = cell = 0;
+ while (cell <= posX) {
+ prevCell = cell;
+ cell += getColspan(row, cell);
}
- function navigateLeft() {
- navigate("left");
+ if (canCellBeActive(row, prevCell)) {
+ return {
+ "row":row,
+ "cell":prevCell,
+ "posX":posX
+ };
}
+ }
+ }
- function navigateDown() {
- navigate("down");
- }
+ function gotoNext(row, cell, posX) {
+ var pos = gotoRight(row, cell, posX);
+ if (pos) {
+ return pos;
+ }
+
+ var firstFocusableCell = null;
+ while (++row < getDataLength() + (options.enableAddRow ? 1 : 0)) {
+ firstFocusableCell = findFirstFocusableCell(row);
+ if (firstFocusableCell !== null) {
+ return {
+ "row":row,
+ "cell":firstFocusableCell,
+ "posX":firstFocusableCell
+ };
+ }
+ }
+ return null;
+ }
- function navigateUp() {
- navigate("up");
- }
+ function gotoPrev(row, cell, posX) {
+ var pos;
+ var lastSelectableCell;
+ while (!pos) {
+ pos = gotoLeft(row, cell, posX);
+ if (pos) {
+ break;
+ }
+ if (--row < 0) {
+ return null;
+ }
+
+ cell = 0;
+ lastSelectableCell = findLastFocusableCell(row);
+ if (lastSelectableCell !== null) {
+ pos = {
+ "row":row,
+ "cell":lastSelectableCell,
+ "posX":lastSelectableCell
+ };
+ }
+ }
+ return pos;
+ }
- function navigateNext() {
- navigate("next");
- }
+ function navigateRight() {
+ navigate("right");
+ }
- function navigatePrev() {
- navigate("prev");
- }
+ function navigateLeft() {
+ navigate("left");
+ }
- function navigate(dir) {
- if (!activeCellNode || !options.enableCellNavigation) { return; }
- if (!getEditorLock().commitCurrentEdit()) { return; }
+ function navigateDown() {
+ navigate("down");
+ }
- var stepFunctions = {
- "up": gotoUp,
- "down": gotoDown,
- "left": gotoLeft,
- "right": gotoRight,
- "prev": gotoPrev,
- "next": gotoNext
- };
- var stepFn = stepFunctions[dir];
- var pos = stepFn(activeRow, activeCell, activePosX);
- if (pos) {
- var isAddNewRow = (pos.row == getDataLength());
- scrollRowIntoView(pos.row, !isAddNewRow);
- setActiveCellInternal(getCellNode(pos.row, pos.cell), isAddNewRow || options.autoEdit);
- activePosX = pos.posX;
- } else {
- setActiveCellInternal(getCellNode(activeRow, activeCell), (activeRow == getDataLength()) || options.autoEdit);
- }
- }
+ function navigateUp() {
+ navigate("up");
+ }
- function getCellNode(row, cell) {
- if (rowsCache[row]) {
- var cells = $(rowsCache[row]).children();
- var nodeCell;
- for (var i = 0; i < cells.length; i++) {
- nodeCell = getCellFromNode(cells[i]);
- if (nodeCell === cell) {
- return cells[i];
- }
- else if (nodeCell > cell) {
- return null;
- }
+ function navigateNext() {
+ navigate("next");
+ }
- }
- }
- return null;
- }
+ function navigatePrev() {
+ navigate("prev");
+ }
- function setActiveCell(row, cell) {
- if (row > getDataLength() || row < 0 || cell >= columns.length || cell < 0) {
- return;
- }
+ function navigate(dir) {
+ if (!activeCellNode || !options.enableCellNavigation) {
+ return;
+ }
+ if (!getEditorLock().commitCurrentEdit()) {
+ return;
+ }
+
+ var stepFunctions = {
+ "up":gotoUp,
+ "down":gotoDown,
+ "left":gotoLeft,
+ "right":gotoRight,
+ "prev":gotoPrev,
+ "next":gotoNext
+ };
+ var stepFn = stepFunctions[dir];
+ var pos = stepFn(activeRow, activeCell, activePosX);
+ if (pos) {
+ var isAddNewRow = (pos.row == getDataLength());
+ scrollRowIntoView(pos.row, !isAddNewRow);
+ setActiveCellInternal(getCellNode(pos.row, pos.cell), isAddNewRow || options.autoEdit);
+ activePosX = pos.posX;
+ } else {
+ setActiveCellInternal(getCellNode(activeRow, activeCell), (activeRow == getDataLength()) || options.autoEdit);
+ }
+ }
- if (!options.enableCellNavigation) {
- return;
- }
+ function getCellNode(row, cell) {
+ if (rowsCache[row]) {
+ var cells = $(rowsCache[row]).children();
+ var nodeCell;
+ for (var i = 0; i < cells.length; i++) {
+ nodeCell = getCellFromNode(cells[i]);
+ if (nodeCell === cell) {
+ return cells[i];
+ } else if (nodeCell > cell) {
+ return null;
+ }
- scrollRowIntoView(row,false);
- setActiveCellInternal(getCellNode(row,cell),false);
}
+ }
+ return null;
+ }
- function canCellBeActive(row, cell) {
- if (!options.enableCellNavigation || row >= getDataLength() + (options.enableAddRow ? 1 : 0) || row < 0 || cell >= columns.length || cell < 0) {
- return false;
- }
+ function setActiveCell(row, cell) {
+ if (row > getDataLength() || row < 0 || cell >= columns.length || cell < 0) {
+ return;
+ }
- var rowMetadata = data.getItemMetadata && data.getItemMetadata(row);
- if (rowMetadata && typeof rowMetadata.focusable === "boolean") {
- return rowMetadata.focusable;
- }
+ if (!options.enableCellNavigation) {
+ return;
+ }
- var columnMetadata = rowMetadata && rowMetadata.columns;
- if (columnMetadata && columnMetadata[columns[cell].id] && typeof columnMetadata[columns[cell].id].focusable === "boolean") {
- return columnMetadata[columns[cell].id].focusable;
- }
- if (columnMetadata && columnMetadata[cell] && typeof columnMetadata[cell].focusable === "boolean") {
- return columnMetadata[cell].focusable;
- }
+ scrollRowIntoView(row, false);
+ setActiveCellInternal(getCellNode(row, cell), false);
+ }
- if (typeof columns[cell].focusable === "boolean") {
- return columns[cell].focusable;
- }
+ function canCellBeActive(row, cell) {
+ if (!options.enableCellNavigation || row >= getDataLength() + (options.enableAddRow ? 1 : 0) ||
+ row < 0 || cell >= columns.length || cell < 0) {
+ return false;
+ }
+
+ var rowMetadata = data.getItemMetadata && data.getItemMetadata(row);
+ if (rowMetadata && typeof rowMetadata.focusable === "boolean") {
+ return rowMetadata.focusable;
+ }
+
+ var columnMetadata = rowMetadata && rowMetadata.columns;
+ if (columnMetadata && columnMetadata[columns[cell].id] && typeof columnMetadata[columns[cell].id].focusable === "boolean") {
+ return columnMetadata[columns[cell].id].focusable;
+ }
+ if (columnMetadata && columnMetadata[cell] && typeof columnMetadata[cell].focusable === "boolean") {
+ return columnMetadata[cell].focusable;
+ }
+
+ if (typeof columns[cell].focusable === "boolean") {
+ return columns[cell].focusable;
+ }
+
+ return true;
+ }
- return true;
- }
+ function canCellBeSelected(row, cell) {
+ if (row >= getDataLength() || row < 0 || cell >= columns.length || cell < 0) {
+ return false;
+ }
- function canCellBeSelected(row, cell) {
- if (row >= getDataLength() || row < 0 || cell >= columns.length || cell < 0) {
- return false;
- }
+ var rowMetadata = data.getItemMetadata && data.getItemMetadata(row);
+ if (rowMetadata && typeof rowMetadata.selectable === "boolean") {
+ return rowMetadata.selectable;
+ }
- var rowMetadata = data.getItemMetadata && data.getItemMetadata(row);
- if (rowMetadata && typeof rowMetadata.selectable === "boolean") {
- return rowMetadata.selectable;
- }
+ var columnMetadata = rowMetadata && rowMetadata.columns && (rowMetadata.columns[columns[cell].id] || rowMetadata.columns[cell]);
+ if (columnMetadata && typeof columnMetadata.selectable === "boolean") {
+ return columnMetadata.selectable;
+ }
- var columnMetadata = rowMetadata && rowMetadata.columns && (rowMetadata.columns[columns[cell].id] || rowMetadata.columns[cell]);
- if (columnMetadata && typeof columnMetadata.selectable === "boolean") {
- return columnMetadata.selectable;
- }
+ if (typeof columns[cell].selectable === "boolean") {
+ return columns[cell].selectable;
+ }
- if (typeof columns[cell].selectable === "boolean") {
- return columns[cell].selectable;
- }
+ return true;
+ }
- return true;
- }
+ function gotoCell(row, cell, forceEdit) {
+ if (!canCellBeActive(row, cell)) {
+ return;
+ }
- function gotoCell(row, cell, forceEdit) {
- if (!canCellBeActive(row, cell)) {
- return;
- }
+ if (!getEditorLock().commitCurrentEdit()) {
+ return;
+ }
- if (!getEditorLock().commitCurrentEdit()) { return; }
+ scrollRowIntoView(row, false);
- scrollRowIntoView(row,false);
+ var newCell = getCellNode(row, cell);
- var newCell = getCellNode(row, cell);
+ // if selecting the 'add new' row, start editing right away
+ setActiveCellInternal(newCell, forceEdit || (row === getDataLength()) || options.autoEdit);
- // if selecting the 'add new' row, start editing right away
- setActiveCellInternal(newCell, forceEdit || (row === getDataLength()) || options.autoEdit);
+ // if no editor was created, set the focus back on the grid
+ if (!currentEditor) {
+ setFocus();
+ }
+ }
- // if no editor was created, set the focus back on the grid
- if (!currentEditor) {
- setFocus();
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////////////////////
- // IEditor implementation for the editor lock
-
- function commitCurrentEdit() {
- var item = getDataItem(activeRow);
- var column = columns[activeCell];
-
- if (currentEditor) {
- if (currentEditor.isValueChanged()) {
- var validationResults = currentEditor.validate();
-
- if (validationResults.valid) {
- if (activeRow < getDataLength()) {
- var editCommand = {
- row: activeRow,
- cell: activeCell,
- editor: currentEditor,
- serializedValue: currentEditor.serializeValue(),
- prevSerializedValue: serializedEditorValue,
- execute: function() {
- this.editor.applyValue(item,this.serializedValue);
- updateRow(this.row);
- },
- undo: function() {
- this.editor.applyValue(item,this.prevSerializedValue);
- updateRow(this.row);
- }
- };
-
- if (options.editCommandHandler) {
- makeActiveCellNormal();
- options.editCommandHandler(item,column,editCommand);
-
- }
- else {
- editCommand.execute();
- makeActiveCellNormal();
- }
-
- trigger(self.onCellChange, {
- row: activeRow,
- cell: activeCell,
- item: item
- });
- }
- else {
- var newItem = {};
- currentEditor.applyValue(newItem,currentEditor.serializeValue());
- makeActiveCellNormal();
- trigger(self.onAddNewRow, {item:newItem, column:column});
- }
-
- // check whether the lock has been re-acquired by event handlers
- return !getEditorLock().isActive();
- }
- else {
- // TODO: remove and put in onValidationError handlers in examples
- $(activeCellNode).addClass("invalid");
- $(activeCellNode).stop(true,true).effect("highlight", {color:"red"}, 300);
-
- trigger(self.onValidationError, {
- editor: currentEditor,
- cellNode: activeCellNode,
- validationResults: validationResults,
- row: activeRow,
- cell: activeCell,
- column: column
- });
-
- currentEditor.focus();
- return false;
- }
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ // IEditor implementation for the editor lock
+
+ function commitCurrentEdit() {
+ var item = getDataItem(activeRow);
+ var column = columns[activeCell];
+
+ if (currentEditor) {
+ if (currentEditor.isValueChanged()) {
+ var validationResults = currentEditor.validate();
+
+ if (validationResults.valid) {
+ if (activeRow < getDataLength()) {
+ var editCommand = {
+ row:activeRow,
+ cell:activeCell,
+ editor:currentEditor,
+ serializedValue:currentEditor.serializeValue(),
+ prevSerializedValue:serializedEditorValue,
+ execute:function () {
+ this.editor.applyValue(item, this.serializedValue);
+ updateRow(this.row);
+ },
+ undo:function () {
+ this.editor.applyValue(item, this.prevSerializedValue);
+ updateRow(this.row);
}
+ };
+ if (options.editCommandHandler) {
makeActiveCellNormal();
- }
- return true;
- }
+ options.editCommandHandler(item, column, editCommand);
+ } else {
+ editCommand.execute();
+ makeActiveCellNormal();
+ }
- function cancelCurrentEdit() {
- makeActiveCellNormal();
- return true;
- }
+ trigger(self.onCellChange, {
+ row:activeRow,
+ cell:activeCell,
+ item:item
+ });
+ } else {
+ var newItem = {};
+ currentEditor.applyValue(newItem, currentEditor.serializeValue());
+ makeActiveCellNormal();
+ trigger(self.onAddNewRow, {item:newItem, column:column});
+ }
+
+ // check whether the lock has been re-acquired by event handlers
+ return !getEditorLock().isActive();
+ } else {
+ // TODO: remove and put in onValidationError handlers in examples
+ $(activeCellNode).addClass("invalid");
+ $(activeCellNode).stop(true, true).effect("highlight", {color:"red"}, 300);
+
+ trigger(self.onValidationError, {
+ editor:currentEditor,
+ cellNode:activeCellNode,
+ validationResults:validationResults,
+ row:activeRow,
+ cell:activeCell,
+ column:column
+ });
- function rowsToRanges(rows) {
- var ranges = [];
- var lastCell = columns.length - 1;
- for (var i = 0; i < rows.length; i++) {
- ranges.push(new Slick.Range(rows[i], 0, rows[i], lastCell));
- }
- return ranges;
+ currentEditor.focus();
+ return false;
+ }
}
- function getSelectedRows() {
- if (!selectionModel) {
- throw "Selection model is not set";
- }
- return selectedRows;
- }
+ makeActiveCellNormal();
+ }
+ return true;
+ }
- function setSelectedRows(rows) {
- if (!selectionModel) {
- throw "Selection model is not set";
- }
- selectionModel.setSelectedRanges(rowsToRanges(rows));
- }
+ function cancelCurrentEdit() {
+ makeActiveCellNormal();
+ return true;
+ }
+ function rowsToRanges(rows) {
+ var ranges = [];
+ var lastCell = columns.length - 1;
+ for (var i = 0; i < rows.length; i++) {
+ ranges.push(new Slick.Range(rows[i], 0, rows[i], lastCell));
+ }
+ return ranges;
+ }
- //////////////////////////////////////////////////////////////////////////////////////////////
- // Debug
+ function getSelectedRows() {
+ if (!selectionModel) {
+ throw "Selection model is not set";
+ }
+ return selectedRows;
+ }
- this.debug = function() {
- var s = "";
+ function setSelectedRows(rows) {
+ if (!selectionModel) {
+ throw "Selection model is not set";
+ }
+ selectionModel.setSelectedRanges(rowsToRanges(rows));
+ }
- s += ("\n" + "counter_rows_rendered: " + counter_rows_rendered);
- s += ("\n" + "counter_rows_removed: " + counter_rows_removed);
- s += ("\n" + "renderedRows: " + renderedRows);
- s += ("\n" + "numVisibleRows: " + numVisibleRows);
- s += ("\n" + "maxSupportedCssHeight: " + maxSupportedCssHeight);
- s += ("\n" + "n(umber of pages): " + n);
- s += ("\n" + "(current) page: " + page);
- s += ("\n" + "page height (ph): " + ph);
- s += ("\n" + "scrollDir: " + scrollDir);
- alert(s);
- };
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ // Debug
- // a debug helper to be able to access private members
- this.eval = function(expr) {
- return eval(expr);
- };
+ this.debug = function () {
+ var s = "";
- //////////////////////////////////////////////////////////////////////////////////////////////
- // Public API
-
- $.extend(this, {
- "slickGridVersion": "2.0a1",
-
- // Events
- "onScroll": new Slick.Event(),
- "onSort": new Slick.Event(),
- "onHeaderContextMenu": new Slick.Event(),
- "onHeaderClick": new Slick.Event(),
- "onMouseEnter": new Slick.Event(),
- "onMouseLeave": new Slick.Event(),
- "onClick": new Slick.Event(),
- "onDblClick": new Slick.Event(),
- "onContextMenu": new Slick.Event(),
- "onKeyDown": new Slick.Event(),
- "onAddNewRow": new Slick.Event(),
- "onValidationError": new Slick.Event(),
- "onViewportChanged": new Slick.Event(),
- "onColumnsReordered": new Slick.Event(),
- "onColumnsResized": new Slick.Event(),
- "onCellChange": new Slick.Event(),
- "onBeforeEditCell": new Slick.Event(),
- "onBeforeCellEditorDestroy": new Slick.Event(),
- "onBeforeDestroy": new Slick.Event(),
- "onActiveCellChanged": new Slick.Event(),
- "onActiveCellPositionChanged": new Slick.Event(),
- "onDragInit": new Slick.Event(),
- "onDragStart": new Slick.Event(),
- "onDrag": new Slick.Event(),
- "onDragEnd": new Slick.Event(),
- "onSelectedRowsChanged": new Slick.Event(),
-
- // Methods
- "registerPlugin": registerPlugin,
- "unregisterPlugin": unregisterPlugin,
- "getColumns": getColumns,
- "setColumns": setColumns,
- "getColumnIndex": getColumnIndex,
- "updateColumnHeader": updateColumnHeader,
- "setSortColumn": setSortColumn,
- "autosizeColumns": autosizeColumns,
- "getOptions": getOptions,
- "setOptions": setOptions,
- "getData": getData,
- "getDataLength": getDataLength,
- "getDataItem": getDataItem,
- "setData": setData,
- "getSelectionModel": getSelectionModel,
- "setSelectionModel": setSelectionModel,
- "getSelectedRows": getSelectedRows,
- "setSelectedRows": setSelectedRows,
-
- "render": render,
- "invalidate": invalidate,
- "invalidateRow": invalidateRow,
- "invalidateRows": invalidateRows,
- "invalidateAllRows": invalidateAllRows,
- "updateCell": updateCell,
- "updateRow": updateRow,
- "getViewport": getVisibleRange,
- "getRenderedRange": getRenderedRange,
- "resizeCanvas": resizeCanvas,
- "updateRowCount": updateRowCount,
- "scrollRowIntoView": scrollRowIntoView,
- "getCanvasNode": getCanvasNode,
-
- "getCellFromPoint": getCellFromPoint,
- "getCellFromEvent": getCellFromEvent,
- "getActiveCell": getActiveCell,
- "setActiveCell": setActiveCell,
- "getActiveCellNode": getActiveCellNode,
- "getActiveCellPosition": getActiveCellPosition,
- "resetActiveCell": resetActiveCell,
- "editActiveCell": makeActiveCellEditable,
- "getCellEditor": getCellEditor,
- "getCellNode": getCellNode,
- "getCellNodeBox": getCellNodeBox,
- "canCellBeSelected": canCellBeSelected,
- "canCellBeActive": canCellBeActive,
- "navigatePrev": navigatePrev,
- "navigateNext": navigateNext,
- "navigateUp": navigateUp,
- "navigateDown": navigateDown,
- "navigateLeft": navigateLeft,
- "navigateRight": navigateRight,
- "gotoCell": gotoCell,
- "getTopPanel": getTopPanel,
- "showTopPanel": showTopPanel,
- "hideTopPanel": hideTopPanel,
- "showHeaderRowColumns": showHeaderRowColumns,
- "hideHeaderRowColumns": hideHeaderRowColumns,
- "getHeaderRow": getHeaderRow,
- "getHeaderRowColumn": getHeaderRowColumn,
- "getGridPosition": getGridPosition,
- "flashCell": flashCell,
- "addCellCssStyles": addCellCssStyles,
- "setCellCssStyles": setCellCssStyles,
- "removeCellCssStyles": removeCellCssStyles,
-
- "destroy": destroy,
-
- // IEditor implementation
- "getEditorLock": getEditorLock,
- "getEditController": getEditController
- });
+ s += ("\n" + "counter_rows_rendered: " + counter_rows_rendered);
+ s += ("\n" + "counter_rows_removed: " + counter_rows_removed);
+ s += ("\n" + "renderedRows: " + renderedRows);
+ s += ("\n" + "numVisibleRows: " + numVisibleRows);
+ s += ("\n" + "maxSupportedCssHeight: " + maxSupportedCssHeight);
+ s += ("\n" + "n(umber of pages): " + n);
+ s += ("\n" + "(current) page: " + page);
+ s += ("\n" + "page height (ph): " + ph);
+ s += ("\n" + "scrollDir: " + scrollDir);
- init();
- }
+ alert(s);
+ };
+
+ // a debug helper to be able to access private members
+ this.eval = function (expr) {
+ return eval(expr);
+ };
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ // Public API
+
+ $.extend(this, {
+ "slickGridVersion":"2.0a1",
+
+ // Events
+ "onScroll":new Slick.Event(),
+ "onSort":new Slick.Event(),
+ "onHeaderContextMenu":new Slick.Event(),
+ "onHeaderClick":new Slick.Event(),
+ "onMouseEnter":new Slick.Event(),
+ "onMouseLeave":new Slick.Event(),
+ "onClick":new Slick.Event(),
+ "onDblClick":new Slick.Event(),
+ "onContextMenu":new Slick.Event(),
+ "onKeyDown":new Slick.Event(),
+ "onAddNewRow":new Slick.Event(),
+ "onValidationError":new Slick.Event(),
+ "onViewportChanged":new Slick.Event(),
+ "onColumnsReordered":new Slick.Event(),
+ "onColumnsResized":new Slick.Event(),
+ "onCellChange":new Slick.Event(),
+ "onBeforeEditCell":new Slick.Event(),
+ "onBeforeCellEditorDestroy":new Slick.Event(),
+ "onBeforeDestroy":new Slick.Event(),
+ "onActiveCellChanged":new Slick.Event(),
+ "onActiveCellPositionChanged":new Slick.Event(),
+ "onDragInit":new Slick.Event(),
+ "onDragStart":new Slick.Event(),
+ "onDrag":new Slick.Event(),
+ "onDragEnd":new Slick.Event(),
+ "onSelectedRowsChanged":new Slick.Event(),
+
+ // Methods
+ "registerPlugin":registerPlugin,
+ "unregisterPlugin":unregisterPlugin,
+ "getColumns":getColumns,
+ "setColumns":setColumns,
+ "getColumnIndex":getColumnIndex,
+ "updateColumnHeader":updateColumnHeader,
+ "setSortColumn":setSortColumn,
+ "autosizeColumns":autosizeColumns,
+ "getOptions":getOptions,
+ "setOptions":setOptions,
+ "getData":getData,
+ "getDataLength":getDataLength,
+ "getDataItem":getDataItem,
+ "setData":setData,
+ "getSelectionModel":getSelectionModel,
+ "setSelectionModel":setSelectionModel,
+ "getSelectedRows":getSelectedRows,
+ "setSelectedRows":setSelectedRows,
+
+ "render":render,
+ "invalidate":invalidate,
+ "invalidateRow":invalidateRow,
+ "invalidateRows":invalidateRows,
+ "invalidateAllRows":invalidateAllRows,
+ "updateCell":updateCell,
+ "updateRow":updateRow,
+ "getViewport":getVisibleRange,
+ "getRenderedRange":getRenderedRange,
+ "resizeCanvas":resizeCanvas,
+ "updateRowCount":updateRowCount,
+ "scrollRowIntoView":scrollRowIntoView,
+ "getCanvasNode":getCanvasNode,
+
+ "getCellFromPoint":getCellFromPoint,
+ "getCellFromEvent":getCellFromEvent,
+ "getActiveCell":getActiveCell,
+ "setActiveCell":setActiveCell,
+ "getActiveCellNode":getActiveCellNode,
+ "getActiveCellPosition":getActiveCellPosition,
+ "resetActiveCell":resetActiveCell,
+ "editActiveCell":makeActiveCellEditable,
+ "getCellEditor":getCellEditor,
+ "getCellNode":getCellNode,
+ "getCellNodeBox":getCellNodeBox,
+ "canCellBeSelected":canCellBeSelected,
+ "canCellBeActive":canCellBeActive,
+ "navigatePrev":navigatePrev,
+ "navigateNext":navigateNext,
+ "navigateUp":navigateUp,
+ "navigateDown":navigateDown,
+ "navigateLeft":navigateLeft,
+ "navigateRight":navigateRight,
+ "gotoCell":gotoCell,
+ "getTopPanel":getTopPanel,
+ "showTopPanel":showTopPanel,
+ "hideTopPanel":hideTopPanel,
+ "showHeaderRowColumns":showHeaderRowColumns,
+ "hideHeaderRowColumns":hideHeaderRowColumns,
+ "getHeaderRow":getHeaderRow,
+ "getHeaderRowColumn":getHeaderRowColumn,
+ "getGridPosition":getGridPosition,
+ "flashCell":flashCell,
+ "addCellCssStyles":addCellCssStyles,
+ "setCellCssStyles":setCellCssStyles,
+ "removeCellCssStyles":removeCellCssStyles,
+
+ "destroy":destroy,
+
+ // IEditor implementation
+ "getEditorLock":getEditorLock,
+ "getEditController":getEditController
+ });
+
+ init();
+ }
}(jQuery));
diff --git a/slick.groupitemmetadataprovider.js b/slick.groupitemmetadataprovider.js
index 68430eb..2ad0137 100644
--- a/slick.groupitemmetadataprovider.js
+++ b/slick.groupitemmetadataprovider.js
@@ -1,140 +1,139 @@
-(function($) {
- $.extend(true, window, {
- Slick: {
- Data: {
- GroupItemMetadataProvider: GroupItemMetadataProvider
- }
- }
- });
-
-
- /***
- * Provides item metadata for group (Slick.Group) and totals (Slick.Totals) rows produced by the DataView.
- * This metadata overrides the default behavior and formatting of those rows so that they appear and function
- * correctly when processed by the grid.
- *
- * This class also acts as a grid plugin providing event handlers to expand & collapse groups.
- * If "grid.registerPlugin(...)" is not called, expand & collapse will not work.
- *
- * @class GroupItemMetadataProvider
- * @module Data
- * @namespace Slick.Data
- * @constructor
- * @param options
- */
- function GroupItemMetadataProvider(options) {
- var _grid;
- var _defaults = {
- groupCssClass: "slick-group",
- totalsCssClass: "slick-group-totals",
- groupFocusable: true,
- totalsFocusable: false,
- toggleCssClass: "slick-group-toggle",
- toggleExpandedCssClass: "expanded",
- toggleCollapsedCssClass: "collapsed",
- enableExpandCollapse: true
- };
-
- options = $.extend(true, {}, _defaults, options);
-
-
- function defaultGroupCellFormatter(row, cell, value, columnDef, item) {
- if (!options.enableExpandCollapse) {
- return item.title;
- }
+(function ($) {
+ $.extend(true, window, {
+ Slick:{
+ Data:{
+ GroupItemMetadataProvider:GroupItemMetadataProvider
+ }
+ }
+ });
+
+
+ /***
+ * Provides item metadata for group (Slick.Group) and totals (Slick.Totals) rows produced by the DataView.
+ * This metadata overrides the default behavior and formatting of those rows so that they appear and function
+ * correctly when processed by the grid.
+ *
+ * This class also acts as a grid plugin providing event handlers to expand & collapse groups.
+ * If "grid.registerPlugin(...)" is not called, expand & collapse will not work.
+ *
+ * @class GroupItemMetadataProvider
+ * @module Data
+ * @namespace Slick.Data
+ * @constructor
+ * @param options
+ */
+ function GroupItemMetadataProvider(options) {
+ var _grid;
+ var _defaults = {
+ groupCssClass:"slick-group",
+ totalsCssClass:"slick-group-totals",
+ groupFocusable:true,
+ totalsFocusable:false,
+ toggleCssClass:"slick-group-toggle",
+ toggleExpandedCssClass:"expanded",
+ toggleCollapsedCssClass:"collapsed",
+ enableExpandCollapse:true
+ };
+
+ options = $.extend(true, {}, _defaults, options);
+
+
+ function defaultGroupCellFormatter(row, cell, value, columnDef, item) {
+ if (!options.enableExpandCollapse) {
+ return item.title;
+ }
+
+ return "<span class='" + options.toggleCssClass + " " +
+ (item.collapsed ? options.toggleCollapsedCssClass : options.toggleExpandedCssClass) +
+ "'></span>" + item.title;
+ }
- return "<span class='" + options.toggleCssClass + " " +
- (item.collapsed ? options.toggleCollapsedCssClass : options.toggleExpandedCssClass) +
- "'></span>" + item.title;
- }
+ function defaultTotalsCellFormatter(row, cell, value, columnDef, item) {
+ return (columnDef.groupTotalsFormatter && columnDef.groupTotalsFormatter(item, columnDef)) || "";
+ }
- function defaultTotalsCellFormatter(row, cell, value, columnDef, item) {
- return (columnDef.groupTotalsFormatter && columnDef.groupTotalsFormatter(item, columnDef)) || "";
- }
+ function init(grid) {
+ _grid = grid;
+ _grid.onClick.subscribe(handleGridClick);
+ _grid.onKeyDown.subscribe(handleGridKeyDown);
- function init(grid) {
- _grid = grid;
- _grid.onClick.subscribe(handleGridClick);
- _grid.onKeyDown.subscribe(handleGridKeyDown);
+ }
- }
+ function destroy() {
+ if (_grid) {
+ _grid.onClick.unsubscribe(handleGridClick);
+ _grid.onKeyDown.unsubscribe(handleGridKeyDown);
+ }
+ }
- function destroy() {
- if (_grid) {
- _grid.onClick.unsubscribe(handleGridClick);
- _grid.onKeyDown.unsubscribe(handleGridKeyDown);
- }
+ function handleGridClick(e, args) {
+ var item = this.getDataItem(args.row);
+ if (item && item instanceof Slick.Group && $(e.target).hasClass(options.toggleCssClass)) {
+ if (item.collapsed) {
+ this.getData().expandGroup(item.value);
}
-
- function handleGridClick(e, args) {
- var item = this.getDataItem(args.row);
- if (item && item instanceof Slick.Group && $(e.target).hasClass(options.toggleCssClass)) {
- if (item.collapsed) {
- this.getData().expandGroup(item.value);
- }
- else {
- this.getData().collapseGroup(item.value);
- }
-
- e.stopImmediatePropagation();
- e.preventDefault();
- }
+ else {
+ this.getData().collapseGroup(item.value);
}
- // TODO: add -/+ handling
- function handleGridKeyDown(e, args) {
- if (options.enableExpandCollapse && (e.which == $.ui.keyCode.SPACE)) {
- var activeCell = this.getActiveCell();
- if (activeCell) {
- var item = this.getDataItem(activeCell.row);
- if (item && item instanceof Slick.Group) {
- if (item.collapsed) {
- this.getData().expandGroup(item.value);
- }
- else {
- this.getData().collapseGroup(item.value);
- }
-
- e.stopImmediatePropagation();
- e.preventDefault();
- }
- }
+ e.stopImmediatePropagation();
+ e.preventDefault();
+ }
+ }
+
+ // TODO: add -/+ handling
+ function handleGridKeyDown(e, args) {
+ if (options.enableExpandCollapse && (e.which == $.ui.keyCode.SPACE)) {
+ var activeCell = this.getActiveCell();
+ if (activeCell) {
+ var item = this.getDataItem(activeCell.row);
+ if (item && item instanceof Slick.Group) {
+ if (item.collapsed) {
+ this.getData().expandGroup(item.value);
+ }
+ else {
+ this.getData().collapseGroup(item.value);
}
- }
- function getGroupRowMetadata(item) {
- return {
- selectable: false,
- focusable: options.groupFocusable,
- cssClasses: options.groupCssClass,
- columns: {
- 0: {
- colspan: "*",
- formatter: defaultGroupCellFormatter,
- editor: null
- }
- }
- };
+ e.stopImmediatePropagation();
+ e.preventDefault();
+ }
}
+ }
+ }
- function getTotalsRowMetadata(item) {
- return {
- selectable: false,
- focusable: options.totalsFocusable,
- cssClasses: options.totalsCssClass,
- formatter: defaultTotalsCellFormatter,
- editor: null
- };
+ function getGroupRowMetadata(item) {
+ return {
+ selectable:false,
+ focusable:options.groupFocusable,
+ cssClasses:options.groupCssClass,
+ columns:{
+ 0:{
+ colspan:"*",
+ formatter:defaultGroupCellFormatter,
+ editor:null
+ }
}
+ };
+ }
-
-
- return {
- "init": init,
- "destroy": destroy,
- "getGroupRowMetadata": getGroupRowMetadata,
- "getTotalsRowMetadata": getTotalsRowMetadata
- };
+ function getTotalsRowMetadata(item) {
+ return {
+ selectable:false,
+ focusable:options.totalsFocusable,
+ cssClasses:options.totalsCssClass,
+ formatter:defaultTotalsCellFormatter,
+ editor:null
+ };
}
+
+
+ return {
+ "init":init,
+ "destroy":destroy,
+ "getGroupRowMetadata":getGroupRowMetadata,
+ "getTotalsRowMetadata":getTotalsRowMetadata
+ };
+ }
})(jQuery); \ No newline at end of file
diff --git a/slick.remotemodel.js b/slick.remotemodel.js
index dc41b64..aba7688 100644
--- a/slick.remotemodel.js
+++ b/slick.remotemodel.js
@@ -1,161 +1,164 @@
-(function($) {
- /***
- * A sample AJAX data store implementation.
- * Right now, it's hooked up to load all Apple-related Digg stories, but can
- * easily be extended to support and JSONP-compatible backend that accepts paging parameters.
- */
- function RemoteModel() {
- // private
- var PAGESIZE = 50;
- var data = {length:0};
- var searchstr = "apple";
- var sortcol = null;
- var sortdir = 1;
- var h_request = null;
- var req = null; // ajax request
-
- // events
- var onDataLoading = new Slick.Event();
- var onDataLoaded = new Slick.Event();
-
-
- function init() {
- }
-
+(function ($) {
+ /***
+ * A sample AJAX data store implementation.
+ * Right now, it's hooked up to load all Apple-related Digg stories, but can
+ * easily be extended to support and JSONP-compatible backend that accepts paging parameters.
+ */
+ function RemoteModel() {
+ // private
+ var PAGESIZE = 50;
+ var data = {length:0};
+ var searchstr = "apple";
+ var sortcol = null;
+ var sortdir = 1;
+ var h_request = null;
+ var req = null; // ajax request
+
+ // events
+ var onDataLoading = new Slick.Event();
+ var onDataLoaded = new Slick.Event();
+
+
+ function init() {
+ }
+
+
+ function isDataLoaded(from, to) {
+ for (var i = from; i <= to; i++) {
+ if (data[i] == undefined || data[i] == null) {
+ return false;
+ }
+ }
+
+ return true;
+ }
- function isDataLoaded(from,to) {
- for (var i=from; i<=to; i++) {
- if (data[i] == undefined || data[i] == null)
- return false;
- }
- return true;
- }
+ function clear() {
+ for (var key in data) {
+ delete data[key];
+ }
+ data.length = 0;
+ }
+
+ function ensureData(from, to) {
+ if (req) {
+ req.abort();
+ for (var i = req.fromPage; i <= req.toPage; i++)
+ data[i * PAGESIZE] = undefined;
+ }
- function clear() {
- for (var key in data) {
- delete data[key];
- }
- data.length = 0;
- }
+ if (from < 0) {
+ from = 0;
+ }
+ var fromPage = Math.floor(from / PAGESIZE);
+ var toPage = Math.floor(to / PAGESIZE);
+
+ while (data[fromPage * PAGESIZE] !== undefined && fromPage < toPage)
+ fromPage++;
+
+ while (data[toPage * PAGESIZE] !== undefined && fromPage < toPage)
+ toPage--;
+
+ if (fromPage > toPage || ((fromPage == toPage) && data[fromPage * PAGESIZE] !== undefined)) {
+ // TODO: look-ahead
+ return;
+ }
+
+ var url = "http://services.digg.com/search/stories?query=" + searchstr + "&offset=" + (fromPage * PAGESIZE) + "&count=" + (((toPage - fromPage) * PAGESIZE) + PAGESIZE) + "&appkey=http://slickgrid.googlecode.com&type=javascript";
+
+ switch (sortcol) {
+ case "diggs":
+ url += ("&sort=" + ((sortdir > 0) ? "digg_count-asc" : "digg_count-desc"));
+ break;
+ }
+
+ if (h_request != null) {
+ clearTimeout(h_request);
+ }
+
+ h_request = setTimeout(function () {
+ for (var i = fromPage; i <= toPage; i++)
+ data[i * PAGESIZE] = null; // null indicates a 'requested but not available yet'
+
+ onDataLoading.notify({from:from, to:to});
+
+ req = $.jsonp({
+ url:url,
+ callbackParameter:"callback",
+ cache:true, // Digg doesn't accept the autogenerated cachebuster param
+ success:onSuccess,
+ error:function () {
+ onError(fromPage, toPage)
+ }
+ });
+ req.fromPage = fromPage;
+ req.toPage = toPage;
+ }, 50);
+ }
+
+
+ function onError(fromPage, toPage) {
+ alert("error loading pages " + fromPage + " to " + toPage);
+ }
- function ensureData(from,to) {
- if (req) {
- req.abort();
- for (var i=req.fromPage; i<=req.toPage; i++)
- data[i*PAGESIZE] = undefined;
- }
+ function onSuccess(resp) {
+ var from = this.fromPage * PAGESIZE, to = from + resp.count;
+ data.length = parseInt(resp.total);
- if (from < 0)
- from = 0;
+ for (var i = 0; i < resp.stories.length; i++) {
+ data[from + i] = resp.stories[i];
+ data[from + i].index = from + i;
+ }
- var fromPage = Math.floor(from / PAGESIZE);
- var toPage = Math.floor(to / PAGESIZE);
-
- while (data[fromPage * PAGESIZE] !== undefined && fromPage < toPage)
- fromPage++;
+ req = null;
- while (data[toPage * PAGESIZE] !== undefined && fromPage < toPage)
- toPage--;
-
- if (fromPage > toPage || ((fromPage == toPage) && data[fromPage*PAGESIZE] !== undefined)) {
- // TODO: look-ahead
- return;
- }
-
- var url = "http://services.digg.com/search/stories?query=" + searchstr + "&offset=" + (fromPage * PAGESIZE) + "&count=" + (((toPage - fromPage) * PAGESIZE) + PAGESIZE) + "&appkey=http://slickgrid.googlecode.com&type=javascript";
-
- switch (sortcol) {
- case "diggs":
- url += ("&sort=" + ((sortdir>0)?"digg_count-asc":"digg_count-desc"));
- break;
- }
-
- if (h_request != null)
- clearTimeout(h_request);
-
- h_request = setTimeout(function() {
- for (var i=fromPage; i<=toPage; i++)
- data[i*PAGESIZE] = null; // null indicates a 'requested but not available yet'
-
- onDataLoading.notify({from:from, to:to});
-
- req = $.jsonp({
- url: url,
- callbackParameter: "callback",
- cache: true, // Digg doesn't accept the autogenerated cachebuster param
- success: onSuccess,
- error: function(){
- onError(fromPage, toPage)
- }
- });
- req.fromPage = fromPage;
- req.toPage = toPage;
- }, 50);
- }
-
-
- function onError(fromPage,toPage) {
- alert("error loading pages " + fromPage + " to " + toPage);
- }
+ onDataLoaded.notify({from:from, to:to});
+ }
- function onSuccess(resp) {
- var from = this.fromPage*PAGESIZE, to = from + resp.count;
- data.length = parseInt(resp.total);
- for (var i = 0; i < resp.stories.length; i++) {
- data[from + i] = resp.stories[i];
- data[from + i].index = from + i;
- }
+ function reloadData(from, to) {
+ for (var i = from; i <= to; i++)
+ delete data[i];
- req = null;
+ ensureData(from, to);
+ }
- onDataLoaded.notify({from:from, to:to});
- }
+ function setSort(column, dir) {
+ sortcol = column;
+ sortdir = dir;
+ clear();
+ }
- function reloadData(from,to) {
- for (var i=from; i<=to; i++)
- delete data[i];
+ function setSearch(str) {
+ searchstr = str;
+ clear();
+ }
- ensureData(from,to);
- }
+ init();
- function setSort(column,dir) {
- sortcol = column;
- sortdir = dir;
- clear();
- }
+ return {
+ // properties
+ "data":data,
- function setSearch(str) {
- searchstr = str;
- clear();
- }
+ // methods
+ "clear":clear,
+ "isDataLoaded":isDataLoaded,
+ "ensureData":ensureData,
+ "reloadData":reloadData,
+ "setSort":setSort,
+ "setSearch":setSearch,
+ // events
+ "onDataLoading":onDataLoading,
+ "onDataLoaded":onDataLoaded
+ };
+ }
- init();
-
- return {
- // properties
- "data": data,
-
- // methods
- "clear": clear,
- "isDataLoaded": isDataLoaded,
- "ensureData": ensureData,
- "reloadData": reloadData,
- "setSort": setSort,
- "setSearch": setSearch,
-
- // events
- "onDataLoading": onDataLoading,
- "onDataLoaded": onDataLoaded
- };
- }
-
- // Slick.Data.RemoteModel
- $.extend(true, window, { Slick: { Data: { RemoteModel: RemoteModel }}});
+ // Slick.Data.RemoteModel
+ $.extend(true, window, { Slick:{ Data:{ RemoteModel:RemoteModel }}});
})(jQuery); \ No newline at end of file