slickgrid 2.3.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.md +30 -0
- data/lib/slickgrid.rb +6 -0
- data/lib/slickgrid/version.rb +3 -0
- data/slickgrid.gemspec +20 -0
- data/vendor/assets/images/slickgrid/CheckboxN.png +0 -0
- data/vendor/assets/images/slickgrid/CheckboxY.png +0 -0
- data/vendor/assets/images/slickgrid/GrpCheckboxN.png +0 -0
- data/vendor/assets/images/slickgrid/GrpCheckboxY.png +0 -0
- data/vendor/assets/images/slickgrid/actions.gif +0 -0
- data/vendor/assets/images/slickgrid/ajax-loader-small.gif +0 -0
- data/vendor/assets/images/slickgrid/arrow-right.gif +0 -0
- data/vendor/assets/images/slickgrid/arrow_redo.png +0 -0
- data/vendor/assets/images/slickgrid/arrow_right_peppermint.png +0 -0
- data/vendor/assets/images/slickgrid/arrow_right_spearmint.png +0 -0
- data/vendor/assets/images/slickgrid/arrow_undo.png +0 -0
- data/vendor/assets/images/slickgrid/bullet_blue.png +0 -0
- data/vendor/assets/images/slickgrid/bullet_star.png +0 -0
- data/vendor/assets/images/slickgrid/bullet_toggle_minus.png +0 -0
- data/vendor/assets/images/slickgrid/bullet_toggle_plus.png +0 -0
- data/vendor/assets/images/slickgrid/calendar.gif +0 -0
- data/vendor/assets/images/slickgrid/collapse.gif +0 -0
- data/vendor/assets/images/slickgrid/comment_yellow.gif +0 -0
- data/vendor/assets/images/slickgrid/delete.png +0 -0
- data/vendor/assets/images/slickgrid/down.gif +0 -0
- data/vendor/assets/images/slickgrid/drag-handle.png +0 -0
- data/vendor/assets/images/slickgrid/editor-helper-bg.gif +0 -0
- data/vendor/assets/images/slickgrid/expand.gif +0 -0
- data/vendor/assets/images/slickgrid/header-bg.gif +0 -0
- data/vendor/assets/images/slickgrid/header-columns-bg.gif +0 -0
- data/vendor/assets/images/slickgrid/header-columns-over-bg.gif +0 -0
- data/vendor/assets/images/slickgrid/help.png +0 -0
- data/vendor/assets/images/slickgrid/info.gif +0 -0
- data/vendor/assets/images/slickgrid/listview.gif +0 -0
- data/vendor/assets/images/slickgrid/pencil.gif +0 -0
- data/vendor/assets/images/slickgrid/row-over-bg.gif +0 -0
- data/vendor/assets/images/slickgrid/sort-asc.gif +0 -0
- data/vendor/assets/images/slickgrid/sort-asc.png +0 -0
- data/vendor/assets/images/slickgrid/sort-desc.gif +0 -0
- data/vendor/assets/images/slickgrid/sort-desc.png +0 -0
- data/vendor/assets/images/slickgrid/stripes.png +0 -0
- data/vendor/assets/images/slickgrid/tag_red.png +0 -0
- data/vendor/assets/images/slickgrid/tick.png +0 -0
- data/vendor/assets/images/slickgrid/user_identity.gif +0 -0
- data/vendor/assets/images/slickgrid/user_identity_plus.gif +0 -0
- data/vendor/assets/javascripts/slickgrid.js +5 -0
- data/vendor/assets/javascripts/slickgrid/controls/columnpicker.js +221 -0
- data/vendor/assets/javascripts/slickgrid/controls/gridmenu.js +429 -0
- data/vendor/assets/javascripts/slickgrid/controls/pager.js +154 -0
- data/vendor/assets/javascripts/slickgrid/core.js +493 -0
- data/vendor/assets/javascripts/slickgrid/dataview.js +1220 -0
- data/vendor/assets/javascripts/slickgrid/editors.js +640 -0
- data/vendor/assets/javascripts/slickgrid/formatters.js +65 -0
- data/vendor/assets/javascripts/slickgrid/grid.js +3990 -0
- data/vendor/assets/javascripts/slickgrid/groupitemmetadataprovider.js +172 -0
- data/vendor/assets/javascripts/slickgrid/plugins/autotooltips.js +83 -0
- data/vendor/assets/javascripts/slickgrid/plugins/cellcopymanager.js +88 -0
- data/vendor/assets/javascripts/slickgrid/plugins/cellexternalcopymanager.js +452 -0
- data/vendor/assets/javascripts/slickgrid/plugins/cellrangedecorator.js +72 -0
- data/vendor/assets/javascripts/slickgrid/plugins/cellrangeselector.js +123 -0
- data/vendor/assets/javascripts/slickgrid/plugins/cellselectionmodel.js +168 -0
- data/vendor/assets/javascripts/slickgrid/plugins/checkboxselectcolumn.js +202 -0
- data/vendor/assets/javascripts/slickgrid/plugins/draggablegrouping.js +207 -0
- data/vendor/assets/javascripts/slickgrid/plugins/headerbuttons.js +177 -0
- data/vendor/assets/javascripts/slickgrid/plugins/headermenu.js +296 -0
- data/vendor/assets/javascripts/slickgrid/plugins/rowdetailview.js +455 -0
- data/vendor/assets/javascripts/slickgrid/plugins/rowmovemanager.js +138 -0
- data/vendor/assets/javascripts/slickgrid/plugins/rowselectionmodel.js +191 -0
- data/vendor/assets/javascripts/slickgrid/remotemodel.js +169 -0
- data/vendor/assets/stylesheets/slickgrid.scss +1 -0
- data/vendor/assets/stylesheets/slickgrid/controls/columnpicker.css +46 -0
- data/vendor/assets/stylesheets/slickgrid/controls/gridmenu.css +113 -0
- data/vendor/assets/stylesheets/slickgrid/controls/pager.css +41 -0
- data/vendor/assets/stylesheets/slickgrid/default-theme.css +132 -0
- data/vendor/assets/stylesheets/slickgrid/grid.css +189 -0
- data/vendor/assets/stylesheets/slickgrid/plugins/headerbuttons.css +39 -0
- data/vendor/assets/stylesheets/slickgrid/plugins/headermenu.css +59 -0
- data/vendor/assets/stylesheets/slickgrid/plugins/rowdetailview.css +39 -0
- metadata +165 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/***
|
|
2
|
+
* Contains basic SlickGrid formatters.
|
|
3
|
+
*
|
|
4
|
+
* NOTE: These are merely examples. You will most likely need to implement something more
|
|
5
|
+
* robust/extensible/localizable/etc. for your use!
|
|
6
|
+
*
|
|
7
|
+
* @module Formatters
|
|
8
|
+
* @namespace Slick
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
(function ($) {
|
|
12
|
+
// register namespace
|
|
13
|
+
$.extend(true, window, {
|
|
14
|
+
"Slick": {
|
|
15
|
+
"Formatters": {
|
|
16
|
+
"PercentComplete": PercentCompleteFormatter,
|
|
17
|
+
"PercentCompleteBar": PercentCompleteBarFormatter,
|
|
18
|
+
"YesNo": YesNoFormatter,
|
|
19
|
+
"Checkmark": CheckmarkFormatter,
|
|
20
|
+
"Checkbox": CheckboxFormatter
|
|
21
|
+
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
function PercentCompleteFormatter(row, cell, value, columnDef, dataContext) {
|
|
27
|
+
if (value == null || value === "") {
|
|
28
|
+
return "-";
|
|
29
|
+
} else if (value < 50) {
|
|
30
|
+
return "<span style='color:red;font-weight:bold;'>" + value + "%</span>";
|
|
31
|
+
} else {
|
|
32
|
+
return "<span style='color:green'>" + value + "%</span>";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function PercentCompleteBarFormatter(row, cell, value, columnDef, dataContext) {
|
|
37
|
+
if (value == null || value === "") {
|
|
38
|
+
return "";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
var color;
|
|
42
|
+
|
|
43
|
+
if (value < 30) {
|
|
44
|
+
color = "red";
|
|
45
|
+
} else if (value < 70) {
|
|
46
|
+
color = "silver";
|
|
47
|
+
} else {
|
|
48
|
+
color = "green";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return "<span class='percent-complete-bar' style='background:" + color + ";width:" + value + "%'></span>";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function YesNoFormatter(row, cell, value, columnDef, dataContext) {
|
|
55
|
+
return value ? "Yes" : "No";
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function CheckboxFormatter(row, cell, value, columnDef, dataContext) {
|
|
59
|
+
return '<img class="slick-edit-preclick" src="../slickgrid/' + (value ? "CheckboxY" : "CheckboxN") + '.png">';
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function CheckmarkFormatter(row, cell, value, columnDef, dataContext) {
|
|
63
|
+
return value ? "<img src='../slickgrid/tick.png'>" : "";
|
|
64
|
+
}
|
|
65
|
+
})(jQuery);
|
|
@@ -0,0 +1,3990 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* (c) 2009-2016 Michael Leibman
|
|
4
|
+
* michael{dot}leibman{at}gmail{dot}com
|
|
5
|
+
* http://github.com/mleibman/slickgrid
|
|
6
|
+
*
|
|
7
|
+
* Distributed under MIT license.
|
|
8
|
+
* All rights reserved.
|
|
9
|
+
*
|
|
10
|
+
* SlickGrid v2.3
|
|
11
|
+
*
|
|
12
|
+
* NOTES:
|
|
13
|
+
* Cell/row DOM manipulations are done directly bypassing jQuery's DOM manipulation methods.
|
|
14
|
+
* This increases the speed dramatically, but can only be done safely because there are no event handlers
|
|
15
|
+
* or data associated with any cell/row DOM nodes. Cell editors must make sure they implement .destroy()
|
|
16
|
+
* and do proper cleanup.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
// make sure required JavaScript modules are loaded
|
|
20
|
+
if (typeof jQuery === "undefined") {
|
|
21
|
+
throw new Error("SlickGrid requires jquery module to be loaded");
|
|
22
|
+
}
|
|
23
|
+
if (!jQuery.fn.drag) {
|
|
24
|
+
throw new Error("SlickGrid requires jquery.event.drag module to be loaded");
|
|
25
|
+
}
|
|
26
|
+
if (typeof Slick === "undefined") {
|
|
27
|
+
throw new Error("slick.core.js not loaded");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
(function ($) {
|
|
32
|
+
// Slick.Grid
|
|
33
|
+
$.extend(true, window, {
|
|
34
|
+
Slick: {
|
|
35
|
+
Grid: SlickGrid
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// shared across all grids on the page
|
|
40
|
+
var scrollbarDimensions;
|
|
41
|
+
var maxSupportedCssHeight; // browser's breaking point
|
|
42
|
+
|
|
43
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
44
|
+
// SlickGrid class implementation (available as Slick.Grid)
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Creates a new instance of the grid.
|
|
48
|
+
* @class SlickGrid
|
|
49
|
+
* @constructor
|
|
50
|
+
* @param {Node} container Container node to create the grid in.
|
|
51
|
+
* @param {Array,Object} data An array of objects for databinding.
|
|
52
|
+
* @param {Array} columns An array of column definitions.
|
|
53
|
+
* @param {Object} options Grid options.
|
|
54
|
+
**/
|
|
55
|
+
function SlickGrid(container, data, columns, options) {
|
|
56
|
+
// settings
|
|
57
|
+
var defaults = {
|
|
58
|
+
explicitInitialization: false,
|
|
59
|
+
rowHeight: 25,
|
|
60
|
+
defaultColumnWidth: 80,
|
|
61
|
+
enableAddRow: false,
|
|
62
|
+
leaveSpaceForNewRows: false,
|
|
63
|
+
editable: false,
|
|
64
|
+
autoEdit: true,
|
|
65
|
+
enableCellNavigation: true,
|
|
66
|
+
enableColumnReorder: true,
|
|
67
|
+
asyncEditorLoading: false,
|
|
68
|
+
asyncEditorLoadDelay: 100,
|
|
69
|
+
forceFitColumns: false,
|
|
70
|
+
enableAsyncPostRender: false,
|
|
71
|
+
asyncPostRenderDelay: 50,
|
|
72
|
+
enableAsyncPostRenderCleanup: false,
|
|
73
|
+
asyncPostRenderCleanupDelay: 40,
|
|
74
|
+
autoHeight: false,
|
|
75
|
+
editorLock: Slick.GlobalEditorLock,
|
|
76
|
+
showHeaderRow: false,
|
|
77
|
+
headerRowHeight: 25,
|
|
78
|
+
createFooterRow: false,
|
|
79
|
+
showFooterRow: false,
|
|
80
|
+
footerRowHeight: 25,
|
|
81
|
+
createPreHeaderPanel: false,
|
|
82
|
+
showPreHeaderPanel: false,
|
|
83
|
+
preHeaderPanelHeight: 25,
|
|
84
|
+
showTopPanel: false,
|
|
85
|
+
topPanelHeight: 25,
|
|
86
|
+
formatterFactory: null,
|
|
87
|
+
editorFactory: null,
|
|
88
|
+
cellFlashingCssClass: "flashing",
|
|
89
|
+
selectedCellCssClass: "selected",
|
|
90
|
+
multiSelect: true,
|
|
91
|
+
enableTextSelectionOnCells: false,
|
|
92
|
+
dataItemColumnValueExtractor: null,
|
|
93
|
+
fullWidthRows: false,
|
|
94
|
+
multiColumnSort: false,
|
|
95
|
+
numberedMultiColumnSort: false,
|
|
96
|
+
tristateMultiColumnSort: false,
|
|
97
|
+
defaultFormatter: defaultFormatter,
|
|
98
|
+
forceSyncScrolling: false,
|
|
99
|
+
addNewRowCssClass: "new-row",
|
|
100
|
+
preserveCopiedSelectionOnPaste: false,
|
|
101
|
+
showCellSelection: true,
|
|
102
|
+
viewportClass: null,
|
|
103
|
+
minRowBuffer: 3,
|
|
104
|
+
emulatePagingWhenScrolling: true
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
var columnDefaults = {
|
|
108
|
+
name: "",
|
|
109
|
+
resizable: true,
|
|
110
|
+
sortable: false,
|
|
111
|
+
minWidth: 30,
|
|
112
|
+
rerenderOnResize: false,
|
|
113
|
+
headerCssClass: null,
|
|
114
|
+
defaultSortAsc: true,
|
|
115
|
+
focusable: true,
|
|
116
|
+
selectable: true
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// scroller
|
|
120
|
+
var th; // virtual height
|
|
121
|
+
var h; // real scrollable height
|
|
122
|
+
var ph; // page height
|
|
123
|
+
var n; // number of pages
|
|
124
|
+
var cj; // "jumpiness" coefficient
|
|
125
|
+
|
|
126
|
+
var page = 0; // current page
|
|
127
|
+
var offset = 0; // current page offset
|
|
128
|
+
var vScrollDir = 1;
|
|
129
|
+
|
|
130
|
+
// private
|
|
131
|
+
var initialized = false;
|
|
132
|
+
var $container;
|
|
133
|
+
var uid = "slickgrid_" + Math.round(1000000 * Math.random());
|
|
134
|
+
var self = this;
|
|
135
|
+
var $focusSink, $focusSink2;
|
|
136
|
+
var $headerScroller;
|
|
137
|
+
var $headers;
|
|
138
|
+
var $headerRow, $headerRowScroller, $headerRowSpacer;
|
|
139
|
+
var $footerRow, $footerRowScroller, $footerRowSpacer;
|
|
140
|
+
var $preHeaderPanel, $preHeaderPanelScroller, $preHeaderPanelSpacer;
|
|
141
|
+
var $topPanelScroller;
|
|
142
|
+
var $topPanel;
|
|
143
|
+
var $viewport;
|
|
144
|
+
var $canvas;
|
|
145
|
+
var $style;
|
|
146
|
+
var $boundAncestors;
|
|
147
|
+
var stylesheet, columnCssRulesL, columnCssRulesR;
|
|
148
|
+
var viewportH, viewportW;
|
|
149
|
+
var canvasWidth;
|
|
150
|
+
var viewportHasHScroll, viewportHasVScroll;
|
|
151
|
+
var headerColumnWidthDiff = 0, headerColumnHeightDiff = 0, // border+padding
|
|
152
|
+
cellWidthDiff = 0, cellHeightDiff = 0, jQueryNewWidthBehaviour = false;
|
|
153
|
+
var absoluteColumnMinWidth;
|
|
154
|
+
var sortIndicatorCssClass = "slick-sort-indicator";
|
|
155
|
+
|
|
156
|
+
var tabbingDirection = 1;
|
|
157
|
+
var activePosX;
|
|
158
|
+
var activeRow, activeCell;
|
|
159
|
+
var activeCellNode = null;
|
|
160
|
+
var currentEditor = null;
|
|
161
|
+
var serializedEditorValue;
|
|
162
|
+
var editController;
|
|
163
|
+
|
|
164
|
+
var rowsCache = {};
|
|
165
|
+
var renderedRows = 0;
|
|
166
|
+
var numVisibleRows;
|
|
167
|
+
var prevScrollTop = 0;
|
|
168
|
+
var scrollTop = 0;
|
|
169
|
+
var lastRenderedScrollTop = 0;
|
|
170
|
+
var lastRenderedScrollLeft = 0;
|
|
171
|
+
var prevScrollLeft = 0;
|
|
172
|
+
var scrollLeft = 0;
|
|
173
|
+
|
|
174
|
+
var selectionModel;
|
|
175
|
+
var selectedRows = [];
|
|
176
|
+
|
|
177
|
+
var plugins = [];
|
|
178
|
+
var cellCssClasses = {};
|
|
179
|
+
|
|
180
|
+
var columnsById = {};
|
|
181
|
+
var sortColumns = [];
|
|
182
|
+
var columnPosLeft = [];
|
|
183
|
+
var columnPosRight = [];
|
|
184
|
+
|
|
185
|
+
var pagingActive = false;
|
|
186
|
+
var pagingIsLastPage = false;
|
|
187
|
+
|
|
188
|
+
// async call handles
|
|
189
|
+
var h_editorLoader = null;
|
|
190
|
+
var h_render = null;
|
|
191
|
+
var h_postrender = null;
|
|
192
|
+
var h_postrenderCleanup = null;
|
|
193
|
+
var postProcessedRows = {};
|
|
194
|
+
var postProcessToRow = null;
|
|
195
|
+
var postProcessFromRow = null;
|
|
196
|
+
var postProcessedCleanupQueue = [];
|
|
197
|
+
var postProcessgroupId = 0;
|
|
198
|
+
|
|
199
|
+
// perf counters
|
|
200
|
+
var counter_rows_rendered = 0;
|
|
201
|
+
var counter_rows_removed = 0;
|
|
202
|
+
|
|
203
|
+
// These two variables work around a bug with inertial scrolling in Webkit/Blink on Mac.
|
|
204
|
+
// See http://crbug.com/312427.
|
|
205
|
+
var rowNodeFromLastMouseWheelEvent; // this node must not be deleted while inertial scrolling
|
|
206
|
+
var zombieRowNodeFromLastMouseWheelEvent; // node that was hidden instead of getting deleted
|
|
207
|
+
var zombieRowCacheFromLastMouseWheelEvent; // row cache for above node
|
|
208
|
+
var zombieRowPostProcessedFromLastMouseWheelEvent; // post processing references for above node
|
|
209
|
+
|
|
210
|
+
// store css attributes if display:none is active in container or parent
|
|
211
|
+
var cssShow = { position: 'absolute', visibility: 'hidden', display: 'block' };
|
|
212
|
+
var $hiddenParents;
|
|
213
|
+
var oldProps = [];
|
|
214
|
+
var columnResizeDragging = false;
|
|
215
|
+
|
|
216
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
217
|
+
// Initialization
|
|
218
|
+
|
|
219
|
+
function init() {
|
|
220
|
+
if (container instanceof jQuery) {
|
|
221
|
+
$container = container;
|
|
222
|
+
} else {
|
|
223
|
+
$container = $(container);
|
|
224
|
+
}
|
|
225
|
+
if ($container.length < 1) {
|
|
226
|
+
throw new Error("SlickGrid requires a valid container, " + container + " does not exist in the DOM.");
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
cacheCssForHiddenInit();
|
|
230
|
+
|
|
231
|
+
// calculate these only once and share between grid instances
|
|
232
|
+
maxSupportedCssHeight = maxSupportedCssHeight || getMaxSupportedCssHeight();
|
|
233
|
+
|
|
234
|
+
options = $.extend({}, defaults, options);
|
|
235
|
+
validateAndEnforceOptions();
|
|
236
|
+
columnDefaults.width = options.defaultColumnWidth;
|
|
237
|
+
|
|
238
|
+
columnsById = {};
|
|
239
|
+
for (var i = 0; i < columns.length; i++) {
|
|
240
|
+
var m = columns[i] = $.extend({}, columnDefaults, columns[i]);
|
|
241
|
+
columnsById[m.id] = i;
|
|
242
|
+
if (m.minWidth && m.width < m.minWidth) {
|
|
243
|
+
m.width = m.minWidth;
|
|
244
|
+
}
|
|
245
|
+
if (m.maxWidth && m.width > m.maxWidth) {
|
|
246
|
+
m.width = m.maxWidth;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// validate loaded JavaScript modules against requested options
|
|
251
|
+
if (options.enableColumnReorder && !$.fn.sortable) {
|
|
252
|
+
throw new Error("SlickGrid's 'enableColumnReorder = true' option requires jquery-ui.sortable module to be loaded");
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
editController = {
|
|
256
|
+
"commitCurrentEdit": commitCurrentEdit,
|
|
257
|
+
"cancelCurrentEdit": cancelCurrentEdit
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
$container
|
|
261
|
+
.empty()
|
|
262
|
+
.css("overflow", "hidden")
|
|
263
|
+
.css("outline", 0)
|
|
264
|
+
.addClass(uid)
|
|
265
|
+
.addClass("ui-widget");
|
|
266
|
+
|
|
267
|
+
// set up a positioning container if needed
|
|
268
|
+
if (!/relative|absolute|fixed/.test($container.css("position"))) {
|
|
269
|
+
$container.css("position", "relative");
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
$focusSink = $("<div tabIndex='0' hideFocus style='position:fixed;width:0;height:0;top:0;left:0;outline:0;'></div>").appendTo($container);
|
|
273
|
+
|
|
274
|
+
if (options.createPreHeaderPanel) {
|
|
275
|
+
$preHeaderPanelScroller = $("<div class='slick-preheader-panel ui-state-default' style='overflow:hidden;position:relative;' />").appendTo($container);
|
|
276
|
+
$preHeaderPanel = $("<div />").appendTo($preHeaderPanelScroller);
|
|
277
|
+
$preHeaderPanelSpacer = $("<div style='display:block;height:1px;position:absolute;top:0;left:0;'></div>")
|
|
278
|
+
.appendTo($preHeaderPanelScroller);
|
|
279
|
+
|
|
280
|
+
if (!options.showPreHeaderPanel) {
|
|
281
|
+
$preHeaderPanelScroller.hide();
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
$headerScroller = $("<div class='slick-header ui-state-default' />").appendTo($container);
|
|
286
|
+
$headers = $("<div class='slick-header-columns' style='left:-1000px' />").appendTo($headerScroller);
|
|
287
|
+
|
|
288
|
+
$headerRowScroller = $("<div class='slick-headerrow ui-state-default' />").appendTo($container);
|
|
289
|
+
$headerRow = $("<div class='slick-headerrow-columns' />").appendTo($headerRowScroller);
|
|
290
|
+
$headerRowSpacer = $("<div style='display:block;height:1px;position:absolute;top:0;left:0;'></div>")
|
|
291
|
+
.appendTo($headerRowScroller);
|
|
292
|
+
|
|
293
|
+
$topPanelScroller = $("<div class='slick-top-panel-scroller ui-state-default' />").appendTo($container);
|
|
294
|
+
$topPanel = $("<div class='slick-top-panel' style='width:10000px' />").appendTo($topPanelScroller);
|
|
295
|
+
|
|
296
|
+
if (!options.showTopPanel) {
|
|
297
|
+
$topPanelScroller.hide();
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (!options.showHeaderRow) {
|
|
301
|
+
$headerRowScroller.hide();
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
$viewport = $("<div class='slick-viewport' style='width:100%;overflow:auto;outline:0;position:relative;;'>").appendTo($container);
|
|
305
|
+
$viewport.css("overflow-y", options.autoHeight ? "hidden" : "auto");
|
|
306
|
+
if (options.viewportClass) $viewport.toggleClass(options.viewportClass, true);
|
|
307
|
+
|
|
308
|
+
$canvas = $("<div class='grid-canvas' />").appendTo($viewport);
|
|
309
|
+
|
|
310
|
+
scrollbarDimensions = scrollbarDimensions || measureScrollbar();
|
|
311
|
+
|
|
312
|
+
if ($preHeaderPanelSpacer) $preHeaderPanelSpacer.css("width", getCanvasWidth() + scrollbarDimensions.width + "px");
|
|
313
|
+
$headers.width(getHeadersWidth());
|
|
314
|
+
$headerRowSpacer.css("width", getCanvasWidth() + scrollbarDimensions.width + "px");
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
if (options.createFooterRow) {
|
|
319
|
+
$footerRowScroller = $("<div class='slick-footerrow ui-state-default' />").appendTo($container);
|
|
320
|
+
$footerRow = $("<div class='slick-footerrow-columns' />").appendTo($footerRowScroller);
|
|
321
|
+
$footerRowSpacer = $("<div style='display:block;height:1px;position:absolute;top:0;left:0;'></div>")
|
|
322
|
+
.css("width", getCanvasWidth() + scrollbarDimensions.width + "px")
|
|
323
|
+
.appendTo($footerRowScroller);
|
|
324
|
+
|
|
325
|
+
if (!options.showFooterRow) {
|
|
326
|
+
$footerRowScroller.hide();
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (options.numberedMultiColumnSort) { sortIndicatorCssClass = "slick-sort-indicator-numbered"; }
|
|
331
|
+
|
|
332
|
+
$focusSink2 = $focusSink.clone().appendTo($container);
|
|
333
|
+
|
|
334
|
+
if (!options.explicitInitialization) {
|
|
335
|
+
finishInitialization();
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function finishInitialization() {
|
|
340
|
+
if (!initialized) {
|
|
341
|
+
initialized = true;
|
|
342
|
+
|
|
343
|
+
viewportW = parseFloat($.css($container[0], "width", true));
|
|
344
|
+
|
|
345
|
+
// header columns and cells may have different padding/border skewing width calculations (box-sizing, hello?)
|
|
346
|
+
// calculate the diff so we can set consistent sizes
|
|
347
|
+
measureCellPaddingAndBorder();
|
|
348
|
+
|
|
349
|
+
// for usability reasons, all text selection in SlickGrid is disabled
|
|
350
|
+
// with the exception of input and textarea elements (selection must
|
|
351
|
+
// be enabled there so that editors work as expected); note that
|
|
352
|
+
// selection in grid cells (grid body) is already unavailable in
|
|
353
|
+
// all browsers except IE
|
|
354
|
+
disableSelection($headers); // disable all text selection in header (including input and textarea)
|
|
355
|
+
|
|
356
|
+
if (!options.enableTextSelectionOnCells) {
|
|
357
|
+
// disable text selection in grid cells except in input and textarea elements
|
|
358
|
+
// (this is IE-specific, because selectstart event will only fire in IE)
|
|
359
|
+
$viewport.on("selectstart.ui", function (event) {
|
|
360
|
+
return $(event.target).is("input,textarea");
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
updateColumnCaches();
|
|
365
|
+
createColumnHeaders();
|
|
366
|
+
setupColumnSort();
|
|
367
|
+
createCssRules();
|
|
368
|
+
resizeCanvas();
|
|
369
|
+
bindAncestorScrollEvents();
|
|
370
|
+
|
|
371
|
+
$container
|
|
372
|
+
.on("resize.slickgrid", resizeCanvas);
|
|
373
|
+
$viewport
|
|
374
|
+
//.on("click", handleClick)
|
|
375
|
+
.on("scroll", handleScroll);
|
|
376
|
+
$headerScroller
|
|
377
|
+
//.on("scroll", handleHeaderScroll)
|
|
378
|
+
.on("contextmenu", handleHeaderContextMenu)
|
|
379
|
+
.on("click", handleHeaderClick)
|
|
380
|
+
.on("mouseenter", ".slick-header-column", handleHeaderMouseEnter)
|
|
381
|
+
.on("mouseleave", ".slick-header-column", handleHeaderMouseLeave);
|
|
382
|
+
$headerRowScroller
|
|
383
|
+
.on("scroll", handleHeaderRowScroll);
|
|
384
|
+
|
|
385
|
+
if (options.createFooterRow) {
|
|
386
|
+
$footerRowScroller
|
|
387
|
+
.on("scroll", handleFooterRowScroll);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (options.createPreHeaderPanel) {
|
|
391
|
+
$preHeaderPanelScroller
|
|
392
|
+
.on("scroll", handlePreHeaderPanelScroll);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
$focusSink.add($focusSink2)
|
|
396
|
+
.on("keydown", handleKeyDown);
|
|
397
|
+
$canvas
|
|
398
|
+
.on("keydown", handleKeyDown)
|
|
399
|
+
.on("click", handleClick)
|
|
400
|
+
.on("dblclick", handleDblClick)
|
|
401
|
+
.on("contextmenu", handleContextMenu)
|
|
402
|
+
.on("draginit", handleDragInit)
|
|
403
|
+
.on("dragstart", {distance: 3}, handleDragStart)
|
|
404
|
+
.on("drag", handleDrag)
|
|
405
|
+
.on("dragend", handleDragEnd)
|
|
406
|
+
.on("mouseenter", ".slick-cell", handleMouseEnter)
|
|
407
|
+
.on("mouseleave", ".slick-cell", handleMouseLeave);
|
|
408
|
+
|
|
409
|
+
// Work around http://crbug.com/312427.
|
|
410
|
+
if (navigator.userAgent.toLowerCase().match(/webkit/) &&
|
|
411
|
+
navigator.userAgent.toLowerCase().match(/macintosh/)) {
|
|
412
|
+
$canvas.on("mousewheel", handleMouseWheel);
|
|
413
|
+
}
|
|
414
|
+
restoreCssFromHiddenInit();
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function cacheCssForHiddenInit() {
|
|
419
|
+
// handle display:none on container or container parents
|
|
420
|
+
$hiddenParents = $container.parents().addBack().not(':visible');
|
|
421
|
+
$hiddenParents.each(function() {
|
|
422
|
+
var old = {};
|
|
423
|
+
for ( var name in cssShow ) {
|
|
424
|
+
old[ name ] = this.style[ name ];
|
|
425
|
+
this.style[ name ] = cssShow[ name ];
|
|
426
|
+
}
|
|
427
|
+
oldProps.push(old);
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
function restoreCssFromHiddenInit() {
|
|
432
|
+
// finish handle display:none on container or container parents
|
|
433
|
+
// - put values back the way they were
|
|
434
|
+
$hiddenParents.each(function(i) {
|
|
435
|
+
var old = oldProps[i];
|
|
436
|
+
for ( var name in cssShow ) {
|
|
437
|
+
this.style[ name ] = old[ name ];
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
function registerPlugin(plugin) {
|
|
443
|
+
plugins.unshift(plugin);
|
|
444
|
+
plugin.init(self);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function unregisterPlugin(plugin) {
|
|
448
|
+
for (var i = plugins.length; i >= 0; i--) {
|
|
449
|
+
if (plugins[i] === plugin) {
|
|
450
|
+
if (plugins[i].destroy) {
|
|
451
|
+
plugins[i].destroy();
|
|
452
|
+
}
|
|
453
|
+
plugins.splice(i, 1);
|
|
454
|
+
break;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
function setSelectionModel(model) {
|
|
460
|
+
if (selectionModel) {
|
|
461
|
+
selectionModel.onSelectedRangesChanged.unsubscribe(handleSelectedRangesChanged);
|
|
462
|
+
if (selectionModel.destroy) {
|
|
463
|
+
selectionModel.destroy();
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
selectionModel = model;
|
|
468
|
+
if (selectionModel) {
|
|
469
|
+
selectionModel.init(self);
|
|
470
|
+
selectionModel.onSelectedRangesChanged.subscribe(handleSelectedRangesChanged);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
function getSelectionModel() {
|
|
475
|
+
return selectionModel;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function getCanvasNode() {
|
|
479
|
+
return $canvas[0];
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
function measureScrollbar() {
|
|
483
|
+
var $outerdiv = $('<div class="' + $viewport.className + '" style="position:absolute; top:-10000px; left:-10000px; overflow:auto; width:100px; height:100px;"></div>').appendTo($viewport);
|
|
484
|
+
var $innerdiv = $('<div style="width:200px; height:200px; overflow:auto;"></div>').appendTo($outerdiv);
|
|
485
|
+
var dim = {
|
|
486
|
+
width: $outerdiv[0].offsetWidth - $outerdiv[0].clientWidth,
|
|
487
|
+
height: $outerdiv[0].offsetHeight - $outerdiv[0].clientHeight
|
|
488
|
+
};
|
|
489
|
+
$innerdiv.remove();
|
|
490
|
+
$outerdiv.remove();
|
|
491
|
+
return dim;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
function getColumnTotalWidth(includeScrollbar) {
|
|
495
|
+
var totalWidth = 0;
|
|
496
|
+
for (var i = 0, ii = columns.length; i < ii; i++) {
|
|
497
|
+
var width = columns[i].width;
|
|
498
|
+
totalWidth += width;
|
|
499
|
+
}
|
|
500
|
+
if (includeScrollbar) {
|
|
501
|
+
totalWidth += scrollbarDimensions.width;
|
|
502
|
+
}
|
|
503
|
+
return totalWidth;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
function getHeadersWidth() {
|
|
507
|
+
var headersWidth = getColumnTotalWidth(!options.autoHeight);
|
|
508
|
+
return Math.max(headersWidth, viewportW) + 1000;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
function getCanvasWidth() {
|
|
512
|
+
var availableWidth = viewportHasVScroll ? viewportW - scrollbarDimensions.width : viewportW;
|
|
513
|
+
var rowWidth = 0;
|
|
514
|
+
var i = columns.length;
|
|
515
|
+
while (i--) {
|
|
516
|
+
rowWidth += columns[i].width;
|
|
517
|
+
}
|
|
518
|
+
return options.fullWidthRows ? Math.max(rowWidth, availableWidth) : rowWidth;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
function updateCanvasWidth(forceColumnWidthsUpdate) {
|
|
522
|
+
var oldCanvasWidth = canvasWidth;
|
|
523
|
+
canvasWidth = getCanvasWidth();
|
|
524
|
+
|
|
525
|
+
if (canvasWidth != oldCanvasWidth) {
|
|
526
|
+
$canvas.width(canvasWidth);
|
|
527
|
+
$headerRow.width(canvasWidth);
|
|
528
|
+
if (options.createFooterRow) { $footerRow.width(canvasWidth); }
|
|
529
|
+
if (options.createPreHeaderPanel) { $preHeaderPanel.width(canvasWidth); }
|
|
530
|
+
$headers.width(getHeadersWidth());
|
|
531
|
+
viewportHasHScroll = (canvasWidth > viewportW - scrollbarDimensions.width);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
var w=canvasWidth + (viewportHasVScroll ? scrollbarDimensions.width : 0);
|
|
535
|
+
$headerRowSpacer.width(w);
|
|
536
|
+
if (options.createFooterRow) { $footerRowSpacer.width(w); }
|
|
537
|
+
if (options.createPreHeaderPanel) { $preHeaderPanelSpacer.width(w); }
|
|
538
|
+
|
|
539
|
+
if (canvasWidth != oldCanvasWidth || forceColumnWidthsUpdate) {
|
|
540
|
+
applyColumnWidths();
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
function disableSelection($target) {
|
|
545
|
+
if ($target && $target.jquery) {
|
|
546
|
+
$target
|
|
547
|
+
.attr("unselectable", "on")
|
|
548
|
+
.css("MozUserSelect", "none")
|
|
549
|
+
.on("selectstart.ui", function () {
|
|
550
|
+
return false;
|
|
551
|
+
}); // from jquery:ui.core.js 1.7.2
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
function getMaxSupportedCssHeight() {
|
|
556
|
+
var supportedHeight = 1000000;
|
|
557
|
+
// FF reports the height back but still renders blank after ~6M px
|
|
558
|
+
var testUpTo = navigator.userAgent.toLowerCase().match(/firefox/) ? 6000000 : 1000000000;
|
|
559
|
+
var div = $("<div style='display:none' />").appendTo(document.body);
|
|
560
|
+
|
|
561
|
+
while (true) {
|
|
562
|
+
var test = supportedHeight * 2;
|
|
563
|
+
div.css("height", test);
|
|
564
|
+
if (test > testUpTo || div.height() !== test) {
|
|
565
|
+
break;
|
|
566
|
+
} else {
|
|
567
|
+
supportedHeight = test;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
div.remove();
|
|
572
|
+
return supportedHeight;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
function getUID() {
|
|
576
|
+
return uid;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
function getHeaderColumnWidthDiff() {
|
|
580
|
+
return headerColumnWidthDiff;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
function getScrollbarDimensions() {
|
|
584
|
+
return scrollbarDimensions;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// TODO: this is static. need to handle page mutation.
|
|
588
|
+
function bindAncestorScrollEvents() {
|
|
589
|
+
var elem = $canvas[0];
|
|
590
|
+
while ((elem = elem.parentNode) != document.body && elem != null) {
|
|
591
|
+
// bind to scroll containers only
|
|
592
|
+
if (elem == $viewport[0] || elem.scrollWidth != elem.clientWidth || elem.scrollHeight != elem.clientHeight) {
|
|
593
|
+
var $elem = $(elem);
|
|
594
|
+
if (!$boundAncestors) {
|
|
595
|
+
$boundAncestors = $elem;
|
|
596
|
+
} else {
|
|
597
|
+
$boundAncestors = $boundAncestors.add($elem);
|
|
598
|
+
}
|
|
599
|
+
$elem.on("scroll." + uid, handleActiveCellPositionChange);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
function unbindAncestorScrollEvents() {
|
|
605
|
+
if (!$boundAncestors) {
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
$boundAncestors.off("scroll." + uid);
|
|
609
|
+
$boundAncestors = null;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
function updateColumnHeader(columnId, title, toolTip) {
|
|
613
|
+
if (!initialized) { return; }
|
|
614
|
+
var idx = getColumnIndex(columnId);
|
|
615
|
+
if (idx == null) {
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
var columnDef = columns[idx];
|
|
620
|
+
var $header = $headers.children().eq(idx);
|
|
621
|
+
if ($header) {
|
|
622
|
+
if (title !== undefined) {
|
|
623
|
+
columns[idx].name = title;
|
|
624
|
+
}
|
|
625
|
+
if (toolTip !== undefined) {
|
|
626
|
+
columns[idx].toolTip = toolTip;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
trigger(self.onBeforeHeaderCellDestroy, {
|
|
630
|
+
"node": $header[0],
|
|
631
|
+
"column": columnDef,
|
|
632
|
+
"grid": self
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
$header
|
|
636
|
+
.attr("title", toolTip || "")
|
|
637
|
+
.children().eq(0).html(title);
|
|
638
|
+
|
|
639
|
+
trigger(self.onHeaderCellRendered, {
|
|
640
|
+
"node": $header[0],
|
|
641
|
+
"column": columnDef,
|
|
642
|
+
"grid": self
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
function getHeader() {
|
|
648
|
+
return $header[0];
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
function getHeaderColumn(columnIdOrIdx) {
|
|
652
|
+
var idx = (typeof columnIdOrIdx === "number" ? columnIdOrIdx : getColumnIndex[columnIdOrIdx]);
|
|
653
|
+
var $rtn = $header.children().eq(idx);
|
|
654
|
+
return $rtn && $rtn[0];
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
function getHeaderRow() {
|
|
658
|
+
return $headerRow[0];
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
function getFooterRow() {
|
|
662
|
+
return $footerRow[0];
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
function getPreHeaderPanel() {
|
|
666
|
+
return $preHeaderPanel[0];
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
function getHeaderRowColumn(columnIdOrIdx) {
|
|
670
|
+
var idx = (typeof columnIdOrIdx === "number" ? columnIdOrIdx : getColumnIndex[columnIdOrIdx]);
|
|
671
|
+
var $rtn = $headerRow.children().eq(idx);
|
|
672
|
+
return $rtn && $rtn[0];
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
function getFooterRowColumn(columnIdOrIdx) {
|
|
676
|
+
var idx = (typeof columnIdOrIdx === "number" ? columnIdOrIdx : getColumnIndex[columnIdOrIdx]);
|
|
677
|
+
var $rtn = $footerRow.children().eq(idx);
|
|
678
|
+
return $rtn && $rtn[0];
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
function createColumnHeaders() {
|
|
682
|
+
function onMouseEnter() {
|
|
683
|
+
$(this).addClass("ui-state-hover");
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
function onMouseLeave() {
|
|
687
|
+
$(this).removeClass("ui-state-hover");
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
$headers.find(".slick-header-column")
|
|
691
|
+
.each(function() {
|
|
692
|
+
var columnDef = $(this).data("column");
|
|
693
|
+
if (columnDef) {
|
|
694
|
+
trigger(self.onBeforeHeaderCellDestroy, {
|
|
695
|
+
"node": this,
|
|
696
|
+
"column": columnDef,
|
|
697
|
+
"grid": self
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
});
|
|
701
|
+
$headers.empty();
|
|
702
|
+
$headers.width(getHeadersWidth());
|
|
703
|
+
|
|
704
|
+
$headerRow.find(".slick-headerrow-column")
|
|
705
|
+
.each(function() {
|
|
706
|
+
var columnDef = $(this).data("column");
|
|
707
|
+
if (columnDef) {
|
|
708
|
+
trigger(self.onBeforeHeaderRowCellDestroy, {
|
|
709
|
+
"node": this,
|
|
710
|
+
"column": columnDef,
|
|
711
|
+
"grid": self
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
});
|
|
715
|
+
$headerRow.empty();
|
|
716
|
+
|
|
717
|
+
if (options.createFooterRow) {
|
|
718
|
+
$footerRow.find(".slick-footerrow-column")
|
|
719
|
+
.each(function() {
|
|
720
|
+
var columnDef = $(this).data("column");
|
|
721
|
+
if (columnDef) {
|
|
722
|
+
trigger(self.onBeforeFooterRowCellDestroy, {
|
|
723
|
+
"node": this,
|
|
724
|
+
"column": columnDef
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
});
|
|
728
|
+
$footerRow.empty();
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
for (var i = 0; i < columns.length; i++) {
|
|
732
|
+
var m = columns[i];
|
|
733
|
+
|
|
734
|
+
var header = $("<div class='ui-state-default slick-header-column' />")
|
|
735
|
+
.html("<span class='slick-column-name'>" + m.name + "</span>")
|
|
736
|
+
.width(m.width - headerColumnWidthDiff)
|
|
737
|
+
.attr("id", "" + uid + m.id)
|
|
738
|
+
.attr("title", m.toolTip || "")
|
|
739
|
+
.data("column", m)
|
|
740
|
+
.addClass(m.headerCssClass || "")
|
|
741
|
+
.appendTo($headers);
|
|
742
|
+
|
|
743
|
+
if (options.enableColumnReorder || m.sortable) {
|
|
744
|
+
header
|
|
745
|
+
.on('mouseenter', onMouseEnter)
|
|
746
|
+
.on('mouseleave', onMouseLeave);
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
if (m.sortable) {
|
|
750
|
+
header.addClass("slick-header-sortable");
|
|
751
|
+
header.append("<span class='" + sortIndicatorCssClass + "' />");
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
trigger(self.onHeaderCellRendered, {
|
|
755
|
+
"node": header[0],
|
|
756
|
+
"column": m,
|
|
757
|
+
"grid": self
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
if (options.showHeaderRow) {
|
|
761
|
+
var headerRowCell = $("<div class='ui-state-default slick-headerrow-column l" + i + " r" + i + "'></div>")
|
|
762
|
+
.data("column", m)
|
|
763
|
+
.appendTo($headerRow);
|
|
764
|
+
|
|
765
|
+
trigger(self.onHeaderRowCellRendered, {
|
|
766
|
+
"node": headerRowCell[0],
|
|
767
|
+
"column": m,
|
|
768
|
+
"grid": self
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
if (options.createFooterRow && options.showFooterRow) {
|
|
772
|
+
var footerRowCell = $("<div class='ui-state-default slick-footerrow-column l" + i + " r" + i + "'></div>")
|
|
773
|
+
.data("column", m)
|
|
774
|
+
.appendTo($footerRow);
|
|
775
|
+
|
|
776
|
+
trigger(self.onFooterRowCellRendered, {
|
|
777
|
+
"node": footerRowCell[0],
|
|
778
|
+
"column": m
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
setSortColumns(sortColumns);
|
|
784
|
+
setupColumnResize();
|
|
785
|
+
if (options.enableColumnReorder) {
|
|
786
|
+
if (typeof options.enableColumnReorder == 'function') {
|
|
787
|
+
options.enableColumnReorder(self, $headers, headerColumnWidthDiff, setColumns, setupColumnResize, columns, getColumnIndex, uid, trigger);
|
|
788
|
+
} else {
|
|
789
|
+
setupColumnReorder();
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
function setupColumnSort() {
|
|
795
|
+
$headers.click(function (e) {
|
|
796
|
+
if (columnResizeDragging) return;
|
|
797
|
+
// temporary workaround for a bug in jQuery 1.7.1 (http://bugs.jquery.com/ticket/11328)
|
|
798
|
+
e.metaKey = e.metaKey || e.ctrlKey;
|
|
799
|
+
|
|
800
|
+
if ($(e.target).hasClass("slick-resizable-handle")) {
|
|
801
|
+
return;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
var $col = $(e.target).closest(".slick-header-column");
|
|
805
|
+
if (!$col.length) {
|
|
806
|
+
return;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
var column = $col.data("column");
|
|
810
|
+
if (column.sortable) {
|
|
811
|
+
if (!getEditorLock().commitCurrentEdit()) {
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
var sortColumn = null;
|
|
816
|
+
var i = 0;
|
|
817
|
+
for (; i < sortColumns.length; i++) {
|
|
818
|
+
if (sortColumns[i].columnId == column.id) {
|
|
819
|
+
sortColumn = sortColumns[i];
|
|
820
|
+
sortColumn.sortAsc = !sortColumn.sortAsc;
|
|
821
|
+
break;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
var hadSortCol = !!sortColumn;
|
|
825
|
+
|
|
826
|
+
if (options.tristateMultiColumnSort) {
|
|
827
|
+
if (!sortColumn) {
|
|
828
|
+
sortColumn = { columnId: column.id, sortAsc: column.defaultSortAsc };
|
|
829
|
+
}
|
|
830
|
+
if (hadSortCol && sortColumn.sortAsc) {
|
|
831
|
+
// three state: remove sort rather than go back to ASC
|
|
832
|
+
sortColumns.splice(i, 1);
|
|
833
|
+
sortColumn = null;
|
|
834
|
+
}
|
|
835
|
+
if (!options.multiColumnSort) { sortColumns = []; }
|
|
836
|
+
if (sortColumn && (!hadSortCol || !options.multiColumnSort)) {
|
|
837
|
+
sortColumns.push(sortColumn);
|
|
838
|
+
}
|
|
839
|
+
} else {
|
|
840
|
+
// legacy behaviour
|
|
841
|
+
if (e.metaKey && options.multiColumnSort) {
|
|
842
|
+
if (sortColumn) {
|
|
843
|
+
sortColumns.splice(i, 1);
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
else {
|
|
847
|
+
if ((!e.shiftKey && !e.metaKey) || !options.multiColumnSort) {
|
|
848
|
+
sortColumns = [];
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
if (!sortColumn) {
|
|
852
|
+
sortColumn = { columnId: column.id, sortAsc: column.defaultSortAsc };
|
|
853
|
+
sortColumns.push(sortColumn);
|
|
854
|
+
} else if (sortColumns.length == 0) {
|
|
855
|
+
sortColumns.push(sortColumn);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
setSortColumns(sortColumns);
|
|
861
|
+
|
|
862
|
+
if (!options.multiColumnSort) {
|
|
863
|
+
trigger(self.onSort, {
|
|
864
|
+
multiColumnSort: false,
|
|
865
|
+
sortCol: (sortColumns.length > 0 ? column : null),
|
|
866
|
+
sortAsc: (sortColumns.length > 0 ? sortColumns[0].sortAsc : true),
|
|
867
|
+
grid: self}, e);
|
|
868
|
+
} else {
|
|
869
|
+
trigger(self.onSort, {
|
|
870
|
+
multiColumnSort: true,
|
|
871
|
+
sortCols: $.map(sortColumns, function(col) {
|
|
872
|
+
return {sortCol: columns[getColumnIndex(col.columnId)], sortAsc: col.sortAsc };
|
|
873
|
+
}),
|
|
874
|
+
grid: self}, e);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
function setupColumnReorder() {
|
|
881
|
+
$headers.filter(":ui-sortable").sortable("destroy");
|
|
882
|
+
$headers.sortable({
|
|
883
|
+
containment: "parent",
|
|
884
|
+
distance: 3,
|
|
885
|
+
axis: "x",
|
|
886
|
+
cursor: "default",
|
|
887
|
+
tolerance: "intersection",
|
|
888
|
+
helper: "clone",
|
|
889
|
+
placeholder: "slick-sortable-placeholder ui-state-default slick-header-column",
|
|
890
|
+
start: function (e, ui) {
|
|
891
|
+
ui.placeholder.width(ui.helper.outerWidth() - headerColumnWidthDiff);
|
|
892
|
+
$(ui.helper).addClass("slick-header-column-active");
|
|
893
|
+
},
|
|
894
|
+
beforeStop: function (e, ui) {
|
|
895
|
+
$(ui.helper).removeClass("slick-header-column-active");
|
|
896
|
+
},
|
|
897
|
+
stop: function (e) {
|
|
898
|
+
if (!getEditorLock().commitCurrentEdit()) {
|
|
899
|
+
$(this).sortable("cancel");
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
var reorderedIds = $headers.sortable("toArray");
|
|
904
|
+
var reorderedColumns = [];
|
|
905
|
+
for (var i = 0; i < reorderedIds.length; i++) {
|
|
906
|
+
reorderedColumns.push(columns[getColumnIndex(reorderedIds[i].replace(uid, ""))]);
|
|
907
|
+
}
|
|
908
|
+
setColumns(reorderedColumns);
|
|
909
|
+
|
|
910
|
+
trigger(self.onColumnsReordered, {grid: self});
|
|
911
|
+
e.stopPropagation();
|
|
912
|
+
setupColumnResize();
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
function setupColumnResize() {
|
|
918
|
+
var $col, j, c, pageX, columnElements, minPageX, maxPageX, firstResizable, lastResizable;
|
|
919
|
+
columnElements = $headers.children();
|
|
920
|
+
columnElements.find(".slick-resizable-handle").remove();
|
|
921
|
+
columnElements.each(function (i, e) {
|
|
922
|
+
if (i >= columns.length) { return; }
|
|
923
|
+
if (columns[i].resizable) {
|
|
924
|
+
if (firstResizable === undefined) {
|
|
925
|
+
firstResizable = i;
|
|
926
|
+
}
|
|
927
|
+
lastResizable = i;
|
|
928
|
+
}
|
|
929
|
+
});
|
|
930
|
+
if (firstResizable === undefined) {
|
|
931
|
+
return;
|
|
932
|
+
}
|
|
933
|
+
columnElements.each(function (i, e) {
|
|
934
|
+
if (i >= columns.length) { return; }
|
|
935
|
+
if (i < firstResizable || (options.forceFitColumns && i >= lastResizable)) {
|
|
936
|
+
return;
|
|
937
|
+
}
|
|
938
|
+
$col = $(e);
|
|
939
|
+
$("<div class='slick-resizable-handle' />")
|
|
940
|
+
.appendTo(e)
|
|
941
|
+
.on("dragstart", function (e, dd) {
|
|
942
|
+
if (!getEditorLock().commitCurrentEdit()) {
|
|
943
|
+
return false;
|
|
944
|
+
}
|
|
945
|
+
pageX = e.pageX;
|
|
946
|
+
$(this).parent().addClass("slick-header-column-active");
|
|
947
|
+
var shrinkLeewayOnRight = null, stretchLeewayOnRight = null;
|
|
948
|
+
// lock each column's width option to current width
|
|
949
|
+
columnElements.each(function (i, e) {
|
|
950
|
+
if (i >= columns.length) { return; }
|
|
951
|
+
columns[i].previousWidth = $(e).outerWidth();
|
|
952
|
+
});
|
|
953
|
+
if (options.forceFitColumns) {
|
|
954
|
+
shrinkLeewayOnRight = 0;
|
|
955
|
+
stretchLeewayOnRight = 0;
|
|
956
|
+
// colums on right affect maxPageX/minPageX
|
|
957
|
+
for (j = i + 1; j < columns.length; j++) {
|
|
958
|
+
c = columns[j];
|
|
959
|
+
if (c.resizable) {
|
|
960
|
+
if (stretchLeewayOnRight !== null) {
|
|
961
|
+
if (c.maxWidth) {
|
|
962
|
+
stretchLeewayOnRight += c.maxWidth - c.previousWidth;
|
|
963
|
+
} else {
|
|
964
|
+
stretchLeewayOnRight = null;
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
shrinkLeewayOnRight += c.previousWidth - Math.max(c.minWidth || 0, absoluteColumnMinWidth);
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
var shrinkLeewayOnLeft = 0, stretchLeewayOnLeft = 0;
|
|
972
|
+
for (j = 0; j <= i; j++) {
|
|
973
|
+
// columns on left only affect minPageX
|
|
974
|
+
c = columns[j];
|
|
975
|
+
if (c.resizable) {
|
|
976
|
+
if (stretchLeewayOnLeft !== null) {
|
|
977
|
+
if (c.maxWidth) {
|
|
978
|
+
stretchLeewayOnLeft += c.maxWidth - c.previousWidth;
|
|
979
|
+
} else {
|
|
980
|
+
stretchLeewayOnLeft = null;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
shrinkLeewayOnLeft += c.previousWidth - Math.max(c.minWidth || 0, absoluteColumnMinWidth);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
if (shrinkLeewayOnRight === null) {
|
|
987
|
+
shrinkLeewayOnRight = 100000;
|
|
988
|
+
}
|
|
989
|
+
if (shrinkLeewayOnLeft === null) {
|
|
990
|
+
shrinkLeewayOnLeft = 100000;
|
|
991
|
+
}
|
|
992
|
+
if (stretchLeewayOnRight === null) {
|
|
993
|
+
stretchLeewayOnRight = 100000;
|
|
994
|
+
}
|
|
995
|
+
if (stretchLeewayOnLeft === null) {
|
|
996
|
+
stretchLeewayOnLeft = 100000;
|
|
997
|
+
}
|
|
998
|
+
maxPageX = pageX + Math.min(shrinkLeewayOnRight, stretchLeewayOnLeft);
|
|
999
|
+
minPageX = pageX - Math.min(shrinkLeewayOnLeft, stretchLeewayOnRight);
|
|
1000
|
+
})
|
|
1001
|
+
.on("drag", function (e, dd) {
|
|
1002
|
+
columnResizeDragging = true;
|
|
1003
|
+
var actualMinWidth, d = Math.min(maxPageX, Math.max(minPageX, e.pageX)) - pageX, x;
|
|
1004
|
+
if (d < 0) { // shrink column
|
|
1005
|
+
x = d;
|
|
1006
|
+
for (j = i; j >= 0; j--) {
|
|
1007
|
+
c = columns[j];
|
|
1008
|
+
if (c.resizable) {
|
|
1009
|
+
actualMinWidth = Math.max(c.minWidth || 0, absoluteColumnMinWidth);
|
|
1010
|
+
if (x && c.previousWidth + x < actualMinWidth) {
|
|
1011
|
+
x += c.previousWidth - actualMinWidth;
|
|
1012
|
+
c.width = actualMinWidth;
|
|
1013
|
+
} else {
|
|
1014
|
+
c.width = c.previousWidth + x;
|
|
1015
|
+
x = 0;
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
if (options.forceFitColumns) {
|
|
1021
|
+
x = -d;
|
|
1022
|
+
for (j = i + 1; j < columns.length; j++) {
|
|
1023
|
+
c = columns[j];
|
|
1024
|
+
if (c.resizable) {
|
|
1025
|
+
if (x && c.maxWidth && (c.maxWidth - c.previousWidth < x)) {
|
|
1026
|
+
x -= c.maxWidth - c.previousWidth;
|
|
1027
|
+
c.width = c.maxWidth;
|
|
1028
|
+
} else {
|
|
1029
|
+
c.width = c.previousWidth + x;
|
|
1030
|
+
x = 0;
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
} else { // stretch column
|
|
1036
|
+
x = d;
|
|
1037
|
+
for (j = i; j >= 0; j--) {
|
|
1038
|
+
c = columns[j];
|
|
1039
|
+
if (c.resizable) {
|
|
1040
|
+
if (x && c.maxWidth && (c.maxWidth - c.previousWidth < x)) {
|
|
1041
|
+
x -= c.maxWidth - c.previousWidth;
|
|
1042
|
+
c.width = c.maxWidth;
|
|
1043
|
+
} else {
|
|
1044
|
+
c.width = c.previousWidth + x;
|
|
1045
|
+
x = 0;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
if (options.forceFitColumns) {
|
|
1051
|
+
x = -d;
|
|
1052
|
+
for (j = i + 1; j < columns.length; j++) {
|
|
1053
|
+
c = columns[j];
|
|
1054
|
+
if (c.resizable) {
|
|
1055
|
+
actualMinWidth = Math.max(c.minWidth || 0, absoluteColumnMinWidth);
|
|
1056
|
+
if (x && c.previousWidth + x < actualMinWidth) {
|
|
1057
|
+
x += c.previousWidth - actualMinWidth;
|
|
1058
|
+
c.width = actualMinWidth;
|
|
1059
|
+
} else {
|
|
1060
|
+
c.width = c.previousWidth + x;
|
|
1061
|
+
x = 0;
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
applyColumnHeaderWidths();
|
|
1068
|
+
if (options.syncColumnCellResize) {
|
|
1069
|
+
applyColumnWidths();
|
|
1070
|
+
}
|
|
1071
|
+
})
|
|
1072
|
+
.on("dragend", function (e, dd) {
|
|
1073
|
+
var newWidth;
|
|
1074
|
+
$(this).parent().removeClass("slick-header-column-active");
|
|
1075
|
+
for (j = 0; j < columns.length; j++) {
|
|
1076
|
+
c = columns[j];
|
|
1077
|
+
newWidth = $(columnElements[j]).outerWidth();
|
|
1078
|
+
|
|
1079
|
+
if (c.previousWidth !== newWidth && c.rerenderOnResize) {
|
|
1080
|
+
invalidateAllRows();
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
updateCanvasWidth(true);
|
|
1084
|
+
render();
|
|
1085
|
+
trigger(self.onColumnsResized, {grid: self});
|
|
1086
|
+
setTimeout(function () { columnResizeDragging = false; }, 300);
|
|
1087
|
+
});
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
function getVBoxDelta($el) {
|
|
1092
|
+
var p = ["borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom"];
|
|
1093
|
+
var delta = 0;
|
|
1094
|
+
$.each(p, function (n, val) {
|
|
1095
|
+
delta += parseFloat($el.css(val)) || 0;
|
|
1096
|
+
});
|
|
1097
|
+
return delta;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
function measureCellPaddingAndBorder() {
|
|
1101
|
+
var el;
|
|
1102
|
+
var h = ["borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight"];
|
|
1103
|
+
var v = ["borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom"];
|
|
1104
|
+
|
|
1105
|
+
// jquery prior to version 1.8 handles .width setter/getter as a direct css write/read
|
|
1106
|
+
// jquery 1.8 changed .width to read the true inner element width if box-sizing is set to border-box, and introduced a setter for .outerWidth
|
|
1107
|
+
// so for equivalent functionality, prior to 1.8 use .width, and after use .outerWidth
|
|
1108
|
+
var verArray = $.fn.jquery.split('.');
|
|
1109
|
+
jQueryNewWidthBehaviour = (verArray[0]==1 && verArray[1]>=8) || verArray[0] >=2;
|
|
1110
|
+
|
|
1111
|
+
el = $("<div class='ui-state-default slick-header-column' style='visibility:hidden'>-</div>").appendTo($headers);
|
|
1112
|
+
headerColumnWidthDiff = headerColumnHeightDiff = 0;
|
|
1113
|
+
if (el.css("box-sizing") != "border-box" && el.css("-moz-box-sizing") != "border-box" && el.css("-webkit-box-sizing") != "border-box") {
|
|
1114
|
+
$.each(h, function (n, val) {
|
|
1115
|
+
headerColumnWidthDiff += parseFloat(el.css(val)) || 0;
|
|
1116
|
+
});
|
|
1117
|
+
$.each(v, function (n, val) {
|
|
1118
|
+
headerColumnHeightDiff += parseFloat(el.css(val)) || 0;
|
|
1119
|
+
});
|
|
1120
|
+
}
|
|
1121
|
+
el.remove();
|
|
1122
|
+
|
|
1123
|
+
var r = $("<div class='slick-row' />").appendTo($canvas);
|
|
1124
|
+
el = $("<div class='slick-cell' id='' style='visibility:hidden'>-</div>").appendTo(r);
|
|
1125
|
+
cellWidthDiff = cellHeightDiff = 0;
|
|
1126
|
+
if (el.css("box-sizing") != "border-box" && el.css("-moz-box-sizing") != "border-box" && el.css("-webkit-box-sizing") != "border-box") {
|
|
1127
|
+
$.each(h, function (n, val) {
|
|
1128
|
+
cellWidthDiff += parseFloat(el.css(val)) || 0;
|
|
1129
|
+
});
|
|
1130
|
+
$.each(v, function (n, val) {
|
|
1131
|
+
cellHeightDiff += parseFloat(el.css(val)) || 0;
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1134
|
+
r.remove();
|
|
1135
|
+
|
|
1136
|
+
absoluteColumnMinWidth = Math.max(headerColumnWidthDiff, cellWidthDiff);
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
function createCssRules() {
|
|
1140
|
+
$style = $("<style type='text/css' rel='stylesheet' />").appendTo($("head"));
|
|
1141
|
+
var rowHeight = (options.rowHeight - cellHeightDiff);
|
|
1142
|
+
var rules = [
|
|
1143
|
+
"." + uid + " .slick-header-column { left: 1000px; }",
|
|
1144
|
+
"." + uid + " .slick-top-panel { height:" + options.topPanelHeight + "px; }",
|
|
1145
|
+
"." + uid + " .slick-preheader-panel { height:" + options.preHeaderPanelHeight + "px; }",
|
|
1146
|
+
"." + uid + " .slick-headerrow-columns { height:" + options.headerRowHeight + "px; }",
|
|
1147
|
+
"." + uid + " .slick-footerrow-columns { height:" + options.footerRowHeight + "px; }",
|
|
1148
|
+
"." + uid + " .slick-cell { height:" + rowHeight + "px; }",
|
|
1149
|
+
"." + uid + " .slick-row { height:" + options.rowHeight + "px; }"
|
|
1150
|
+
];
|
|
1151
|
+
|
|
1152
|
+
for (var i = 0; i < columns.length; i++) {
|
|
1153
|
+
rules.push("." + uid + " .l" + i + " { }");
|
|
1154
|
+
rules.push("." + uid + " .r" + i + " { }");
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
if ($style[0].styleSheet) { // IE
|
|
1158
|
+
$style[0].styleSheet.cssText = rules.join(" ");
|
|
1159
|
+
} else {
|
|
1160
|
+
$style[0].appendChild(document.createTextNode(rules.join(" ")));
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
function getColumnCssRules(idx) {
|
|
1165
|
+
var i;
|
|
1166
|
+
if (!stylesheet) {
|
|
1167
|
+
var sheets = document.styleSheets;
|
|
1168
|
+
for (i = 0; i < sheets.length; i++) {
|
|
1169
|
+
if ((sheets[i].ownerNode || sheets[i].owningElement) == $style[0]) {
|
|
1170
|
+
stylesheet = sheets[i];
|
|
1171
|
+
break;
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
if (!stylesheet) {
|
|
1176
|
+
throw new Error("Cannot find stylesheet.");
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
// find and cache column CSS rules
|
|
1180
|
+
columnCssRulesL = [];
|
|
1181
|
+
columnCssRulesR = [];
|
|
1182
|
+
var cssRules = (stylesheet.cssRules || stylesheet.rules);
|
|
1183
|
+
var matches, columnIdx;
|
|
1184
|
+
for (i = 0; i < cssRules.length; i++) {
|
|
1185
|
+
var selector = cssRules[i].selectorText;
|
|
1186
|
+
if (matches = /\.l\d+/.exec(selector)) {
|
|
1187
|
+
columnIdx = parseInt(matches[0].substr(2, matches[0].length - 2), 10);
|
|
1188
|
+
columnCssRulesL[columnIdx] = cssRules[i];
|
|
1189
|
+
} else if (matches = /\.r\d+/.exec(selector)) {
|
|
1190
|
+
columnIdx = parseInt(matches[0].substr(2, matches[0].length - 2), 10);
|
|
1191
|
+
columnCssRulesR[columnIdx] = cssRules[i];
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
return {
|
|
1197
|
+
"left": columnCssRulesL[idx],
|
|
1198
|
+
"right": columnCssRulesR[idx]
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
function removeCssRules() {
|
|
1203
|
+
$style.remove();
|
|
1204
|
+
stylesheet = null;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
function destroy() {
|
|
1208
|
+
getEditorLock().cancelCurrentEdit();
|
|
1209
|
+
|
|
1210
|
+
trigger(self.onBeforeDestroy, {grid: self});
|
|
1211
|
+
|
|
1212
|
+
var i = plugins.length;
|
|
1213
|
+
while(i--) {
|
|
1214
|
+
unregisterPlugin(plugins[i]);
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
if (options.enableColumnReorder) {
|
|
1218
|
+
$headers.filter(":ui-sortable").sortable("destroy");
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
unbindAncestorScrollEvents();
|
|
1222
|
+
$container.off(".slickgrid");
|
|
1223
|
+
removeCssRules();
|
|
1224
|
+
|
|
1225
|
+
$canvas.off("draginit dragstart dragend drag");
|
|
1226
|
+
$container.empty().removeClass(uid);
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
|
|
1230
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
1231
|
+
// General
|
|
1232
|
+
|
|
1233
|
+
function trigger(evt, args, e) {
|
|
1234
|
+
e = e || new Slick.EventData();
|
|
1235
|
+
args = args || {};
|
|
1236
|
+
args.grid = self;
|
|
1237
|
+
return evt.notify(args, e, self);
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
function getEditorLock() {
|
|
1241
|
+
return options.editorLock;
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
function getEditController() {
|
|
1245
|
+
return editController;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
function getColumnIndex(id) {
|
|
1249
|
+
return columnsById[id];
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
function autosizeColumns() {
|
|
1253
|
+
var i, c,
|
|
1254
|
+
widths = [],
|
|
1255
|
+
shrinkLeeway = 0,
|
|
1256
|
+
total = 0,
|
|
1257
|
+
prevTotal,
|
|
1258
|
+
availWidth = viewportHasVScroll ? viewportW - scrollbarDimensions.width : viewportW;
|
|
1259
|
+
|
|
1260
|
+
for (i = 0; i < columns.length; i++) {
|
|
1261
|
+
c = columns[i];
|
|
1262
|
+
widths.push(c.width);
|
|
1263
|
+
total += c.width;
|
|
1264
|
+
if (c.resizable) {
|
|
1265
|
+
shrinkLeeway += c.width - Math.max(c.minWidth, absoluteColumnMinWidth);
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
// shrink
|
|
1270
|
+
prevTotal = total;
|
|
1271
|
+
while (total > availWidth && shrinkLeeway) {
|
|
1272
|
+
var shrinkProportion = (total - availWidth) / shrinkLeeway;
|
|
1273
|
+
for (i = 0; i < columns.length && total > availWidth; i++) {
|
|
1274
|
+
c = columns[i];
|
|
1275
|
+
var width = widths[i];
|
|
1276
|
+
if (!c.resizable || width <= c.minWidth || width <= absoluteColumnMinWidth) {
|
|
1277
|
+
continue;
|
|
1278
|
+
}
|
|
1279
|
+
var absMinWidth = Math.max(c.minWidth, absoluteColumnMinWidth);
|
|
1280
|
+
var shrinkSize = Math.floor(shrinkProportion * (width - absMinWidth)) || 1;
|
|
1281
|
+
shrinkSize = Math.min(shrinkSize, width - absMinWidth);
|
|
1282
|
+
total -= shrinkSize;
|
|
1283
|
+
shrinkLeeway -= shrinkSize;
|
|
1284
|
+
widths[i] -= shrinkSize;
|
|
1285
|
+
}
|
|
1286
|
+
if (prevTotal <= total) { // avoid infinite loop
|
|
1287
|
+
break;
|
|
1288
|
+
}
|
|
1289
|
+
prevTotal = total;
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
// grow
|
|
1293
|
+
prevTotal = total;
|
|
1294
|
+
while (total < availWidth) {
|
|
1295
|
+
var growProportion = availWidth / total;
|
|
1296
|
+
for (i = 0; i < columns.length && total < availWidth; i++) {
|
|
1297
|
+
c = columns[i];
|
|
1298
|
+
var currentWidth = widths[i];
|
|
1299
|
+
var growSize;
|
|
1300
|
+
|
|
1301
|
+
if (!c.resizable || c.maxWidth <= currentWidth) {
|
|
1302
|
+
growSize = 0;
|
|
1303
|
+
} else {
|
|
1304
|
+
growSize = Math.min(Math.floor(growProportion * currentWidth) - currentWidth, (c.maxWidth - currentWidth) || 1000000) || 1;
|
|
1305
|
+
}
|
|
1306
|
+
total += growSize;
|
|
1307
|
+
widths[i] += (total <= availWidth ? growSize : 0);
|
|
1308
|
+
}
|
|
1309
|
+
if (prevTotal >= total) { // avoid infinite loop
|
|
1310
|
+
break;
|
|
1311
|
+
}
|
|
1312
|
+
prevTotal = total;
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
var reRender = false;
|
|
1316
|
+
for (i = 0; i < columns.length; i++) {
|
|
1317
|
+
if (columns[i].rerenderOnResize && columns[i].width != widths[i]) {
|
|
1318
|
+
reRender = true;
|
|
1319
|
+
}
|
|
1320
|
+
columns[i].width = widths[i];
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
applyColumnHeaderWidths();
|
|
1324
|
+
updateCanvasWidth(true);
|
|
1325
|
+
if (reRender) {
|
|
1326
|
+
invalidateAllRows();
|
|
1327
|
+
render();
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
function applyColumnHeaderWidths() {
|
|
1332
|
+
if (!initialized) { return; }
|
|
1333
|
+
var h;
|
|
1334
|
+
|
|
1335
|
+
for (var i = 0, headers = $headers.children(), ii = columns.length; i < ii; i++) {
|
|
1336
|
+
h = $(headers[i]);
|
|
1337
|
+
if (jQueryNewWidthBehaviour) {
|
|
1338
|
+
if (h.outerWidth() !== columns[i].width) {
|
|
1339
|
+
h.outerWidth(columns[i].width);
|
|
1340
|
+
}
|
|
1341
|
+
} else {
|
|
1342
|
+
if (h.width() !== columns[i].width - headerColumnWidthDiff) {
|
|
1343
|
+
h.width(columns[i].width - headerColumnWidthDiff);
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
updateColumnCaches();
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
function applyColumnWidths() {
|
|
1352
|
+
var x = 0, w, rule;
|
|
1353
|
+
for (var i = 0; i < columns.length; i++) {
|
|
1354
|
+
w = columns[i].width;
|
|
1355
|
+
|
|
1356
|
+
rule = getColumnCssRules(i);
|
|
1357
|
+
rule.left.style.left = x + "px";
|
|
1358
|
+
rule.right.style.right = (canvasWidth - x - w) + "px";
|
|
1359
|
+
|
|
1360
|
+
x += columns[i].width;
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
function setSortColumn(columnId, ascending) {
|
|
1365
|
+
setSortColumns([{ columnId: columnId, sortAsc: ascending}]);
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
function setSortColumns(cols) {
|
|
1369
|
+
sortColumns = cols;
|
|
1370
|
+
var numberCols = options.numberedMultiColumnSort && sortColumns.length > 1;
|
|
1371
|
+
var headerColumnEls = $headers.children();
|
|
1372
|
+
var sortIndicatorEl = headerColumnEls
|
|
1373
|
+
.removeClass("slick-header-column-sorted")
|
|
1374
|
+
.find("." + sortIndicatorCssClass)
|
|
1375
|
+
.removeClass("slick-sort-indicator-asc slick-sort-indicator-desc");
|
|
1376
|
+
sortIndicatorEl.text('');
|
|
1377
|
+
|
|
1378
|
+
$.each(sortColumns, function(i, col) {
|
|
1379
|
+
if (col.sortAsc == null) {
|
|
1380
|
+
col.sortAsc = true;
|
|
1381
|
+
}
|
|
1382
|
+
var columnIndex = getColumnIndex(col.columnId);
|
|
1383
|
+
if (columnIndex != null) {
|
|
1384
|
+
sortIndicatorEl = headerColumnEls.eq(columnIndex)
|
|
1385
|
+
.addClass("slick-header-column-sorted")
|
|
1386
|
+
.find("." + sortIndicatorCssClass)
|
|
1387
|
+
.addClass(col.sortAsc ? "slick-sort-indicator-asc" : "slick-sort-indicator-desc");
|
|
1388
|
+
if (numberCols) { sortIndicatorEl.text(i+1); }
|
|
1389
|
+
}
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
function getSortColumns() {
|
|
1394
|
+
return sortColumns;
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
function handleSelectedRangesChanged(e, ranges) {
|
|
1398
|
+
selectedRows = [];
|
|
1399
|
+
var hash = {};
|
|
1400
|
+
for (var i = 0; i < ranges.length; i++) {
|
|
1401
|
+
for (var j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
|
|
1402
|
+
if (!hash[j]) { // prevent duplicates
|
|
1403
|
+
selectedRows.push(j);
|
|
1404
|
+
hash[j] = {};
|
|
1405
|
+
}
|
|
1406
|
+
for (var k = ranges[i].fromCell; k <= ranges[i].toCell; k++) {
|
|
1407
|
+
if (canCellBeSelected(j, k)) {
|
|
1408
|
+
hash[j][columns[k].id] = options.selectedCellCssClass;
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
setCellCssStyles(options.selectedCellCssClass, hash);
|
|
1415
|
+
|
|
1416
|
+
trigger(self.onSelectedRowsChanged, {rows: getSelectedRows(), grid: self}, e);
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1419
|
+
function getColumns() {
|
|
1420
|
+
return columns;
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
function updateColumnCaches() {
|
|
1424
|
+
// Pre-calculate cell boundaries.
|
|
1425
|
+
columnPosLeft = [];
|
|
1426
|
+
columnPosRight = [];
|
|
1427
|
+
var x = 0;
|
|
1428
|
+
for (var i = 0, ii = columns.length; i < ii; i++) {
|
|
1429
|
+
columnPosLeft[i] = x;
|
|
1430
|
+
columnPosRight[i] = x + columns[i].width;
|
|
1431
|
+
x += columns[i].width;
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
function setColumns(columnDefinitions) {
|
|
1436
|
+
columns = columnDefinitions;
|
|
1437
|
+
|
|
1438
|
+
columnsById = {};
|
|
1439
|
+
for (var i = 0; i < columns.length; i++) {
|
|
1440
|
+
var m = columns[i] = $.extend({}, columnDefaults, columns[i]);
|
|
1441
|
+
columnsById[m.id] = i;
|
|
1442
|
+
if (m.minWidth && m.width < m.minWidth) {
|
|
1443
|
+
m.width = m.minWidth;
|
|
1444
|
+
}
|
|
1445
|
+
if (m.maxWidth && m.width > m.maxWidth) {
|
|
1446
|
+
m.width = m.maxWidth;
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
updateColumnCaches();
|
|
1451
|
+
|
|
1452
|
+
if (initialized) {
|
|
1453
|
+
invalidateAllRows();
|
|
1454
|
+
createColumnHeaders();
|
|
1455
|
+
removeCssRules();
|
|
1456
|
+
createCssRules();
|
|
1457
|
+
resizeCanvas();
|
|
1458
|
+
applyColumnWidths();
|
|
1459
|
+
handleScroll();
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
function getOptions() {
|
|
1464
|
+
return options;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
function setOptions(args, suppressRender) {
|
|
1468
|
+
if (!getEditorLock().commitCurrentEdit()) {
|
|
1469
|
+
return;
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
makeActiveCellNormal();
|
|
1473
|
+
|
|
1474
|
+
if (options.enableAddRow !== args.enableAddRow) {
|
|
1475
|
+
invalidateRow(getDataLength());
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
options = $.extend(options, args);
|
|
1479
|
+
validateAndEnforceOptions();
|
|
1480
|
+
|
|
1481
|
+
$viewport.css("overflow-y", options.autoHeight ? "hidden" : "auto");
|
|
1482
|
+
if (!suppressRender) { render(); }
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
function validateAndEnforceOptions() {
|
|
1486
|
+
if (options.autoHeight) {
|
|
1487
|
+
options.leaveSpaceForNewRows = false;
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
function setData(newData, scrollToTop) {
|
|
1492
|
+
data = newData;
|
|
1493
|
+
invalidateAllRows();
|
|
1494
|
+
updateRowCount();
|
|
1495
|
+
if (scrollToTop) {
|
|
1496
|
+
scrollTo(0);
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
function getData() {
|
|
1501
|
+
return data;
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
function getDataLength() {
|
|
1505
|
+
if (data.getLength) {
|
|
1506
|
+
return data.getLength();
|
|
1507
|
+
} else {
|
|
1508
|
+
return data.length;
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
function getDataLengthIncludingAddNew() {
|
|
1513
|
+
return getDataLength() + (!options.enableAddRow ? 0
|
|
1514
|
+
: (!pagingActive || pagingIsLastPage ? 1 : 0)
|
|
1515
|
+
);
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
function getDataItem(i) {
|
|
1519
|
+
if (data.getItem) {
|
|
1520
|
+
return data.getItem(i);
|
|
1521
|
+
} else {
|
|
1522
|
+
return data[i];
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
function getTopPanel() {
|
|
1527
|
+
return $topPanel[0];
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
function setTopPanelVisibility(visible) {
|
|
1531
|
+
if (options.showTopPanel != visible) {
|
|
1532
|
+
options.showTopPanel = visible;
|
|
1533
|
+
if (visible) {
|
|
1534
|
+
$topPanelScroller.slideDown("fast", resizeCanvas);
|
|
1535
|
+
} else {
|
|
1536
|
+
$topPanelScroller.slideUp("fast", resizeCanvas);
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
function setHeaderRowVisibility(visible) {
|
|
1542
|
+
if (options.showHeaderRow != visible) {
|
|
1543
|
+
options.showHeaderRow = visible;
|
|
1544
|
+
if (visible) {
|
|
1545
|
+
$headerRowScroller.slideDown("fast", resizeCanvas);
|
|
1546
|
+
} else {
|
|
1547
|
+
$headerRowScroller.slideUp("fast", resizeCanvas);
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
function setFooterRowVisibility(visible) {
|
|
1553
|
+
if (options.showFooterRow != visible) {
|
|
1554
|
+
options.showFooterRow = visible;
|
|
1555
|
+
if (visible) {
|
|
1556
|
+
$footerRowScroller.slideDown("fast", resizeCanvas);
|
|
1557
|
+
} else {
|
|
1558
|
+
$footerRowScroller.slideUp("fast", resizeCanvas);
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
function setPreHeaderPanelVisibility(visible) {
|
|
1564
|
+
if (options.showPreHeaderPanel != visible) {
|
|
1565
|
+
options.showPreHeaderPanel = visible;
|
|
1566
|
+
if (visible) {
|
|
1567
|
+
$preHeaderPanelScroller.slideDown("fast", resizeCanvas);
|
|
1568
|
+
} else {
|
|
1569
|
+
$preHeaderPanelScroller.slideUp("fast", resizeCanvas);
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
function getContainerNode() {
|
|
1575
|
+
return $container.get(0);
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
1579
|
+
// Rendering / Scrolling
|
|
1580
|
+
|
|
1581
|
+
function getRowTop(row) {
|
|
1582
|
+
return options.rowHeight * row - offset;
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
function getRowFromPosition(y) {
|
|
1586
|
+
return Math.floor((y + offset) / options.rowHeight);
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
function scrollTo(y) {
|
|
1590
|
+
y = Math.max(y, 0);
|
|
1591
|
+
y = Math.min(y, th - viewportH + (viewportHasHScroll ? scrollbarDimensions.height : 0));
|
|
1592
|
+
|
|
1593
|
+
var oldOffset = offset;
|
|
1594
|
+
|
|
1595
|
+
page = Math.min(n - 1, Math.floor(y / ph));
|
|
1596
|
+
offset = Math.round(page * cj);
|
|
1597
|
+
var newScrollTop = y - offset;
|
|
1598
|
+
|
|
1599
|
+
if (offset != oldOffset) {
|
|
1600
|
+
var range = getVisibleRange(newScrollTop);
|
|
1601
|
+
cleanupRows(range);
|
|
1602
|
+
updateRowPositions();
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
if (prevScrollTop != newScrollTop) {
|
|
1606
|
+
vScrollDir = (prevScrollTop + oldOffset < newScrollTop + offset) ? 1 : -1;
|
|
1607
|
+
$viewport[0].scrollTop = (lastRenderedScrollTop = scrollTop = prevScrollTop = newScrollTop);
|
|
1608
|
+
|
|
1609
|
+
trigger(self.onViewportChanged, {grid: self});
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
function defaultFormatter(row, cell, value, columnDef, dataContext, grid) {
|
|
1614
|
+
if (value == null) {
|
|
1615
|
+
return "";
|
|
1616
|
+
} else {
|
|
1617
|
+
return (value + "").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
function getFormatter(row, column) {
|
|
1622
|
+
var rowMetadata = data.getItemMetadata && data.getItemMetadata(row);
|
|
1623
|
+
|
|
1624
|
+
// look up by id, then index
|
|
1625
|
+
var columnOverrides = rowMetadata &&
|
|
1626
|
+
rowMetadata.columns &&
|
|
1627
|
+
(rowMetadata.columns[column.id] || rowMetadata.columns[getColumnIndex(column.id)]);
|
|
1628
|
+
|
|
1629
|
+
return (columnOverrides && columnOverrides.formatter) ||
|
|
1630
|
+
(rowMetadata && rowMetadata.formatter) ||
|
|
1631
|
+
column.formatter ||
|
|
1632
|
+
(options.formatterFactory && options.formatterFactory.getFormatter(column)) ||
|
|
1633
|
+
options.defaultFormatter;
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
function getEditor(row, cell) {
|
|
1637
|
+
var column = columns[cell];
|
|
1638
|
+
var rowMetadata = data.getItemMetadata && data.getItemMetadata(row);
|
|
1639
|
+
var columnMetadata = rowMetadata && rowMetadata.columns;
|
|
1640
|
+
|
|
1641
|
+
if (columnMetadata && columnMetadata[column.id] && columnMetadata[column.id].editor !== undefined) {
|
|
1642
|
+
return columnMetadata[column.id].editor;
|
|
1643
|
+
}
|
|
1644
|
+
if (columnMetadata && columnMetadata[cell] && columnMetadata[cell].editor !== undefined) {
|
|
1645
|
+
return columnMetadata[cell].editor;
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1648
|
+
return column.editor || (options.editorFactory && options.editorFactory.getEditor(column));
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
function getDataItemValueForColumn(item, columnDef) {
|
|
1652
|
+
if (options.dataItemColumnValueExtractor) {
|
|
1653
|
+
return options.dataItemColumnValueExtractor(item, columnDef);
|
|
1654
|
+
}
|
|
1655
|
+
return item[columnDef.field];
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
function appendRowHtml(stringArray, row, range, dataLength) {
|
|
1659
|
+
var d = getDataItem(row);
|
|
1660
|
+
var dataLoading = row < dataLength && !d;
|
|
1661
|
+
var rowCss = "slick-row" +
|
|
1662
|
+
(dataLoading ? " loading" : "") +
|
|
1663
|
+
(row === activeRow ? " active" : "") +
|
|
1664
|
+
(row % 2 == 1 ? " odd" : " even");
|
|
1665
|
+
|
|
1666
|
+
if (!d) {
|
|
1667
|
+
rowCss += " " + options.addNewRowCssClass;
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
var metadata = data.getItemMetadata && data.getItemMetadata(row);
|
|
1671
|
+
|
|
1672
|
+
if (metadata && metadata.cssClasses) {
|
|
1673
|
+
rowCss += " " + metadata.cssClasses;
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
stringArray.push("<div class='ui-widget-content " + rowCss + "' style='top:" + getRowTop(row) + "px'>");
|
|
1677
|
+
|
|
1678
|
+
var colspan, m;
|
|
1679
|
+
for (var i = 0, ii = columns.length; i < ii; i++) {
|
|
1680
|
+
m = columns[i];
|
|
1681
|
+
colspan = 1;
|
|
1682
|
+
if (metadata && metadata.columns) {
|
|
1683
|
+
var columnData = metadata.columns[m.id] || metadata.columns[i];
|
|
1684
|
+
colspan = (columnData && columnData.colspan) || 1;
|
|
1685
|
+
if (colspan === "*") {
|
|
1686
|
+
colspan = ii - i;
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
// Do not render cells outside of the viewport.
|
|
1691
|
+
if (columnPosRight[Math.min(ii - 1, i + colspan - 1)] > range.leftPx) {
|
|
1692
|
+
if (columnPosLeft[i] > range.rightPx) {
|
|
1693
|
+
// All columns to the right are outside the range.
|
|
1694
|
+
break;
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
appendCellHtml(stringArray, row, i, colspan, d);
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
if (colspan > 1) {
|
|
1701
|
+
i += (colspan - 1);
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
stringArray.push("</div>");
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
function appendCellHtml(stringArray, row, cell, colspan, item) {
|
|
1709
|
+
// stringArray: stringBuilder containing the HTML parts
|
|
1710
|
+
// row, cell: row and column index
|
|
1711
|
+
// colspan: HTML colspan
|
|
1712
|
+
// item: grid data for row
|
|
1713
|
+
|
|
1714
|
+
var m = columns[cell];
|
|
1715
|
+
var cellCss = "slick-cell l" + cell + " r" + Math.min(columns.length - 1, cell + colspan - 1) +
|
|
1716
|
+
(m.cssClass ? " " + m.cssClass : "");
|
|
1717
|
+
if (row === activeRow && cell === activeCell) {
|
|
1718
|
+
cellCss += (" active");
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1721
|
+
// TODO: merge them together in the setter
|
|
1722
|
+
for (var key in cellCssClasses) {
|
|
1723
|
+
if (cellCssClasses[key][row] && cellCssClasses[key][row][m.id]) {
|
|
1724
|
+
cellCss += (" " + cellCssClasses[key][row][m.id]);
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
var value = null, formatterResult = '';
|
|
1729
|
+
if (item) {
|
|
1730
|
+
value = getDataItemValueForColumn(item, m);
|
|
1731
|
+
formatterResult = getFormatter(row, m)(row, cell, value, m, item, self);
|
|
1732
|
+
if (formatterResult === null || formatterResult === undefined) { formatterResult = ''; }
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
// get addl css class names from object type formatter return and from string type return of onBeforeAppendCell
|
|
1736
|
+
var addlCssClasses = trigger(self.onBeforeAppendCell, { row: row, cell: cell, grid: self, value: value, dataContext: item }) || '';
|
|
1737
|
+
addlCssClasses += (formatterResult.addClasses ? (addlCssClasses ? ' ' : '') + formatterResult.addClasses : '');
|
|
1738
|
+
|
|
1739
|
+
stringArray.push("<div class='" + cellCss + (addlCssClasses ? ' ' + addlCssClasses : '') + "'>");
|
|
1740
|
+
|
|
1741
|
+
// if there is a corresponding row (if not, this is the Add New row or this data hasn't been loaded yet)
|
|
1742
|
+
if (item) {
|
|
1743
|
+
stringArray.push(Object.prototype.toString.call(formatterResult) !== '[object Object]' ? formatterResult : formatterResult.text);
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
stringArray.push("</div>");
|
|
1747
|
+
|
|
1748
|
+
rowsCache[row].cellRenderQueue.push(cell);
|
|
1749
|
+
rowsCache[row].cellColSpans[cell] = colspan;
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
|
|
1753
|
+
function cleanupRows(rangeToKeep) {
|
|
1754
|
+
for (var i in rowsCache) {
|
|
1755
|
+
if (((i = parseInt(i, 10)) !== activeRow) && (i < rangeToKeep.top || i > rangeToKeep.bottom)) {
|
|
1756
|
+
removeRowFromCache(i);
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
if (options.enableAsyncPostRenderCleanup) { startPostProcessingCleanup(); }
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
function invalidate() {
|
|
1763
|
+
updateRowCount();
|
|
1764
|
+
invalidateAllRows();
|
|
1765
|
+
render();
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
function invalidateAllRows() {
|
|
1769
|
+
if (currentEditor) {
|
|
1770
|
+
makeActiveCellNormal();
|
|
1771
|
+
}
|
|
1772
|
+
for (var row in rowsCache) {
|
|
1773
|
+
removeRowFromCache(row);
|
|
1774
|
+
}
|
|
1775
|
+
if (options.enableAsyncPostRenderCleanup) { startPostProcessingCleanup(); }
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
function queuePostProcessedRowForCleanup(cacheEntry, postProcessedRow, rowIdx) {
|
|
1779
|
+
postProcessgroupId++;
|
|
1780
|
+
|
|
1781
|
+
// store and detach node for later async cleanup
|
|
1782
|
+
for (var columnIdx in postProcessedRow) {
|
|
1783
|
+
if (postProcessedRow.hasOwnProperty(columnIdx)) {
|
|
1784
|
+
postProcessedCleanupQueue.push({
|
|
1785
|
+
actionType: 'C',
|
|
1786
|
+
groupId: postProcessgroupId,
|
|
1787
|
+
node: cacheEntry.cellNodesByColumnIdx[ columnIdx | 0],
|
|
1788
|
+
columnIdx: columnIdx | 0,
|
|
1789
|
+
rowIdx: rowIdx
|
|
1790
|
+
});
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
postProcessedCleanupQueue.push({
|
|
1794
|
+
actionType: 'R',
|
|
1795
|
+
groupId: postProcessgroupId,
|
|
1796
|
+
node: cacheEntry.rowNode
|
|
1797
|
+
});
|
|
1798
|
+
$(cacheEntry.rowNode).detach();
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
function queuePostProcessedCellForCleanup(cellnode, columnIdx, rowIdx) {
|
|
1802
|
+
postProcessedCleanupQueue.push({
|
|
1803
|
+
actionType: 'C',
|
|
1804
|
+
groupId: postProcessgroupId,
|
|
1805
|
+
node: cellnode,
|
|
1806
|
+
columnIdx: columnIdx,
|
|
1807
|
+
rowIdx: rowIdx
|
|
1808
|
+
});
|
|
1809
|
+
$(cellnode).detach();
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
function removeRowFromCache(row) {
|
|
1813
|
+
var cacheEntry = rowsCache[row];
|
|
1814
|
+
if (!cacheEntry) {
|
|
1815
|
+
return;
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
if (cacheEntry.rowNode) {
|
|
1819
|
+
if (rowNodeFromLastMouseWheelEvent === cacheEntry.rowNode) {
|
|
1820
|
+
cacheEntry.rowNode.style.display = 'none';
|
|
1821
|
+
zombieRowNodeFromLastMouseWheelEvent = rowNodeFromLastMouseWheelEvent;
|
|
1822
|
+
zombieRowCacheFromLastMouseWheelEvent = cacheEntry;
|
|
1823
|
+
zombieRowPostProcessedFromLastMouseWheelEvent = postProcessedRows[row];
|
|
1824
|
+
// ignore post processing cleanup in this case - it will be dealt with later
|
|
1825
|
+
} else {
|
|
1826
|
+
if (options.enableAsyncPostRenderCleanup && postProcessedRows[row]) {
|
|
1827
|
+
queuePostProcessedRowForCleanup(cacheEntry, postProcessedRows[row], row);
|
|
1828
|
+
} else {
|
|
1829
|
+
$canvas[0].removeChild(cacheEntry.rowNode);
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1834
|
+
delete rowsCache[row];
|
|
1835
|
+
delete postProcessedRows[row];
|
|
1836
|
+
renderedRows--;
|
|
1837
|
+
counter_rows_removed++;
|
|
1838
|
+
}
|
|
1839
|
+
|
|
1840
|
+
function invalidateRows(rows) {
|
|
1841
|
+
var i, rl;
|
|
1842
|
+
if (!rows || !rows.length) {
|
|
1843
|
+
return;
|
|
1844
|
+
}
|
|
1845
|
+
vScrollDir = 0;
|
|
1846
|
+
rl = rows.length;
|
|
1847
|
+
for (i = 0; i < rl; i++) {
|
|
1848
|
+
if (currentEditor && activeRow === rows[i]) {
|
|
1849
|
+
makeActiveCellNormal();
|
|
1850
|
+
}
|
|
1851
|
+
if (rowsCache[rows[i]]) {
|
|
1852
|
+
removeRowFromCache(rows[i]);
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
if (options.enableAsyncPostRenderCleanup) { startPostProcessingCleanup(); }
|
|
1856
|
+
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1859
|
+
function invalidateRow(row) {
|
|
1860
|
+
invalidateRows([row]);
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1863
|
+
function applyFormatResultToCellNode(formatterResult, cellNode, suppressRemove) {
|
|
1864
|
+
if (Object.prototype.toString.call(formatterResult) !== '[object Object]') {
|
|
1865
|
+
cellNode.innerHTML = formatterResult;
|
|
1866
|
+
return;
|
|
1867
|
+
}
|
|
1868
|
+
cellNode.innerHTML = formatterResult.text;
|
|
1869
|
+
if (formatterResult.removeClasses && !suppressRemove) {
|
|
1870
|
+
$(cellNode).removeClass(formatterResult.removeClasses);
|
|
1871
|
+
}
|
|
1872
|
+
if (formatterResult.addClasses) {
|
|
1873
|
+
$(cellNode).addClass(formatterResult.addClasses);
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
function updateCell(row, cell) {
|
|
1878
|
+
var cellNode = getCellNode(row, cell);
|
|
1879
|
+
if (!cellNode) {
|
|
1880
|
+
return;
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1883
|
+
var m = columns[cell], d = getDataItem(row);
|
|
1884
|
+
if (currentEditor && activeRow === row && activeCell === cell) {
|
|
1885
|
+
currentEditor.loadValue(d);
|
|
1886
|
+
} else {
|
|
1887
|
+
var formatterResult = d ? getFormatter(row, m)(row, cell, getDataItemValueForColumn(d, m), m, d, self) : "";
|
|
1888
|
+
applyFormatResultToCellNode(formatterResult, cellNode);
|
|
1889
|
+
invalidatePostProcessingResults(row);
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
function updateRow(row) {
|
|
1894
|
+
var cacheEntry = rowsCache[row];
|
|
1895
|
+
if (!cacheEntry) {
|
|
1896
|
+
return;
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
ensureCellNodesInRowsCache(row);
|
|
1900
|
+
|
|
1901
|
+
var formatterResult, d = getDataItem(row);
|
|
1902
|
+
|
|
1903
|
+
for (var columnIdx in cacheEntry.cellNodesByColumnIdx) {
|
|
1904
|
+
if (!cacheEntry.cellNodesByColumnIdx.hasOwnProperty(columnIdx)) {
|
|
1905
|
+
continue;
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1908
|
+
columnIdx = columnIdx | 0;
|
|
1909
|
+
var m = columns[columnIdx],
|
|
1910
|
+
node = cacheEntry.cellNodesByColumnIdx[columnIdx];
|
|
1911
|
+
|
|
1912
|
+
if (row === activeRow && columnIdx === activeCell && currentEditor) {
|
|
1913
|
+
currentEditor.loadValue(d);
|
|
1914
|
+
} else if (d) {
|
|
1915
|
+
formatterResult = getFormatter(row, m)(row, columnIdx, getDataItemValueForColumn(d, m), m, d, self);
|
|
1916
|
+
applyFormatResultToCellNode(formatterResult, node);
|
|
1917
|
+
} else {
|
|
1918
|
+
node.innerHTML = "";
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
invalidatePostProcessingResults(row);
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
function getViewportHeight() {
|
|
1926
|
+
return parseFloat($.css($container[0], "height", true)) -
|
|
1927
|
+
parseFloat($.css($container[0], "paddingTop", true)) -
|
|
1928
|
+
parseFloat($.css($container[0], "paddingBottom", true)) -
|
|
1929
|
+
parseFloat($.css($headerScroller[0], "height")) - getVBoxDelta($headerScroller) -
|
|
1930
|
+
(options.showTopPanel ? options.topPanelHeight + getVBoxDelta($topPanelScroller) : 0) -
|
|
1931
|
+
(options.showHeaderRow ? options.headerRowHeight + getVBoxDelta($headerRowScroller) : 0) -
|
|
1932
|
+
(options.createFooterRow && options.showFooterRow ? options.footerRowHeight + getVBoxDelta($footerRowScroller) : 0) -
|
|
1933
|
+
(options.createPreHeaderPanel && options.showPreHeaderPanel ? options.preHeaderPanelHeight + getVBoxDelta($preHeaderPanelScroller) : 0);
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
function resizeCanvas() {
|
|
1937
|
+
if (!initialized) { return; }
|
|
1938
|
+
if (options.autoHeight) {
|
|
1939
|
+
viewportH = options.rowHeight * getDataLengthIncludingAddNew();
|
|
1940
|
+
} else {
|
|
1941
|
+
viewportH = getViewportHeight();
|
|
1942
|
+
}
|
|
1943
|
+
|
|
1944
|
+
numVisibleRows = Math.ceil(viewportH / options.rowHeight);
|
|
1945
|
+
viewportW = parseFloat($.css($container[0], "width", true));
|
|
1946
|
+
if (!options.autoHeight) {
|
|
1947
|
+
$viewport.height(viewportH);
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
if (!scrollbarDimensions || !scrollbarDimensions.width) {
|
|
1951
|
+
scrollbarDimensions = measureScrollbar();
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
if (options.forceFitColumns) {
|
|
1955
|
+
autosizeColumns();
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1958
|
+
updateRowCount();
|
|
1959
|
+
handleScroll();
|
|
1960
|
+
// Since the width has changed, force the render() to reevaluate virtually rendered cells.
|
|
1961
|
+
lastRenderedScrollLeft = -1;
|
|
1962
|
+
render();
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
function updatePagingStatusFromView( pagingInfo ) {
|
|
1966
|
+
pagingActive = (pagingInfo.pageSize !== 0);
|
|
1967
|
+
pagingIsLastPage = (pagingInfo.pageNum == pagingInfo.totalPages - 1);
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
function updateRowCount() {
|
|
1971
|
+
if (!initialized) { return; }
|
|
1972
|
+
|
|
1973
|
+
var dataLength = getDataLength();
|
|
1974
|
+
var dataLengthIncludingAddNew = getDataLengthIncludingAddNew();
|
|
1975
|
+
var numberOfRows = dataLengthIncludingAddNew +
|
|
1976
|
+
(options.leaveSpaceForNewRows ? numVisibleRows - 1 : 0);
|
|
1977
|
+
|
|
1978
|
+
var oldViewportHasVScroll = viewportHasVScroll;
|
|
1979
|
+
// with autoHeight, we do not need to accommodate the vertical scroll bar
|
|
1980
|
+
viewportHasVScroll = !options.autoHeight && (numberOfRows * options.rowHeight > viewportH);
|
|
1981
|
+
viewportHasHScroll = (canvasWidth > viewportW - scrollbarDimensions.width);
|
|
1982
|
+
|
|
1983
|
+
makeActiveCellNormal();
|
|
1984
|
+
|
|
1985
|
+
// remove the rows that are now outside of the data range
|
|
1986
|
+
// this helps avoid redundant calls to .removeRow() when the size of the data decreased by thousands of rows
|
|
1987
|
+
var r1 = dataLength - 1;
|
|
1988
|
+
for (var i in rowsCache) {
|
|
1989
|
+
if (i > r1) {
|
|
1990
|
+
removeRowFromCache(i);
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
if (options.enableAsyncPostRenderCleanup) { startPostProcessingCleanup(); }
|
|
1994
|
+
|
|
1995
|
+
if (activeCellNode && activeRow > r1) {
|
|
1996
|
+
resetActiveCell();
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
var oldH = h;
|
|
2000
|
+
th = Math.max(options.rowHeight * numberOfRows, viewportH - scrollbarDimensions.height);
|
|
2001
|
+
if (th < maxSupportedCssHeight) {
|
|
2002
|
+
// just one page
|
|
2003
|
+
h = ph = th;
|
|
2004
|
+
n = 1;
|
|
2005
|
+
cj = 0;
|
|
2006
|
+
} else {
|
|
2007
|
+
// break into pages
|
|
2008
|
+
h = maxSupportedCssHeight;
|
|
2009
|
+
ph = h / 100;
|
|
2010
|
+
n = Math.floor(th / ph);
|
|
2011
|
+
cj = (th - h) / (n - 1);
|
|
2012
|
+
}
|
|
2013
|
+
|
|
2014
|
+
if (h !== oldH) {
|
|
2015
|
+
$canvas.css("height", h);
|
|
2016
|
+
scrollTop = $viewport[0].scrollTop;
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
var oldScrollTopInRange = (scrollTop + offset <= th - viewportH);
|
|
2020
|
+
|
|
2021
|
+
if (th == 0 || scrollTop == 0) {
|
|
2022
|
+
page = offset = 0;
|
|
2023
|
+
} else if (oldScrollTopInRange) {
|
|
2024
|
+
// maintain virtual position
|
|
2025
|
+
scrollTo(scrollTop + offset);
|
|
2026
|
+
} else {
|
|
2027
|
+
// scroll to bottom
|
|
2028
|
+
scrollTo(th - viewportH);
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
if (h != oldH && options.autoHeight) {
|
|
2032
|
+
resizeCanvas();
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2035
|
+
if (options.forceFitColumns && oldViewportHasVScroll != viewportHasVScroll) {
|
|
2036
|
+
autosizeColumns();
|
|
2037
|
+
}
|
|
2038
|
+
updateCanvasWidth(false);
|
|
2039
|
+
}
|
|
2040
|
+
|
|
2041
|
+
function getVisibleRange(viewportTop, viewportLeft) {
|
|
2042
|
+
if (viewportTop == null) {
|
|
2043
|
+
viewportTop = scrollTop;
|
|
2044
|
+
}
|
|
2045
|
+
if (viewportLeft == null) {
|
|
2046
|
+
viewportLeft = scrollLeft;
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
return {
|
|
2050
|
+
top: getRowFromPosition(viewportTop),
|
|
2051
|
+
bottom: getRowFromPosition(viewportTop + viewportH) + 1,
|
|
2052
|
+
leftPx: viewportLeft,
|
|
2053
|
+
rightPx: viewportLeft + viewportW
|
|
2054
|
+
};
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
function getRenderedRange(viewportTop, viewportLeft) {
|
|
2058
|
+
var range = getVisibleRange(viewportTop, viewportLeft);
|
|
2059
|
+
var buffer = Math.round(viewportH / options.rowHeight);
|
|
2060
|
+
var minBuffer = options.minRowBuffer;
|
|
2061
|
+
|
|
2062
|
+
if (vScrollDir == -1) {
|
|
2063
|
+
range.top -= buffer;
|
|
2064
|
+
range.bottom += minBuffer;
|
|
2065
|
+
} else if (vScrollDir == 1) {
|
|
2066
|
+
range.top -= minBuffer;
|
|
2067
|
+
range.bottom += buffer;
|
|
2068
|
+
} else {
|
|
2069
|
+
range.top -= minBuffer;
|
|
2070
|
+
range.bottom += minBuffer;
|
|
2071
|
+
}
|
|
2072
|
+
|
|
2073
|
+
range.top = Math.max(0, range.top);
|
|
2074
|
+
range.bottom = Math.min(getDataLengthIncludingAddNew() - 1, range.bottom);
|
|
2075
|
+
|
|
2076
|
+
range.leftPx -= viewportW;
|
|
2077
|
+
range.rightPx += viewportW;
|
|
2078
|
+
|
|
2079
|
+
range.leftPx = Math.max(0, range.leftPx);
|
|
2080
|
+
range.rightPx = Math.min(canvasWidth, range.rightPx);
|
|
2081
|
+
|
|
2082
|
+
return range;
|
|
2083
|
+
}
|
|
2084
|
+
|
|
2085
|
+
function ensureCellNodesInRowsCache(row) {
|
|
2086
|
+
var cacheEntry = rowsCache[row];
|
|
2087
|
+
if (cacheEntry) {
|
|
2088
|
+
if (cacheEntry.cellRenderQueue.length) {
|
|
2089
|
+
var lastChild = cacheEntry.rowNode.lastChild;
|
|
2090
|
+
while (cacheEntry.cellRenderQueue.length) {
|
|
2091
|
+
var columnIdx = cacheEntry.cellRenderQueue.pop();
|
|
2092
|
+
cacheEntry.cellNodesByColumnIdx[columnIdx] = lastChild;
|
|
2093
|
+
lastChild = lastChild.previousSibling;
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
|
|
2099
|
+
function cleanUpCells(range, row) {
|
|
2100
|
+
var totalCellsRemoved = 0;
|
|
2101
|
+
var cacheEntry = rowsCache[row];
|
|
2102
|
+
|
|
2103
|
+
// Remove cells outside the range.
|
|
2104
|
+
var cellsToRemove = [];
|
|
2105
|
+
for (var i in cacheEntry.cellNodesByColumnIdx) {
|
|
2106
|
+
// I really hate it when people mess with Array.prototype.
|
|
2107
|
+
if (!cacheEntry.cellNodesByColumnIdx.hasOwnProperty(i)) {
|
|
2108
|
+
continue;
|
|
2109
|
+
}
|
|
2110
|
+
|
|
2111
|
+
// This is a string, so it needs to be cast back to a number.
|
|
2112
|
+
i = i | 0;
|
|
2113
|
+
|
|
2114
|
+
var colspan = cacheEntry.cellColSpans[i];
|
|
2115
|
+
if (columnPosLeft[i] > range.rightPx ||
|
|
2116
|
+
columnPosRight[Math.min(columns.length - 1, i + colspan - 1)] < range.leftPx) {
|
|
2117
|
+
if (!(row == activeRow && i == activeCell)) {
|
|
2118
|
+
cellsToRemove.push(i);
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2122
|
+
|
|
2123
|
+
var cellToRemove, node;
|
|
2124
|
+
postProcessgroupId++;
|
|
2125
|
+
while ((cellToRemove = cellsToRemove.pop()) != null) {
|
|
2126
|
+
node = cacheEntry.cellNodesByColumnIdx[cellToRemove];
|
|
2127
|
+
if (options.enableAsyncPostRenderCleanup && postProcessedRows[row] && postProcessedRows[row][cellToRemove]) {
|
|
2128
|
+
queuePostProcessedCellForCleanup(node, cellToRemove, row);
|
|
2129
|
+
} else {
|
|
2130
|
+
cacheEntry.rowNode.removeChild(node);
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
delete cacheEntry.cellColSpans[cellToRemove];
|
|
2134
|
+
delete cacheEntry.cellNodesByColumnIdx[cellToRemove];
|
|
2135
|
+
if (postProcessedRows[row]) {
|
|
2136
|
+
delete postProcessedRows[row][cellToRemove];
|
|
2137
|
+
}
|
|
2138
|
+
totalCellsRemoved++;
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
function cleanUpAndRenderCells(range) {
|
|
2143
|
+
var cacheEntry;
|
|
2144
|
+
var stringArray = [];
|
|
2145
|
+
var processedRows = [];
|
|
2146
|
+
var cellsAdded;
|
|
2147
|
+
var totalCellsAdded = 0;
|
|
2148
|
+
var colspan;
|
|
2149
|
+
|
|
2150
|
+
for (var row = range.top, btm = range.bottom; row <= btm; row++) {
|
|
2151
|
+
cacheEntry = rowsCache[row];
|
|
2152
|
+
if (!cacheEntry) {
|
|
2153
|
+
continue;
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
// cellRenderQueue populated in renderRows() needs to be cleared first
|
|
2157
|
+
ensureCellNodesInRowsCache(row);
|
|
2158
|
+
|
|
2159
|
+
cleanUpCells(range, row);
|
|
2160
|
+
|
|
2161
|
+
// Render missing cells.
|
|
2162
|
+
cellsAdded = 0;
|
|
2163
|
+
|
|
2164
|
+
var metadata = data.getItemMetadata && data.getItemMetadata(row);
|
|
2165
|
+
metadata = metadata && metadata.columns;
|
|
2166
|
+
|
|
2167
|
+
var d = getDataItem(row);
|
|
2168
|
+
|
|
2169
|
+
// TODO: shorten this loop (index? heuristics? binary search?)
|
|
2170
|
+
for (var i = 0, ii = columns.length; i < ii; i++) {
|
|
2171
|
+
// Cells to the right are outside the range.
|
|
2172
|
+
if (columnPosLeft[i] > range.rightPx) {
|
|
2173
|
+
break;
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
// Already rendered.
|
|
2177
|
+
if ((colspan = cacheEntry.cellColSpans[i]) != null) {
|
|
2178
|
+
i += (colspan > 1 ? colspan - 1 : 0);
|
|
2179
|
+
continue;
|
|
2180
|
+
}
|
|
2181
|
+
|
|
2182
|
+
colspan = 1;
|
|
2183
|
+
if (metadata) {
|
|
2184
|
+
var columnData = metadata[columns[i].id] || metadata[i];
|
|
2185
|
+
colspan = (columnData && columnData.colspan) || 1;
|
|
2186
|
+
if (colspan === "*") {
|
|
2187
|
+
colspan = ii - i;
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
|
|
2191
|
+
if (columnPosRight[Math.min(ii - 1, i + colspan - 1)] > range.leftPx) {
|
|
2192
|
+
appendCellHtml(stringArray, row, i, colspan, d);
|
|
2193
|
+
cellsAdded++;
|
|
2194
|
+
}
|
|
2195
|
+
|
|
2196
|
+
i += (colspan > 1 ? colspan - 1 : 0);
|
|
2197
|
+
}
|
|
2198
|
+
|
|
2199
|
+
if (cellsAdded) {
|
|
2200
|
+
totalCellsAdded += cellsAdded;
|
|
2201
|
+
processedRows.push(row);
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
if (!stringArray.length) {
|
|
2206
|
+
return;
|
|
2207
|
+
}
|
|
2208
|
+
|
|
2209
|
+
var x = document.createElement("div");
|
|
2210
|
+
x.innerHTML = stringArray.join("");
|
|
2211
|
+
|
|
2212
|
+
var processedRow;
|
|
2213
|
+
var node;
|
|
2214
|
+
while ((processedRow = processedRows.pop()) != null) {
|
|
2215
|
+
cacheEntry = rowsCache[processedRow];
|
|
2216
|
+
var columnIdx;
|
|
2217
|
+
while ((columnIdx = cacheEntry.cellRenderQueue.pop()) != null) {
|
|
2218
|
+
node = x.lastChild;
|
|
2219
|
+
cacheEntry.rowNode.appendChild(node);
|
|
2220
|
+
cacheEntry.cellNodesByColumnIdx[columnIdx] = node;
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2225
|
+
function renderRows(range) {
|
|
2226
|
+
var parentNode = $canvas[0],
|
|
2227
|
+
stringArray = [],
|
|
2228
|
+
rows = [],
|
|
2229
|
+
needToReselectCell = false,
|
|
2230
|
+
dataLength = getDataLength();
|
|
2231
|
+
|
|
2232
|
+
for (var i = range.top, ii = range.bottom; i <= ii; i++) {
|
|
2233
|
+
if (rowsCache[i]) {
|
|
2234
|
+
continue;
|
|
2235
|
+
}
|
|
2236
|
+
renderedRows++;
|
|
2237
|
+
rows.push(i);
|
|
2238
|
+
|
|
2239
|
+
// Create an entry right away so that appendRowHtml() can
|
|
2240
|
+
// start populatating it.
|
|
2241
|
+
rowsCache[i] = {
|
|
2242
|
+
"rowNode": null,
|
|
2243
|
+
|
|
2244
|
+
// ColSpans of rendered cells (by column idx).
|
|
2245
|
+
// Can also be used for checking whether a cell has been rendered.
|
|
2246
|
+
"cellColSpans": [],
|
|
2247
|
+
|
|
2248
|
+
// Cell nodes (by column idx). Lazy-populated by ensureCellNodesInRowsCache().
|
|
2249
|
+
"cellNodesByColumnIdx": [],
|
|
2250
|
+
|
|
2251
|
+
// Column indices of cell nodes that have been rendered, but not yet indexed in
|
|
2252
|
+
// cellNodesByColumnIdx. These are in the same order as cell nodes added at the
|
|
2253
|
+
// end of the row.
|
|
2254
|
+
"cellRenderQueue": []
|
|
2255
|
+
};
|
|
2256
|
+
|
|
2257
|
+
appendRowHtml(stringArray, i, range, dataLength);
|
|
2258
|
+
if (activeCellNode && activeRow === i) {
|
|
2259
|
+
needToReselectCell = true;
|
|
2260
|
+
}
|
|
2261
|
+
counter_rows_rendered++;
|
|
2262
|
+
}
|
|
2263
|
+
|
|
2264
|
+
if (!rows.length) { return; }
|
|
2265
|
+
|
|
2266
|
+
var x = document.createElement("div");
|
|
2267
|
+
x.innerHTML = stringArray.join("");
|
|
2268
|
+
|
|
2269
|
+
for (var i = 0, ii = rows.length; i < ii; i++) {
|
|
2270
|
+
rowsCache[rows[i]].rowNode = parentNode.appendChild(x.firstChild);
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
if (needToReselectCell) {
|
|
2274
|
+
activeCellNode = getCellNode(activeRow, activeCell);
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
|
|
2278
|
+
function startPostProcessing() {
|
|
2279
|
+
if (!options.enableAsyncPostRender) {
|
|
2280
|
+
return;
|
|
2281
|
+
}
|
|
2282
|
+
clearTimeout(h_postrender);
|
|
2283
|
+
h_postrender = setTimeout(asyncPostProcessRows, options.asyncPostRenderDelay);
|
|
2284
|
+
}
|
|
2285
|
+
|
|
2286
|
+
function startPostProcessingCleanup() {
|
|
2287
|
+
if (!options.enableAsyncPostRenderCleanup) {
|
|
2288
|
+
return;
|
|
2289
|
+
}
|
|
2290
|
+
clearTimeout(h_postrenderCleanup);
|
|
2291
|
+
h_postrenderCleanup = setTimeout(asyncPostProcessCleanupRows, options.asyncPostRenderCleanupDelay);
|
|
2292
|
+
}
|
|
2293
|
+
|
|
2294
|
+
function invalidatePostProcessingResults(row) {
|
|
2295
|
+
// change status of columns to be re-rendered
|
|
2296
|
+
for (var columnIdx in postProcessedRows[row]) {
|
|
2297
|
+
if (postProcessedRows[row].hasOwnProperty(columnIdx)) {
|
|
2298
|
+
postProcessedRows[row][columnIdx] = 'C';
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
postProcessFromRow = Math.min(postProcessFromRow, row);
|
|
2302
|
+
postProcessToRow = Math.max(postProcessToRow, row);
|
|
2303
|
+
startPostProcessing();
|
|
2304
|
+
}
|
|
2305
|
+
|
|
2306
|
+
function updateRowPositions() {
|
|
2307
|
+
for (var row in rowsCache) {
|
|
2308
|
+
rowsCache[row].rowNode.style.top = getRowTop(row) + "px";
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
|
|
2312
|
+
function render() {
|
|
2313
|
+
if (!initialized) { return; }
|
|
2314
|
+
var visible = getVisibleRange();
|
|
2315
|
+
var rendered = getRenderedRange();
|
|
2316
|
+
|
|
2317
|
+
// remove rows no longer in the viewport
|
|
2318
|
+
cleanupRows(rendered);
|
|
2319
|
+
|
|
2320
|
+
// add new rows & missing cells in existing rows
|
|
2321
|
+
if (lastRenderedScrollLeft != scrollLeft) {
|
|
2322
|
+
cleanUpAndRenderCells(rendered);
|
|
2323
|
+
}
|
|
2324
|
+
|
|
2325
|
+
// render missing rows
|
|
2326
|
+
renderRows(rendered);
|
|
2327
|
+
|
|
2328
|
+
postProcessFromRow = visible.top;
|
|
2329
|
+
postProcessToRow = Math.min(getDataLengthIncludingAddNew() - 1, visible.bottom);
|
|
2330
|
+
startPostProcessing();
|
|
2331
|
+
|
|
2332
|
+
lastRenderedScrollTop = scrollTop;
|
|
2333
|
+
lastRenderedScrollLeft = scrollLeft;
|
|
2334
|
+
h_render = null;
|
|
2335
|
+
}
|
|
2336
|
+
|
|
2337
|
+
function handleHeaderScroll() {
|
|
2338
|
+
handleElementScroll($headerScroller[0]);
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2341
|
+
function handleHeaderRowScroll() {
|
|
2342
|
+
handleElementScroll($headerRowScroller[0]);
|
|
2343
|
+
}
|
|
2344
|
+
|
|
2345
|
+
function handleFooterRowScroll() {
|
|
2346
|
+
handleElementScroll($footerRowScroller[0]);
|
|
2347
|
+
}
|
|
2348
|
+
|
|
2349
|
+
function handlePreHeaderPanelScroll() {
|
|
2350
|
+
handleElementScroll($preHeaderPanelScroller[0]);
|
|
2351
|
+
}
|
|
2352
|
+
|
|
2353
|
+
function handleElementScroll(element) {
|
|
2354
|
+
var scrollLeft = element.scrollLeft;
|
|
2355
|
+
if (scrollLeft != $viewport[0].scrollLeft) {
|
|
2356
|
+
$viewport[0].scrollLeft = scrollLeft;
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2359
|
+
|
|
2360
|
+
function handleScroll() {
|
|
2361
|
+
scrollTop = $viewport[0].scrollTop;
|
|
2362
|
+
scrollLeft = $viewport[0].scrollLeft;
|
|
2363
|
+
var vScrollDist = Math.abs(scrollTop - prevScrollTop);
|
|
2364
|
+
var hScrollDist = Math.abs(scrollLeft - prevScrollLeft);
|
|
2365
|
+
|
|
2366
|
+
if (hScrollDist) {
|
|
2367
|
+
prevScrollLeft = scrollLeft;
|
|
2368
|
+
$headerScroller[0].scrollLeft = scrollLeft;
|
|
2369
|
+
$topPanelScroller[0].scrollLeft = scrollLeft;
|
|
2370
|
+
$headerRowScroller[0].scrollLeft = scrollLeft;
|
|
2371
|
+
if (options.createFooterRow) {
|
|
2372
|
+
$footerRowScroller[0].scrollLeft = scrollLeft;
|
|
2373
|
+
}
|
|
2374
|
+
if (options.createPreHeaderPanel) {
|
|
2375
|
+
$preHeaderPanelScroller[0].scrollLeft = scrollLeft;
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
|
|
2379
|
+
if (vScrollDist) {
|
|
2380
|
+
vScrollDir = prevScrollTop < scrollTop ? 1 : -1;
|
|
2381
|
+
prevScrollTop = scrollTop;
|
|
2382
|
+
|
|
2383
|
+
// switch virtual pages if needed
|
|
2384
|
+
if (vScrollDist < viewportH) {
|
|
2385
|
+
scrollTo(scrollTop + offset);
|
|
2386
|
+
} else {
|
|
2387
|
+
var oldOffset = offset;
|
|
2388
|
+
if (h == viewportH) {
|
|
2389
|
+
page = 0;
|
|
2390
|
+
} else {
|
|
2391
|
+
page = Math.min(n - 1, Math.floor(scrollTop * ((th - viewportH) / (h - viewportH)) * (1 / ph)));
|
|
2392
|
+
}
|
|
2393
|
+
offset = Math.round(page * cj);
|
|
2394
|
+
if (oldOffset != offset) {
|
|
2395
|
+
invalidateAllRows();
|
|
2396
|
+
}
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2399
|
+
|
|
2400
|
+
if (hScrollDist || vScrollDist) {
|
|
2401
|
+
if (h_render) {
|
|
2402
|
+
clearTimeout(h_render);
|
|
2403
|
+
}
|
|
2404
|
+
|
|
2405
|
+
if (Math.abs(lastRenderedScrollTop - scrollTop) > 20 ||
|
|
2406
|
+
Math.abs(lastRenderedScrollLeft - scrollLeft) > 20) {
|
|
2407
|
+
if (options.forceSyncScrolling || (
|
|
2408
|
+
Math.abs(lastRenderedScrollTop - scrollTop) < viewportH &&
|
|
2409
|
+
Math.abs(lastRenderedScrollLeft - scrollLeft) < viewportW)) {
|
|
2410
|
+
render();
|
|
2411
|
+
} else {
|
|
2412
|
+
h_render = setTimeout(render, 50);
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
trigger(self.onViewportChanged, {grid: self});
|
|
2416
|
+
}
|
|
2417
|
+
}
|
|
2418
|
+
|
|
2419
|
+
trigger(self.onScroll, {scrollLeft: scrollLeft, scrollTop: scrollTop, grid: self});
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2422
|
+
function asyncPostProcessRows() {
|
|
2423
|
+
var dataLength = getDataLength();
|
|
2424
|
+
while (postProcessFromRow <= postProcessToRow) {
|
|
2425
|
+
var row = (vScrollDir >= 0) ? postProcessFromRow++ : postProcessToRow--;
|
|
2426
|
+
var cacheEntry = rowsCache[row];
|
|
2427
|
+
if (!cacheEntry || row >= dataLength) {
|
|
2428
|
+
continue;
|
|
2429
|
+
}
|
|
2430
|
+
|
|
2431
|
+
if (!postProcessedRows[row]) {
|
|
2432
|
+
postProcessedRows[row] = {};
|
|
2433
|
+
}
|
|
2434
|
+
|
|
2435
|
+
ensureCellNodesInRowsCache(row);
|
|
2436
|
+
for (var columnIdx in cacheEntry.cellNodesByColumnIdx) {
|
|
2437
|
+
if (!cacheEntry.cellNodesByColumnIdx.hasOwnProperty(columnIdx)) {
|
|
2438
|
+
continue;
|
|
2439
|
+
}
|
|
2440
|
+
|
|
2441
|
+
columnIdx = columnIdx | 0;
|
|
2442
|
+
|
|
2443
|
+
var m = columns[columnIdx];
|
|
2444
|
+
var processedStatus = postProcessedRows[row][columnIdx]; // C=cleanup and re-render, R=rendered
|
|
2445
|
+
if (m.asyncPostRender && processedStatus !== 'R') {
|
|
2446
|
+
var node = cacheEntry.cellNodesByColumnIdx[columnIdx];
|
|
2447
|
+
if (node) {
|
|
2448
|
+
m.asyncPostRender(node, row, getDataItem(row), m, (processedStatus === 'C'));
|
|
2449
|
+
}
|
|
2450
|
+
postProcessedRows[row][columnIdx] = 'R';
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
|
|
2454
|
+
h_postrender = setTimeout(asyncPostProcessRows, options.asyncPostRenderDelay);
|
|
2455
|
+
return;
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
|
|
2459
|
+
function asyncPostProcessCleanupRows() {
|
|
2460
|
+
if (postProcessedCleanupQueue.length > 0) {
|
|
2461
|
+
var groupId = postProcessedCleanupQueue[0].groupId;
|
|
2462
|
+
|
|
2463
|
+
// loop through all queue members with this groupID
|
|
2464
|
+
while (postProcessedCleanupQueue.length > 0 && postProcessedCleanupQueue[0].groupId == groupId) {
|
|
2465
|
+
var entry = postProcessedCleanupQueue.shift();
|
|
2466
|
+
if (entry.actionType == 'R') {
|
|
2467
|
+
$(entry.node).remove();
|
|
2468
|
+
}
|
|
2469
|
+
if (entry.actionType == 'C') {
|
|
2470
|
+
var column = columns[entry.columnIdx];
|
|
2471
|
+
if (column.asyncPostRenderCleanup && entry.node) {
|
|
2472
|
+
// cleanup must also remove element
|
|
2473
|
+
column.asyncPostRenderCleanup(entry.node, entry.rowIdx, column);
|
|
2474
|
+
}
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
2477
|
+
|
|
2478
|
+
// call this function again after the specified delay
|
|
2479
|
+
h_postrenderCleanup = setTimeout(asyncPostProcessCleanupRows, options.asyncPostRenderCleanupDelay);
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
|
|
2483
|
+
function updateCellCssStylesOnRenderedRows(addedHash, removedHash) {
|
|
2484
|
+
var node, columnId, addedRowHash, removedRowHash;
|
|
2485
|
+
for (var row in rowsCache) {
|
|
2486
|
+
removedRowHash = removedHash && removedHash[row];
|
|
2487
|
+
addedRowHash = addedHash && addedHash[row];
|
|
2488
|
+
|
|
2489
|
+
if (removedRowHash) {
|
|
2490
|
+
for (columnId in removedRowHash) {
|
|
2491
|
+
if (!addedRowHash || removedRowHash[columnId] != addedRowHash[columnId]) {
|
|
2492
|
+
node = getCellNode(row, getColumnIndex(columnId));
|
|
2493
|
+
if (node) {
|
|
2494
|
+
$(node).removeClass(removedRowHash[columnId]);
|
|
2495
|
+
}
|
|
2496
|
+
}
|
|
2497
|
+
}
|
|
2498
|
+
}
|
|
2499
|
+
|
|
2500
|
+
if (addedRowHash) {
|
|
2501
|
+
for (columnId in addedRowHash) {
|
|
2502
|
+
if (!removedRowHash || removedRowHash[columnId] != addedRowHash[columnId]) {
|
|
2503
|
+
node = getCellNode(row, getColumnIndex(columnId));
|
|
2504
|
+
if (node) {
|
|
2505
|
+
$(node).addClass(addedRowHash[columnId]);
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
}
|
|
2511
|
+
}
|
|
2512
|
+
|
|
2513
|
+
function addCellCssStyles(key, hash) {
|
|
2514
|
+
if (cellCssClasses[key]) {
|
|
2515
|
+
throw new Error("addCellCssStyles: cell CSS hash with key '" + key + "' already exists.");
|
|
2516
|
+
}
|
|
2517
|
+
|
|
2518
|
+
cellCssClasses[key] = hash;
|
|
2519
|
+
updateCellCssStylesOnRenderedRows(hash, null);
|
|
2520
|
+
|
|
2521
|
+
trigger(self.onCellCssStylesChanged, { "key": key, "hash": hash, "grid": self });
|
|
2522
|
+
}
|
|
2523
|
+
|
|
2524
|
+
function removeCellCssStyles(key) {
|
|
2525
|
+
if (!cellCssClasses[key]) {
|
|
2526
|
+
return;
|
|
2527
|
+
}
|
|
2528
|
+
|
|
2529
|
+
updateCellCssStylesOnRenderedRows(null, cellCssClasses[key]);
|
|
2530
|
+
delete cellCssClasses[key];
|
|
2531
|
+
|
|
2532
|
+
trigger(self.onCellCssStylesChanged, { "key": key, "hash": null, "grid": self });
|
|
2533
|
+
}
|
|
2534
|
+
|
|
2535
|
+
function setCellCssStyles(key, hash) {
|
|
2536
|
+
var prevHash = cellCssClasses[key];
|
|
2537
|
+
|
|
2538
|
+
cellCssClasses[key] = hash;
|
|
2539
|
+
updateCellCssStylesOnRenderedRows(hash, prevHash);
|
|
2540
|
+
|
|
2541
|
+
trigger(self.onCellCssStylesChanged, { "key": key, "hash": hash, "grid": self });
|
|
2542
|
+
}
|
|
2543
|
+
|
|
2544
|
+
function getCellCssStyles(key) {
|
|
2545
|
+
return cellCssClasses[key];
|
|
2546
|
+
}
|
|
2547
|
+
|
|
2548
|
+
function flashCell(row, cell, speed) {
|
|
2549
|
+
speed = speed || 100;
|
|
2550
|
+
if (rowsCache[row]) {
|
|
2551
|
+
var $cell = $(getCellNode(row, cell));
|
|
2552
|
+
|
|
2553
|
+
function toggleCellClass(times) {
|
|
2554
|
+
if (!times) {
|
|
2555
|
+
return;
|
|
2556
|
+
}
|
|
2557
|
+
setTimeout(function () {
|
|
2558
|
+
$cell.queue(function () {
|
|
2559
|
+
$cell.toggleClass(options.cellFlashingCssClass).dequeue();
|
|
2560
|
+
toggleCellClass(times - 1);
|
|
2561
|
+
});
|
|
2562
|
+
},
|
|
2563
|
+
speed);
|
|
2564
|
+
}
|
|
2565
|
+
|
|
2566
|
+
toggleCellClass(4);
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
|
|
2570
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
2571
|
+
// Interactivity
|
|
2572
|
+
|
|
2573
|
+
function handleMouseWheel(e) {
|
|
2574
|
+
var rowNode = $(e.target).closest(".slick-row")[0];
|
|
2575
|
+
if (rowNode != rowNodeFromLastMouseWheelEvent) {
|
|
2576
|
+
if (zombieRowNodeFromLastMouseWheelEvent && zombieRowNodeFromLastMouseWheelEvent != rowNode) {
|
|
2577
|
+
if (options.enableAsyncPostRenderCleanup && zombieRowPostProcessedFromLastMouseWheelEvent) {
|
|
2578
|
+
queuePostProcessedRowForCleanup(zombieRowCacheFromLastMouseWheelEvent,
|
|
2579
|
+
zombieRowPostProcessedFromLastMouseWheelEvent);
|
|
2580
|
+
} else {
|
|
2581
|
+
$canvas[0].removeChild(zombieRowNodeFromLastMouseWheelEvent);
|
|
2582
|
+
}
|
|
2583
|
+
zombieRowNodeFromLastMouseWheelEvent = null;
|
|
2584
|
+
zombieRowCacheFromLastMouseWheelEvent = null;
|
|
2585
|
+
zombieRowPostProcessedFromLastMouseWheelEvent = null;
|
|
2586
|
+
|
|
2587
|
+
if (options.enableAsyncPostRenderCleanup) { startPostProcessingCleanup(); }
|
|
2588
|
+
}
|
|
2589
|
+
rowNodeFromLastMouseWheelEvent = rowNode;
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
|
|
2593
|
+
function handleDragInit(e, dd) {
|
|
2594
|
+
var cell = getCellFromEvent(e);
|
|
2595
|
+
if (!cell || !cellExists(cell.row, cell.cell)) {
|
|
2596
|
+
return false;
|
|
2597
|
+
}
|
|
2598
|
+
|
|
2599
|
+
var retval = trigger(self.onDragInit, dd, e);
|
|
2600
|
+
if (e.isImmediatePropagationStopped()) {
|
|
2601
|
+
return retval;
|
|
2602
|
+
}
|
|
2603
|
+
|
|
2604
|
+
// if nobody claims to be handling drag'n'drop by stopping immediate propagation,
|
|
2605
|
+
// cancel out of it
|
|
2606
|
+
return false;
|
|
2607
|
+
}
|
|
2608
|
+
|
|
2609
|
+
function handleDragStart(e, dd) {
|
|
2610
|
+
var cell = getCellFromEvent(e);
|
|
2611
|
+
if (!cell || !cellExists(cell.row, cell.cell)) {
|
|
2612
|
+
return false;
|
|
2613
|
+
}
|
|
2614
|
+
|
|
2615
|
+
var retval = trigger(self.onDragStart, dd, e);
|
|
2616
|
+
if (e.isImmediatePropagationStopped()) {
|
|
2617
|
+
return retval;
|
|
2618
|
+
}
|
|
2619
|
+
|
|
2620
|
+
return false;
|
|
2621
|
+
}
|
|
2622
|
+
|
|
2623
|
+
function handleDrag(e, dd) {
|
|
2624
|
+
return trigger(self.onDrag, dd, e);
|
|
2625
|
+
}
|
|
2626
|
+
|
|
2627
|
+
function handleDragEnd(e, dd) {
|
|
2628
|
+
trigger(self.onDragEnd, dd, e);
|
|
2629
|
+
}
|
|
2630
|
+
|
|
2631
|
+
function handleKeyDown(e) {
|
|
2632
|
+
trigger(self.onKeyDown, {row: activeRow, cell: activeCell, grid: self}, e);
|
|
2633
|
+
var handled = e.isImmediatePropagationStopped();
|
|
2634
|
+
var keyCode = Slick.keyCode;
|
|
2635
|
+
|
|
2636
|
+
if (!handled) {
|
|
2637
|
+
if (!e.shiftKey && !e.altKey) {
|
|
2638
|
+
if (options.editable && currentEditor && currentEditor.keyCaptureList) {
|
|
2639
|
+
if (currentEditor.keyCaptureList.indexOf(e.which) > -1) {
|
|
2640
|
+
return;
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
if (e.which == keyCode.HOME) {
|
|
2644
|
+
handled = (e.ctrlKey) ? navigateTop() : navigateRowStart();
|
|
2645
|
+
} else if (e.which == keyCode.END) {
|
|
2646
|
+
handled = (e.ctrlKey) ? navigateBottom() : navigateRowEnd();
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
}
|
|
2650
|
+
if (!handled) {
|
|
2651
|
+
if (!e.shiftKey && !e.altKey && !e.ctrlKey) {
|
|
2652
|
+
// editor may specify an array of keys to bubble
|
|
2653
|
+
if (options.editable && currentEditor && currentEditor.keyCaptureList) {
|
|
2654
|
+
if (currentEditor.keyCaptureList.indexOf( e.which ) > -1) {
|
|
2655
|
+
return;
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2658
|
+
if (e.which == keyCode.ESCAPE) {
|
|
2659
|
+
if (!getEditorLock().isActive()) {
|
|
2660
|
+
return; // no editing mode to cancel, allow bubbling and default processing (exit without cancelling the event)
|
|
2661
|
+
}
|
|
2662
|
+
cancelEditAndSetFocus();
|
|
2663
|
+
} else if (e.which == keyCode.PAGE_DOWN) {
|
|
2664
|
+
navigatePageDown();
|
|
2665
|
+
handled = true;
|
|
2666
|
+
} else if (e.which == keyCode.PAGE_UP) {
|
|
2667
|
+
navigatePageUp();
|
|
2668
|
+
handled = true;
|
|
2669
|
+
} else if (e.which == keyCode.LEFT) {
|
|
2670
|
+
handled = navigateLeft();
|
|
2671
|
+
} else if (e.which == keyCode.RIGHT) {
|
|
2672
|
+
handled = navigateRight();
|
|
2673
|
+
} else if (e.which == keyCode.UP) {
|
|
2674
|
+
handled = navigateUp();
|
|
2675
|
+
} else if (e.which == keyCode.DOWN) {
|
|
2676
|
+
handled = navigateDown();
|
|
2677
|
+
} else if (e.which == keyCode.TAB) {
|
|
2678
|
+
handled = navigateNext();
|
|
2679
|
+
} else if (e.which == keyCode.ENTER) {
|
|
2680
|
+
if (options.editable) {
|
|
2681
|
+
if (currentEditor) {
|
|
2682
|
+
// adding new row
|
|
2683
|
+
if (activeRow === getDataLength()) {
|
|
2684
|
+
navigateDown();
|
|
2685
|
+
} else {
|
|
2686
|
+
commitEditAndSetFocus();
|
|
2687
|
+
}
|
|
2688
|
+
} else {
|
|
2689
|
+
if (getEditorLock().commitCurrentEdit()) {
|
|
2690
|
+
makeActiveCellEditable();
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
handled = true;
|
|
2695
|
+
}
|
|
2696
|
+
} else if (e.which == keyCode.TAB && e.shiftKey && !e.ctrlKey && !e.altKey) {
|
|
2697
|
+
handled = navigatePrev();
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2700
|
+
|
|
2701
|
+
if (handled) {
|
|
2702
|
+
// the event has been handled so don't let parent element (bubbling/propagation) or browser (default) handle it
|
|
2703
|
+
e.stopPropagation();
|
|
2704
|
+
e.preventDefault();
|
|
2705
|
+
try {
|
|
2706
|
+
e.originalEvent.keyCode = 0; // prevent default behaviour for special keys in IE browsers (F3, F5, etc.)
|
|
2707
|
+
}
|
|
2708
|
+
// ignore exceptions - setting the original event's keycode throws access denied exception for "Ctrl"
|
|
2709
|
+
// (hitting control key only, nothing else), "Shift" (maybe others)
|
|
2710
|
+
catch (error) {
|
|
2711
|
+
}
|
|
2712
|
+
}
|
|
2713
|
+
}
|
|
2714
|
+
|
|
2715
|
+
function handleClick(e) {
|
|
2716
|
+
if (!currentEditor) {
|
|
2717
|
+
// if this click resulted in some cell child node getting focus,
|
|
2718
|
+
// don't steal it back - keyboard events will still bubble up
|
|
2719
|
+
// IE9+ seems to default DIVs to tabIndex=0 instead of -1, so check for cell clicks directly.
|
|
2720
|
+
if (e.target != document.activeElement || $(e.target).hasClass("slick-cell")) {
|
|
2721
|
+
setFocus();
|
|
2722
|
+
}
|
|
2723
|
+
}
|
|
2724
|
+
|
|
2725
|
+
var cell = getCellFromEvent(e);
|
|
2726
|
+
if (!cell || (currentEditor !== null && activeRow == cell.row && activeCell == cell.cell)) {
|
|
2727
|
+
return;
|
|
2728
|
+
}
|
|
2729
|
+
|
|
2730
|
+
trigger(self.onClick, {row: cell.row, cell: cell.cell, grid: self}, e);
|
|
2731
|
+
if (e.isImmediatePropagationStopped()) {
|
|
2732
|
+
return;
|
|
2733
|
+
}
|
|
2734
|
+
|
|
2735
|
+
// this optimisation causes trouble - MLeibman #329
|
|
2736
|
+
//if ((activeCell != cell.cell || activeRow != cell.row) && canCellBeActive(cell.row, cell.cell)) {
|
|
2737
|
+
if (canCellBeActive(cell.row, cell.cell)) {
|
|
2738
|
+
if (!getEditorLock().isActive() || getEditorLock().commitCurrentEdit()) {
|
|
2739
|
+
scrollRowIntoView(cell.row, false);
|
|
2740
|
+
|
|
2741
|
+
var preClickModeOn = (e.target && e.target.className === Slick.preClickClassName);
|
|
2742
|
+
setActiveCellInternal(getCellNode(cell.row, cell.cell), null, preClickModeOn);
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
}
|
|
2746
|
+
|
|
2747
|
+
function handleContextMenu(e) {
|
|
2748
|
+
var $cell = $(e.target).closest(".slick-cell", $canvas);
|
|
2749
|
+
if ($cell.length === 0) {
|
|
2750
|
+
return;
|
|
2751
|
+
}
|
|
2752
|
+
|
|
2753
|
+
// are we editing this cell?
|
|
2754
|
+
if (activeCellNode === $cell[0] && currentEditor !== null) {
|
|
2755
|
+
return;
|
|
2756
|
+
}
|
|
2757
|
+
|
|
2758
|
+
trigger(self.onContextMenu, {grid: self}, e);
|
|
2759
|
+
}
|
|
2760
|
+
|
|
2761
|
+
function handleDblClick(e) {
|
|
2762
|
+
var cell = getCellFromEvent(e);
|
|
2763
|
+
if (!cell || (currentEditor !== null && activeRow == cell.row && activeCell == cell.cell)) {
|
|
2764
|
+
return;
|
|
2765
|
+
}
|
|
2766
|
+
|
|
2767
|
+
trigger(self.onDblClick, {row: cell.row, cell: cell.cell, grid: self}, e);
|
|
2768
|
+
if (e.isImmediatePropagationStopped()) {
|
|
2769
|
+
return;
|
|
2770
|
+
}
|
|
2771
|
+
|
|
2772
|
+
if (options.editable) {
|
|
2773
|
+
gotoCell(cell.row, cell.cell, true);
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2776
|
+
|
|
2777
|
+
function handleHeaderMouseEnter(e) {
|
|
2778
|
+
trigger(self.onHeaderMouseEnter, {
|
|
2779
|
+
"column": $(this).data("column"),
|
|
2780
|
+
"grid": self
|
|
2781
|
+
}, e);
|
|
2782
|
+
}
|
|
2783
|
+
|
|
2784
|
+
function handleHeaderMouseLeave(e) {
|
|
2785
|
+
trigger(self.onHeaderMouseLeave, {
|
|
2786
|
+
"column": $(this).data("column"),
|
|
2787
|
+
"grid": self
|
|
2788
|
+
}, e);
|
|
2789
|
+
}
|
|
2790
|
+
|
|
2791
|
+
function handleHeaderContextMenu(e) {
|
|
2792
|
+
var $header = $(e.target).closest(".slick-header-column", ".slick-header-columns");
|
|
2793
|
+
var column = $header && $header.data("column");
|
|
2794
|
+
trigger(self.onHeaderContextMenu, {column: column, grid: self}, e);
|
|
2795
|
+
}
|
|
2796
|
+
|
|
2797
|
+
function handleHeaderClick(e) {
|
|
2798
|
+
if (columnResizeDragging) return;
|
|
2799
|
+
var $header = $(e.target).closest(".slick-header-column", ".slick-header-columns");
|
|
2800
|
+
var column = $header && $header.data("column");
|
|
2801
|
+
if (column) {
|
|
2802
|
+
trigger(self.onHeaderClick, {column: column, grid: self}, e);
|
|
2803
|
+
}
|
|
2804
|
+
}
|
|
2805
|
+
|
|
2806
|
+
function handleMouseEnter(e) {
|
|
2807
|
+
trigger(self.onMouseEnter, {grid: self}, e);
|
|
2808
|
+
}
|
|
2809
|
+
|
|
2810
|
+
function handleMouseLeave(e) {
|
|
2811
|
+
trigger(self.onMouseLeave, {grid: self}, e);
|
|
2812
|
+
}
|
|
2813
|
+
|
|
2814
|
+
function cellExists(row, cell) {
|
|
2815
|
+
return !(row < 0 || row >= getDataLength() || cell < 0 || cell >= columns.length);
|
|
2816
|
+
}
|
|
2817
|
+
|
|
2818
|
+
function getCellFromPoint(x, y) {
|
|
2819
|
+
var row = getRowFromPosition(y);
|
|
2820
|
+
var cell = 0;
|
|
2821
|
+
|
|
2822
|
+
var w = 0;
|
|
2823
|
+
for (var i = 0; i < columns.length && w < x; i++) {
|
|
2824
|
+
w += columns[i].width;
|
|
2825
|
+
cell++;
|
|
2826
|
+
}
|
|
2827
|
+
|
|
2828
|
+
if (cell < 0) {
|
|
2829
|
+
cell = 0;
|
|
2830
|
+
}
|
|
2831
|
+
|
|
2832
|
+
return {row: row, cell: cell - 1};
|
|
2833
|
+
}
|
|
2834
|
+
|
|
2835
|
+
function getCellFromNode(cellNode) {
|
|
2836
|
+
// read column number from .l<columnNumber> CSS class
|
|
2837
|
+
var cls = /l\d+/.exec(cellNode.className);
|
|
2838
|
+
if (!cls) {
|
|
2839
|
+
throw new Error("getCellFromNode: cannot get cell - " + cellNode.className);
|
|
2840
|
+
}
|
|
2841
|
+
return parseInt(cls[0].substr(1, cls[0].length - 1), 10);
|
|
2842
|
+
}
|
|
2843
|
+
|
|
2844
|
+
function getRowFromNode(rowNode) {
|
|
2845
|
+
for (var row in rowsCache) {
|
|
2846
|
+
if (rowsCache[row].rowNode === rowNode) {
|
|
2847
|
+
return row | 0;
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2850
|
+
|
|
2851
|
+
return null;
|
|
2852
|
+
}
|
|
2853
|
+
|
|
2854
|
+
function getCellFromEvent(e) {
|
|
2855
|
+
var $cell = $(e.target).closest(".slick-cell", $canvas);
|
|
2856
|
+
if (!$cell.length) {
|
|
2857
|
+
return null;
|
|
2858
|
+
}
|
|
2859
|
+
|
|
2860
|
+
var row = getRowFromNode($cell[0].parentNode);
|
|
2861
|
+
var cell = getCellFromNode($cell[0]);
|
|
2862
|
+
|
|
2863
|
+
if (row == null || cell == null) {
|
|
2864
|
+
return null;
|
|
2865
|
+
} else {
|
|
2866
|
+
return {
|
|
2867
|
+
"row": row,
|
|
2868
|
+
"cell": cell
|
|
2869
|
+
};
|
|
2870
|
+
}
|
|
2871
|
+
}
|
|
2872
|
+
|
|
2873
|
+
function getCellNodeBox(row, cell) {
|
|
2874
|
+
if (!cellExists(row, cell)) {
|
|
2875
|
+
return null;
|
|
2876
|
+
}
|
|
2877
|
+
|
|
2878
|
+
var y1 = getRowTop(row);
|
|
2879
|
+
var y2 = y1 + options.rowHeight - 1;
|
|
2880
|
+
var x1 = 0;
|
|
2881
|
+
for (var i = 0; i < cell; i++) {
|
|
2882
|
+
x1 += columns[i].width;
|
|
2883
|
+
}
|
|
2884
|
+
var x2 = x1 + columns[cell].width;
|
|
2885
|
+
|
|
2886
|
+
return {
|
|
2887
|
+
top: y1,
|
|
2888
|
+
left: x1,
|
|
2889
|
+
bottom: y2,
|
|
2890
|
+
right: x2
|
|
2891
|
+
};
|
|
2892
|
+
}
|
|
2893
|
+
|
|
2894
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
2895
|
+
// Cell switching
|
|
2896
|
+
|
|
2897
|
+
function resetActiveCell() {
|
|
2898
|
+
setActiveCellInternal(null, false);
|
|
2899
|
+
}
|
|
2900
|
+
|
|
2901
|
+
function setFocus() {
|
|
2902
|
+
if (tabbingDirection == -1) {
|
|
2903
|
+
$focusSink[0].focus();
|
|
2904
|
+
} else {
|
|
2905
|
+
$focusSink2[0].focus();
|
|
2906
|
+
}
|
|
2907
|
+
}
|
|
2908
|
+
|
|
2909
|
+
function scrollCellIntoView(row, cell, doPaging) {
|
|
2910
|
+
scrollRowIntoView(row, doPaging);
|
|
2911
|
+
|
|
2912
|
+
var colspan = getColspan(row, cell);
|
|
2913
|
+
internalScrollColumnIntoView(columnPosLeft[cell], columnPosRight[cell + (colspan > 1 ? colspan - 1 : 0)]);
|
|
2914
|
+
}
|
|
2915
|
+
|
|
2916
|
+
function internalScrollColumnIntoView(left, right) {
|
|
2917
|
+
var scrollRight = scrollLeft + viewportW;
|
|
2918
|
+
|
|
2919
|
+
if (left < scrollLeft) {
|
|
2920
|
+
$viewport.scrollLeft(left);
|
|
2921
|
+
handleScroll();
|
|
2922
|
+
render();
|
|
2923
|
+
} else if (right > scrollRight) {
|
|
2924
|
+
$viewport.scrollLeft(Math.min(left, right - $viewport[0].clientWidth));
|
|
2925
|
+
handleScroll();
|
|
2926
|
+
render();
|
|
2927
|
+
}
|
|
2928
|
+
}
|
|
2929
|
+
|
|
2930
|
+
function scrollColumnIntoView(cell) {
|
|
2931
|
+
internalScrollColumnIntoView(columnPosLeft[cell], columnPosRight[cell]);
|
|
2932
|
+
}
|
|
2933
|
+
|
|
2934
|
+
function setActiveCellInternal(newCell, opt_editMode, preClickModeOn, suppressActiveCellChangedEvent) {
|
|
2935
|
+
if (activeCellNode !== null) {
|
|
2936
|
+
makeActiveCellNormal();
|
|
2937
|
+
$(activeCellNode).removeClass("active");
|
|
2938
|
+
if (rowsCache[activeRow]) {
|
|
2939
|
+
$(rowsCache[activeRow].rowNode).removeClass("active");
|
|
2940
|
+
}
|
|
2941
|
+
}
|
|
2942
|
+
|
|
2943
|
+
var activeCellChanged = (activeCellNode !== newCell);
|
|
2944
|
+
activeCellNode = newCell;
|
|
2945
|
+
|
|
2946
|
+
if (activeCellNode != null) {
|
|
2947
|
+
activeRow = getRowFromNode(activeCellNode.parentNode);
|
|
2948
|
+
activeCell = activePosX = getCellFromNode(activeCellNode);
|
|
2949
|
+
|
|
2950
|
+
if (opt_editMode == null) {
|
|
2951
|
+
opt_editMode = (activeRow == getDataLength()) || options.autoEdit;
|
|
2952
|
+
}
|
|
2953
|
+
|
|
2954
|
+
if (options.showCellSelection) {
|
|
2955
|
+
$(activeCellNode).addClass("active");
|
|
2956
|
+
$(rowsCache[activeRow].rowNode).addClass("active");
|
|
2957
|
+
}
|
|
2958
|
+
|
|
2959
|
+
if (options.editable && opt_editMode && isCellPotentiallyEditable(activeRow, activeCell)) {
|
|
2960
|
+
clearTimeout(h_editorLoader);
|
|
2961
|
+
|
|
2962
|
+
if (options.asyncEditorLoading) {
|
|
2963
|
+
h_editorLoader = setTimeout(function () {
|
|
2964
|
+
makeActiveCellEditable(undefined, preClickModeOn);
|
|
2965
|
+
}, options.asyncEditorLoadDelay);
|
|
2966
|
+
} else {
|
|
2967
|
+
makeActiveCellEditable(undefined, preClickModeOn);
|
|
2968
|
+
}
|
|
2969
|
+
}
|
|
2970
|
+
} else {
|
|
2971
|
+
activeRow = activeCell = null;
|
|
2972
|
+
}
|
|
2973
|
+
|
|
2974
|
+
// this optimisation causes trouble - MLeibman #329
|
|
2975
|
+
//if (activeCellChanged) {
|
|
2976
|
+
if (!suppressActiveCellChangedEvent) { trigger(self.onActiveCellChanged, getActiveCell()); }
|
|
2977
|
+
//}
|
|
2978
|
+
}
|
|
2979
|
+
|
|
2980
|
+
function clearTextSelection() {
|
|
2981
|
+
if (document.selection && document.selection.empty) {
|
|
2982
|
+
try {
|
|
2983
|
+
//IE fails here if selected element is not in dom
|
|
2984
|
+
document.selection.empty();
|
|
2985
|
+
} catch (e) { }
|
|
2986
|
+
} else if (window.getSelection) {
|
|
2987
|
+
var sel = window.getSelection();
|
|
2988
|
+
if (sel && sel.removeAllRanges) {
|
|
2989
|
+
sel.removeAllRanges();
|
|
2990
|
+
}
|
|
2991
|
+
}
|
|
2992
|
+
}
|
|
2993
|
+
|
|
2994
|
+
function isCellPotentiallyEditable(row, cell) {
|
|
2995
|
+
var dataLength = getDataLength();
|
|
2996
|
+
// is the data for this row loaded?
|
|
2997
|
+
if (row < dataLength && !getDataItem(row)) {
|
|
2998
|
+
return false;
|
|
2999
|
+
}
|
|
3000
|
+
|
|
3001
|
+
// are we in the Add New row? can we create new from this cell?
|
|
3002
|
+
if (columns[cell].cannotTriggerInsert && row >= dataLength) {
|
|
3003
|
+
return false;
|
|
3004
|
+
}
|
|
3005
|
+
|
|
3006
|
+
// does this cell have an editor?
|
|
3007
|
+
if (!getEditor(row, cell)) {
|
|
3008
|
+
return false;
|
|
3009
|
+
}
|
|
3010
|
+
|
|
3011
|
+
return true;
|
|
3012
|
+
}
|
|
3013
|
+
|
|
3014
|
+
function makeActiveCellNormal() {
|
|
3015
|
+
if (!currentEditor) {
|
|
3016
|
+
return;
|
|
3017
|
+
}
|
|
3018
|
+
trigger(self.onBeforeCellEditorDestroy, {editor: currentEditor, grid: self});
|
|
3019
|
+
currentEditor.destroy();
|
|
3020
|
+
currentEditor = null;
|
|
3021
|
+
|
|
3022
|
+
if (activeCellNode) {
|
|
3023
|
+
var d = getDataItem(activeRow);
|
|
3024
|
+
$(activeCellNode).removeClass("editable invalid");
|
|
3025
|
+
if (d) {
|
|
3026
|
+
var column = columns[activeCell];
|
|
3027
|
+
var formatter = getFormatter(activeRow, column);
|
|
3028
|
+
var formatterResult = formatter(activeRow, activeCell, getDataItemValueForColumn(d, column), column, d, self);
|
|
3029
|
+
applyFormatResultToCellNode(formatterResult, activeCellNode);
|
|
3030
|
+
invalidatePostProcessingResults(activeRow);
|
|
3031
|
+
}
|
|
3032
|
+
}
|
|
3033
|
+
|
|
3034
|
+
// if there previously was text selected on a page (such as selected text in the edit cell just removed),
|
|
3035
|
+
// IE can't set focus to anything else correctly
|
|
3036
|
+
if (navigator.userAgent.toLowerCase().match(/msie/)) {
|
|
3037
|
+
clearTextSelection();
|
|
3038
|
+
}
|
|
3039
|
+
|
|
3040
|
+
getEditorLock().deactivate(editController);
|
|
3041
|
+
}
|
|
3042
|
+
|
|
3043
|
+
function makeActiveCellEditable(editor, preClickModeOn) {
|
|
3044
|
+
if (!activeCellNode) {
|
|
3045
|
+
return;
|
|
3046
|
+
}
|
|
3047
|
+
if (!options.editable) {
|
|
3048
|
+
throw new Error("Grid : makeActiveCellEditable : should never get called when options.editable is false");
|
|
3049
|
+
}
|
|
3050
|
+
|
|
3051
|
+
// cancel pending async call if there is one
|
|
3052
|
+
clearTimeout(h_editorLoader);
|
|
3053
|
+
|
|
3054
|
+
if (!isCellPotentiallyEditable(activeRow, activeCell)) {
|
|
3055
|
+
return;
|
|
3056
|
+
}
|
|
3057
|
+
|
|
3058
|
+
var columnDef = columns[activeCell];
|
|
3059
|
+
var item = getDataItem(activeRow);
|
|
3060
|
+
|
|
3061
|
+
if (trigger(self.onBeforeEditCell, {row: activeRow, cell: activeCell, item: item, column: columnDef, grid: self}) === false) {
|
|
3062
|
+
setFocus();
|
|
3063
|
+
return;
|
|
3064
|
+
}
|
|
3065
|
+
|
|
3066
|
+
getEditorLock().activate(editController);
|
|
3067
|
+
$(activeCellNode).addClass("editable");
|
|
3068
|
+
|
|
3069
|
+
var useEditor = editor || getEditor(activeRow, activeCell);
|
|
3070
|
+
|
|
3071
|
+
// don't clear the cell if a custom editor is passed through
|
|
3072
|
+
if (!editor && !useEditor.suppressClearOnEdit) {
|
|
3073
|
+
activeCellNode.innerHTML = "";
|
|
3074
|
+
}
|
|
3075
|
+
|
|
3076
|
+
currentEditor = new useEditor({
|
|
3077
|
+
grid: self,
|
|
3078
|
+
gridPosition: absBox($container[0]),
|
|
3079
|
+
position: absBox(activeCellNode),
|
|
3080
|
+
container: activeCellNode,
|
|
3081
|
+
column: columnDef,
|
|
3082
|
+
item: item || {},
|
|
3083
|
+
commitChanges: commitEditAndSetFocus,
|
|
3084
|
+
cancelChanges: cancelEditAndSetFocus
|
|
3085
|
+
});
|
|
3086
|
+
|
|
3087
|
+
if (item) {
|
|
3088
|
+
currentEditor.loadValue(item);
|
|
3089
|
+
if (preClickModeOn && currentEditor.preClick) {
|
|
3090
|
+
currentEditor.preClick();
|
|
3091
|
+
}
|
|
3092
|
+
}
|
|
3093
|
+
|
|
3094
|
+
serializedEditorValue = currentEditor.serializeValue();
|
|
3095
|
+
|
|
3096
|
+
if (currentEditor.position) {
|
|
3097
|
+
handleActiveCellPositionChange();
|
|
3098
|
+
}
|
|
3099
|
+
}
|
|
3100
|
+
|
|
3101
|
+
function commitEditAndSetFocus() {
|
|
3102
|
+
// if the commit fails, it would do so due to a validation error
|
|
3103
|
+
// if so, do not steal the focus from the editor
|
|
3104
|
+
if (getEditorLock().commitCurrentEdit()) {
|
|
3105
|
+
setFocus();
|
|
3106
|
+
if (options.autoEdit) {
|
|
3107
|
+
navigateDown();
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
}
|
|
3111
|
+
|
|
3112
|
+
function cancelEditAndSetFocus() {
|
|
3113
|
+
if (getEditorLock().cancelCurrentEdit()) {
|
|
3114
|
+
setFocus();
|
|
3115
|
+
}
|
|
3116
|
+
}
|
|
3117
|
+
|
|
3118
|
+
function absBox(elem) {
|
|
3119
|
+
var box = {
|
|
3120
|
+
top: elem.offsetTop,
|
|
3121
|
+
left: elem.offsetLeft,
|
|
3122
|
+
bottom: 0,
|
|
3123
|
+
right: 0,
|
|
3124
|
+
width: $(elem).outerWidth(),
|
|
3125
|
+
height: $(elem).outerHeight(),
|
|
3126
|
+
visible: true};
|
|
3127
|
+
box.bottom = box.top + box.height;
|
|
3128
|
+
box.right = box.left + box.width;
|
|
3129
|
+
|
|
3130
|
+
// walk up the tree
|
|
3131
|
+
var offsetParent = elem.offsetParent;
|
|
3132
|
+
while ((elem = elem.parentNode) != document.body) {
|
|
3133
|
+
if (elem == null) break;
|
|
3134
|
+
|
|
3135
|
+
if (box.visible && elem.scrollHeight != elem.offsetHeight && $(elem).css("overflowY") != "visible") {
|
|
3136
|
+
box.visible = box.bottom > elem.scrollTop && box.top < elem.scrollTop + elem.clientHeight;
|
|
3137
|
+
}
|
|
3138
|
+
|
|
3139
|
+
if (box.visible && elem.scrollWidth != elem.offsetWidth && $(elem).css("overflowX") != "visible") {
|
|
3140
|
+
box.visible = box.right > elem.scrollLeft && box.left < elem.scrollLeft + elem.clientWidth;
|
|
3141
|
+
}
|
|
3142
|
+
|
|
3143
|
+
box.left -= elem.scrollLeft;
|
|
3144
|
+
box.top -= elem.scrollTop;
|
|
3145
|
+
|
|
3146
|
+
if (elem === offsetParent) {
|
|
3147
|
+
box.left += elem.offsetLeft;
|
|
3148
|
+
box.top += elem.offsetTop;
|
|
3149
|
+
offsetParent = elem.offsetParent;
|
|
3150
|
+
}
|
|
3151
|
+
|
|
3152
|
+
box.bottom = box.top + box.height;
|
|
3153
|
+
box.right = box.left + box.width;
|
|
3154
|
+
}
|
|
3155
|
+
|
|
3156
|
+
return box;
|
|
3157
|
+
}
|
|
3158
|
+
|
|
3159
|
+
function getActiveCellPosition() {
|
|
3160
|
+
return absBox(activeCellNode);
|
|
3161
|
+
}
|
|
3162
|
+
|
|
3163
|
+
function getGridPosition() {
|
|
3164
|
+
return absBox($container[0])
|
|
3165
|
+
}
|
|
3166
|
+
|
|
3167
|
+
function handleActiveCellPositionChange() {
|
|
3168
|
+
if (!activeCellNode) {
|
|
3169
|
+
return;
|
|
3170
|
+
}
|
|
3171
|
+
|
|
3172
|
+
trigger(self.onActiveCellPositionChanged, {grid: self});
|
|
3173
|
+
|
|
3174
|
+
if (currentEditor) {
|
|
3175
|
+
var cellBox = getActiveCellPosition();
|
|
3176
|
+
if (currentEditor.show && currentEditor.hide) {
|
|
3177
|
+
if (!cellBox.visible) {
|
|
3178
|
+
currentEditor.hide();
|
|
3179
|
+
} else {
|
|
3180
|
+
currentEditor.show();
|
|
3181
|
+
}
|
|
3182
|
+
}
|
|
3183
|
+
|
|
3184
|
+
if (currentEditor.position) {
|
|
3185
|
+
currentEditor.position(cellBox);
|
|
3186
|
+
}
|
|
3187
|
+
}
|
|
3188
|
+
}
|
|
3189
|
+
|
|
3190
|
+
function getCellEditor() {
|
|
3191
|
+
return currentEditor;
|
|
3192
|
+
}
|
|
3193
|
+
|
|
3194
|
+
function getActiveCell() {
|
|
3195
|
+
if (!activeCellNode) {
|
|
3196
|
+
return null;
|
|
3197
|
+
} else {
|
|
3198
|
+
return {row: activeRow, cell: activeCell, grid: self};
|
|
3199
|
+
}
|
|
3200
|
+
}
|
|
3201
|
+
|
|
3202
|
+
function getActiveCellNode() {
|
|
3203
|
+
return activeCellNode;
|
|
3204
|
+
}
|
|
3205
|
+
|
|
3206
|
+
function scrollRowIntoView(row, doPaging) {
|
|
3207
|
+
var rowAtTop = row * options.rowHeight;
|
|
3208
|
+
var rowAtBottom = (row + 1) * options.rowHeight - viewportH + (viewportHasHScroll ? scrollbarDimensions.height : 0);
|
|
3209
|
+
|
|
3210
|
+
// need to page down?
|
|
3211
|
+
if ((row + 1) * options.rowHeight > scrollTop + viewportH + offset) {
|
|
3212
|
+
scrollTo(doPaging ? rowAtTop : rowAtBottom);
|
|
3213
|
+
render();
|
|
3214
|
+
}
|
|
3215
|
+
// or page up?
|
|
3216
|
+
else if (row * options.rowHeight < scrollTop + offset) {
|
|
3217
|
+
scrollTo(doPaging ? rowAtBottom : rowAtTop);
|
|
3218
|
+
render();
|
|
3219
|
+
}
|
|
3220
|
+
}
|
|
3221
|
+
|
|
3222
|
+
function scrollRowToTop(row) {
|
|
3223
|
+
scrollTo(row * options.rowHeight);
|
|
3224
|
+
render();
|
|
3225
|
+
}
|
|
3226
|
+
|
|
3227
|
+
function scrollPage(dir) {
|
|
3228
|
+
var deltaRows = dir * numVisibleRows;
|
|
3229
|
+
scrollTo((getRowFromPosition(scrollTop) + deltaRows) * options.rowHeight);
|
|
3230
|
+
render();
|
|
3231
|
+
|
|
3232
|
+
if (options.enableCellNavigation && activeRow != null) {
|
|
3233
|
+
var row = activeRow + deltaRows;
|
|
3234
|
+
var dataLengthIncludingAddNew = getDataLengthIncludingAddNew();
|
|
3235
|
+
if (row >= dataLengthIncludingAddNew) {
|
|
3236
|
+
row = dataLengthIncludingAddNew - 1;
|
|
3237
|
+
}
|
|
3238
|
+
if (row < 0) {
|
|
3239
|
+
row = 0;
|
|
3240
|
+
}
|
|
3241
|
+
|
|
3242
|
+
var cell = 0, prevCell = null;
|
|
3243
|
+
var prevActivePosX = activePosX;
|
|
3244
|
+
while (cell <= activePosX) {
|
|
3245
|
+
if (canCellBeActive(row, cell)) {
|
|
3246
|
+
prevCell = cell;
|
|
3247
|
+
}
|
|
3248
|
+
cell += getColspan(row, cell);
|
|
3249
|
+
}
|
|
3250
|
+
|
|
3251
|
+
if (prevCell !== null) {
|
|
3252
|
+
setActiveCellInternal(getCellNode(row, prevCell));
|
|
3253
|
+
activePosX = prevActivePosX;
|
|
3254
|
+
} else {
|
|
3255
|
+
resetActiveCell();
|
|
3256
|
+
}
|
|
3257
|
+
}
|
|
3258
|
+
}
|
|
3259
|
+
|
|
3260
|
+
function navigatePageDown() {
|
|
3261
|
+
scrollPage(1);
|
|
3262
|
+
}
|
|
3263
|
+
|
|
3264
|
+
function navigatePageUp() {
|
|
3265
|
+
scrollPage(-1);
|
|
3266
|
+
}
|
|
3267
|
+
|
|
3268
|
+
function navigateTop() {
|
|
3269
|
+
navigateToRow(0);
|
|
3270
|
+
}
|
|
3271
|
+
|
|
3272
|
+
function navigateBottom() {
|
|
3273
|
+
navigateToRow(getDataLength()-1);
|
|
3274
|
+
}
|
|
3275
|
+
|
|
3276
|
+
function navigateToRow(row) {
|
|
3277
|
+
var num_rows = getDataLength();
|
|
3278
|
+
if (!num_rows) return true;
|
|
3279
|
+
|
|
3280
|
+
if (row < 0) row = 0;
|
|
3281
|
+
else if (row >= num_rows) row = num_rows - 1;
|
|
3282
|
+
|
|
3283
|
+
scrollCellIntoView(row, 0, true);
|
|
3284
|
+
if (options.enableCellNavigation && activeRow != null) {
|
|
3285
|
+
var cell = 0, prevCell = null;
|
|
3286
|
+
var prevActivePosX = activePosX;
|
|
3287
|
+
while (cell <= activePosX) {
|
|
3288
|
+
if (canCellBeActive(row, cell)) {
|
|
3289
|
+
prevCell = cell;
|
|
3290
|
+
}
|
|
3291
|
+
cell += getColspan(row, cell);
|
|
3292
|
+
}
|
|
3293
|
+
|
|
3294
|
+
if (prevCell !== null) {
|
|
3295
|
+
setActiveCellInternal(getCellNode(row, prevCell));
|
|
3296
|
+
activePosX = prevActivePosX;
|
|
3297
|
+
} else {
|
|
3298
|
+
resetActiveCell();
|
|
3299
|
+
}
|
|
3300
|
+
}
|
|
3301
|
+
return true;
|
|
3302
|
+
}
|
|
3303
|
+
|
|
3304
|
+
function getColspan(row, cell) {
|
|
3305
|
+
var metadata = data.getItemMetadata && data.getItemMetadata(row);
|
|
3306
|
+
if (!metadata || !metadata.columns) {
|
|
3307
|
+
return 1;
|
|
3308
|
+
}
|
|
3309
|
+
|
|
3310
|
+
var columnData = metadata.columns[columns[cell].id] || metadata.columns[cell];
|
|
3311
|
+
var colspan = (columnData && columnData.colspan);
|
|
3312
|
+
if (colspan === "*") {
|
|
3313
|
+
colspan = columns.length - cell;
|
|
3314
|
+
} else {
|
|
3315
|
+
colspan = colspan || 1;
|
|
3316
|
+
}
|
|
3317
|
+
|
|
3318
|
+
return colspan;
|
|
3319
|
+
}
|
|
3320
|
+
|
|
3321
|
+
function findFirstFocusableCell(row) {
|
|
3322
|
+
var cell = 0;
|
|
3323
|
+
while (cell < columns.length) {
|
|
3324
|
+
if (canCellBeActive(row, cell)) {
|
|
3325
|
+
return cell;
|
|
3326
|
+
}
|
|
3327
|
+
cell += getColspan(row, cell);
|
|
3328
|
+
}
|
|
3329
|
+
return null;
|
|
3330
|
+
}
|
|
3331
|
+
|
|
3332
|
+
function findLastFocusableCell(row) {
|
|
3333
|
+
var cell = 0;
|
|
3334
|
+
var lastFocusableCell = null;
|
|
3335
|
+
while (cell < columns.length) {
|
|
3336
|
+
if (canCellBeActive(row, cell)) {
|
|
3337
|
+
lastFocusableCell = cell;
|
|
3338
|
+
}
|
|
3339
|
+
cell += getColspan(row, cell);
|
|
3340
|
+
}
|
|
3341
|
+
return lastFocusableCell;
|
|
3342
|
+
}
|
|
3343
|
+
|
|
3344
|
+
function gotoRight(row, cell, posX) {
|
|
3345
|
+
if (cell >= columns.length) {
|
|
3346
|
+
return null;
|
|
3347
|
+
}
|
|
3348
|
+
|
|
3349
|
+
do {
|
|
3350
|
+
cell += getColspan(row, cell);
|
|
3351
|
+
}
|
|
3352
|
+
while (cell < columns.length && !canCellBeActive(row, cell));
|
|
3353
|
+
|
|
3354
|
+
if (cell < columns.length) {
|
|
3355
|
+
return {
|
|
3356
|
+
"row": row,
|
|
3357
|
+
"cell": cell,
|
|
3358
|
+
"posX": cell
|
|
3359
|
+
};
|
|
3360
|
+
}
|
|
3361
|
+
return null;
|
|
3362
|
+
}
|
|
3363
|
+
|
|
3364
|
+
function gotoLeft(row, cell, posX) {
|
|
3365
|
+
if (cell <= 0) {
|
|
3366
|
+
return null;
|
|
3367
|
+
}
|
|
3368
|
+
|
|
3369
|
+
var firstFocusableCell = findFirstFocusableCell(row);
|
|
3370
|
+
if (firstFocusableCell === null || firstFocusableCell >= cell) {
|
|
3371
|
+
return null;
|
|
3372
|
+
}
|
|
3373
|
+
|
|
3374
|
+
var prev = {
|
|
3375
|
+
"row": row,
|
|
3376
|
+
"cell": firstFocusableCell,
|
|
3377
|
+
"posX": firstFocusableCell
|
|
3378
|
+
};
|
|
3379
|
+
var pos;
|
|
3380
|
+
while (true) {
|
|
3381
|
+
pos = gotoRight(prev.row, prev.cell, prev.posX);
|
|
3382
|
+
if (!pos) {
|
|
3383
|
+
return null;
|
|
3384
|
+
}
|
|
3385
|
+
if (pos.cell >= cell) {
|
|
3386
|
+
return prev;
|
|
3387
|
+
}
|
|
3388
|
+
prev = pos;
|
|
3389
|
+
}
|
|
3390
|
+
}
|
|
3391
|
+
|
|
3392
|
+
function gotoDown(row, cell, posX) {
|
|
3393
|
+
var prevCell;
|
|
3394
|
+
var dataLengthIncludingAddNew = getDataLengthIncludingAddNew();
|
|
3395
|
+
while (true) {
|
|
3396
|
+
if (++row >= dataLengthIncludingAddNew) {
|
|
3397
|
+
return null;
|
|
3398
|
+
}
|
|
3399
|
+
|
|
3400
|
+
prevCell = cell = 0;
|
|
3401
|
+
while (cell <= posX) {
|
|
3402
|
+
prevCell = cell;
|
|
3403
|
+
cell += getColspan(row, cell);
|
|
3404
|
+
}
|
|
3405
|
+
|
|
3406
|
+
if (canCellBeActive(row, prevCell)) {
|
|
3407
|
+
return {
|
|
3408
|
+
"row": row,
|
|
3409
|
+
"cell": prevCell,
|
|
3410
|
+
"posX": posX
|
|
3411
|
+
};
|
|
3412
|
+
}
|
|
3413
|
+
}
|
|
3414
|
+
}
|
|
3415
|
+
|
|
3416
|
+
function gotoUp(row, cell, posX) {
|
|
3417
|
+
var prevCell;
|
|
3418
|
+
while (true) {
|
|
3419
|
+
if (--row < 0) {
|
|
3420
|
+
return null;
|
|
3421
|
+
}
|
|
3422
|
+
|
|
3423
|
+
prevCell = cell = 0;
|
|
3424
|
+
while (cell <= posX) {
|
|
3425
|
+
prevCell = cell;
|
|
3426
|
+
cell += getColspan(row, cell);
|
|
3427
|
+
}
|
|
3428
|
+
|
|
3429
|
+
if (canCellBeActive(row, prevCell)) {
|
|
3430
|
+
return {
|
|
3431
|
+
"row": row,
|
|
3432
|
+
"cell": prevCell,
|
|
3433
|
+
"posX": posX
|
|
3434
|
+
};
|
|
3435
|
+
}
|
|
3436
|
+
}
|
|
3437
|
+
}
|
|
3438
|
+
|
|
3439
|
+
function gotoNext(row, cell, posX) {
|
|
3440
|
+
if (row == null && cell == null) {
|
|
3441
|
+
row = cell = posX = 0;
|
|
3442
|
+
if (canCellBeActive(row, cell)) {
|
|
3443
|
+
return {
|
|
3444
|
+
"row": row,
|
|
3445
|
+
"cell": cell,
|
|
3446
|
+
"posX": cell
|
|
3447
|
+
};
|
|
3448
|
+
}
|
|
3449
|
+
}
|
|
3450
|
+
|
|
3451
|
+
var pos = gotoRight(row, cell, posX);
|
|
3452
|
+
if (pos) {
|
|
3453
|
+
return pos;
|
|
3454
|
+
}
|
|
3455
|
+
|
|
3456
|
+
var firstFocusableCell = null;
|
|
3457
|
+
var dataLengthIncludingAddNew = getDataLengthIncludingAddNew();
|
|
3458
|
+
|
|
3459
|
+
// if at last row, cycle through columns rather than get stuck in the last one
|
|
3460
|
+
if (row === dataLengthIncludingAddNew - 1) { row--; }
|
|
3461
|
+
|
|
3462
|
+
while (++row < dataLengthIncludingAddNew) {
|
|
3463
|
+
firstFocusableCell = findFirstFocusableCell(row);
|
|
3464
|
+
if (firstFocusableCell !== null) {
|
|
3465
|
+
return {
|
|
3466
|
+
"row": row,
|
|
3467
|
+
"cell": firstFocusableCell,
|
|
3468
|
+
"posX": firstFocusableCell
|
|
3469
|
+
};
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
3472
|
+
return null;
|
|
3473
|
+
}
|
|
3474
|
+
|
|
3475
|
+
function gotoPrev(row, cell, posX) {
|
|
3476
|
+
if (row == null && cell == null) {
|
|
3477
|
+
row = getDataLengthIncludingAddNew() - 1;
|
|
3478
|
+
cell = posX = columns.length - 1;
|
|
3479
|
+
if (canCellBeActive(row, cell)) {
|
|
3480
|
+
return {
|
|
3481
|
+
"row": row,
|
|
3482
|
+
"cell": cell,
|
|
3483
|
+
"posX": cell
|
|
3484
|
+
};
|
|
3485
|
+
}
|
|
3486
|
+
}
|
|
3487
|
+
|
|
3488
|
+
var pos;
|
|
3489
|
+
var lastSelectableCell;
|
|
3490
|
+
while (!pos) {
|
|
3491
|
+
pos = gotoLeft(row, cell, posX);
|
|
3492
|
+
if (pos) {
|
|
3493
|
+
break;
|
|
3494
|
+
}
|
|
3495
|
+
if (--row < 0) {
|
|
3496
|
+
return null;
|
|
3497
|
+
}
|
|
3498
|
+
|
|
3499
|
+
cell = 0;
|
|
3500
|
+
lastSelectableCell = findLastFocusableCell(row);
|
|
3501
|
+
if (lastSelectableCell !== null) {
|
|
3502
|
+
pos = {
|
|
3503
|
+
"row": row,
|
|
3504
|
+
"cell": lastSelectableCell,
|
|
3505
|
+
"posX": lastSelectableCell
|
|
3506
|
+
};
|
|
3507
|
+
}
|
|
3508
|
+
}
|
|
3509
|
+
return pos;
|
|
3510
|
+
}
|
|
3511
|
+
|
|
3512
|
+
function gotoRowStart(row, cell, posX) {
|
|
3513
|
+
var newCell = findFirstFocusableCell(row);
|
|
3514
|
+
if (newCell === null) return null;
|
|
3515
|
+
|
|
3516
|
+
return {
|
|
3517
|
+
"row": row,
|
|
3518
|
+
"cell": newCell,
|
|
3519
|
+
"posX": posX
|
|
3520
|
+
};
|
|
3521
|
+
}
|
|
3522
|
+
|
|
3523
|
+
function gotoRowEnd(row, cell, posX) {
|
|
3524
|
+
var newCell = findLastFocusableCell(row);
|
|
3525
|
+
if (newCell === null) return null;
|
|
3526
|
+
|
|
3527
|
+
return {
|
|
3528
|
+
"row": row,
|
|
3529
|
+
"cell": newCell,
|
|
3530
|
+
"posX": posX
|
|
3531
|
+
};
|
|
3532
|
+
}
|
|
3533
|
+
|
|
3534
|
+
function navigateRight() {
|
|
3535
|
+
return navigate("right");
|
|
3536
|
+
}
|
|
3537
|
+
|
|
3538
|
+
function navigateLeft() {
|
|
3539
|
+
return navigate("left");
|
|
3540
|
+
}
|
|
3541
|
+
|
|
3542
|
+
function navigateDown() {
|
|
3543
|
+
return navigate("down");
|
|
3544
|
+
}
|
|
3545
|
+
|
|
3546
|
+
function navigateUp() {
|
|
3547
|
+
return navigate("up");
|
|
3548
|
+
}
|
|
3549
|
+
|
|
3550
|
+
function navigateNext() {
|
|
3551
|
+
return navigate("next");
|
|
3552
|
+
}
|
|
3553
|
+
|
|
3554
|
+
function navigatePrev() {
|
|
3555
|
+
return navigate("prev");
|
|
3556
|
+
}
|
|
3557
|
+
|
|
3558
|
+
function navigateRowStart() {
|
|
3559
|
+
return navigate("home");
|
|
3560
|
+
}
|
|
3561
|
+
|
|
3562
|
+
function navigateRowEnd() {
|
|
3563
|
+
return navigate("end");
|
|
3564
|
+
}
|
|
3565
|
+
|
|
3566
|
+
/**
|
|
3567
|
+
* @param {string} dir Navigation direction.
|
|
3568
|
+
* @return {boolean} Whether navigation resulted in a change of active cell.
|
|
3569
|
+
*/
|
|
3570
|
+
function navigate(dir) {
|
|
3571
|
+
if (!options.enableCellNavigation) {
|
|
3572
|
+
return false;
|
|
3573
|
+
}
|
|
3574
|
+
|
|
3575
|
+
if (!activeCellNode && dir != "prev" && dir != "next") {
|
|
3576
|
+
return false;
|
|
3577
|
+
}
|
|
3578
|
+
|
|
3579
|
+
if (!getEditorLock().commitCurrentEdit()) {
|
|
3580
|
+
return true;
|
|
3581
|
+
}
|
|
3582
|
+
setFocus();
|
|
3583
|
+
|
|
3584
|
+
var tabbingDirections = {
|
|
3585
|
+
"up": -1,
|
|
3586
|
+
"down": 1,
|
|
3587
|
+
"left": -1,
|
|
3588
|
+
"right": 1,
|
|
3589
|
+
"prev": -1,
|
|
3590
|
+
"next": 1,
|
|
3591
|
+
"home": -1,
|
|
3592
|
+
"end": 1
|
|
3593
|
+
};
|
|
3594
|
+
tabbingDirection = tabbingDirections[dir];
|
|
3595
|
+
|
|
3596
|
+
var stepFunctions = {
|
|
3597
|
+
"up": gotoUp,
|
|
3598
|
+
"down": gotoDown,
|
|
3599
|
+
"left": gotoLeft,
|
|
3600
|
+
"right": gotoRight,
|
|
3601
|
+
"prev": gotoPrev,
|
|
3602
|
+
"next": gotoNext,
|
|
3603
|
+
"home": gotoRowStart,
|
|
3604
|
+
"end": gotoRowEnd
|
|
3605
|
+
};
|
|
3606
|
+
var stepFn = stepFunctions[dir];
|
|
3607
|
+
var pos = stepFn(activeRow, activeCell, activePosX);
|
|
3608
|
+
if (pos) {
|
|
3609
|
+
var isAddNewRow = (pos.row == getDataLength());
|
|
3610
|
+
scrollCellIntoView(pos.row, pos.cell, !isAddNewRow && options.emulatePagingWhenScrolling);
|
|
3611
|
+
setActiveCellInternal(getCellNode(pos.row, pos.cell));
|
|
3612
|
+
activePosX = pos.posX;
|
|
3613
|
+
return true;
|
|
3614
|
+
} else {
|
|
3615
|
+
setActiveCellInternal(getCellNode(activeRow, activeCell));
|
|
3616
|
+
return false;
|
|
3617
|
+
}
|
|
3618
|
+
}
|
|
3619
|
+
|
|
3620
|
+
function getCellNode(row, cell) {
|
|
3621
|
+
if (rowsCache[row]) {
|
|
3622
|
+
ensureCellNodesInRowsCache(row);
|
|
3623
|
+
return rowsCache[row].cellNodesByColumnIdx[cell];
|
|
3624
|
+
}
|
|
3625
|
+
return null;
|
|
3626
|
+
}
|
|
3627
|
+
|
|
3628
|
+
function setActiveCell(row, cell, opt_editMode, preClickModeOn, suppressActiveCellChangedEvent) {
|
|
3629
|
+
if (!initialized) { return; }
|
|
3630
|
+
if (row > getDataLength() || row < 0 || cell >= columns.length || cell < 0) {
|
|
3631
|
+
return;
|
|
3632
|
+
}
|
|
3633
|
+
|
|
3634
|
+
if (!options.enableCellNavigation) {
|
|
3635
|
+
return;
|
|
3636
|
+
}
|
|
3637
|
+
|
|
3638
|
+
scrollCellIntoView(row, cell, false);
|
|
3639
|
+
setActiveCellInternal(getCellNode(row, cell), opt_editMode, preClickModeOn, suppressActiveCellChangedEvent);
|
|
3640
|
+
}
|
|
3641
|
+
|
|
3642
|
+
function canCellBeActive(row, cell) {
|
|
3643
|
+
if (!options.enableCellNavigation || row >= getDataLengthIncludingAddNew() ||
|
|
3644
|
+
row < 0 || cell >= columns.length || cell < 0) {
|
|
3645
|
+
return false;
|
|
3646
|
+
}
|
|
3647
|
+
|
|
3648
|
+
var rowMetadata = data.getItemMetadata && data.getItemMetadata(row);
|
|
3649
|
+
if (rowMetadata && typeof rowMetadata.focusable !== "undefined") {
|
|
3650
|
+
return !!rowMetadata.focusable;
|
|
3651
|
+
}
|
|
3652
|
+
|
|
3653
|
+
var columnMetadata = rowMetadata && rowMetadata.columns;
|
|
3654
|
+
if (columnMetadata && columnMetadata[columns[cell].id] && typeof columnMetadata[columns[cell].id].focusable !== "undefined") {
|
|
3655
|
+
return !!columnMetadata[columns[cell].id].focusable;
|
|
3656
|
+
}
|
|
3657
|
+
if (columnMetadata && columnMetadata[cell] && typeof columnMetadata[cell].focusable !== "undefined") {
|
|
3658
|
+
return !!columnMetadata[cell].focusable;
|
|
3659
|
+
}
|
|
3660
|
+
|
|
3661
|
+
return !!columns[cell].focusable;
|
|
3662
|
+
}
|
|
3663
|
+
|
|
3664
|
+
function canCellBeSelected(row, cell) {
|
|
3665
|
+
if (row >= getDataLength() || row < 0 || cell >= columns.length || cell < 0) {
|
|
3666
|
+
return false;
|
|
3667
|
+
}
|
|
3668
|
+
|
|
3669
|
+
var rowMetadata = data.getItemMetadata && data.getItemMetadata(row);
|
|
3670
|
+
if (rowMetadata && typeof rowMetadata.selectable !== "undefined") {
|
|
3671
|
+
return !!rowMetadata.selectable;
|
|
3672
|
+
}
|
|
3673
|
+
|
|
3674
|
+
var columnMetadata = rowMetadata && rowMetadata.columns && (rowMetadata.columns[columns[cell].id] || rowMetadata.columns[cell]);
|
|
3675
|
+
if (columnMetadata && typeof columnMetadata.selectable !== "undefined") {
|
|
3676
|
+
return !!columnMetadata.selectable;
|
|
3677
|
+
}
|
|
3678
|
+
|
|
3679
|
+
return !!columns[cell].selectable;
|
|
3680
|
+
}
|
|
3681
|
+
|
|
3682
|
+
function gotoCell(row, cell, forceEdit) {
|
|
3683
|
+
if (!initialized) { return; }
|
|
3684
|
+
if (!canCellBeActive(row, cell)) {
|
|
3685
|
+
return;
|
|
3686
|
+
}
|
|
3687
|
+
|
|
3688
|
+
if (!getEditorLock().commitCurrentEdit()) {
|
|
3689
|
+
return;
|
|
3690
|
+
}
|
|
3691
|
+
|
|
3692
|
+
scrollCellIntoView(row, cell, false);
|
|
3693
|
+
|
|
3694
|
+
var newCell = getCellNode(row, cell);
|
|
3695
|
+
|
|
3696
|
+
// if selecting the 'add new' row, start editing right away
|
|
3697
|
+
setActiveCellInternal(newCell, forceEdit || (row === getDataLength()) || options.autoEdit);
|
|
3698
|
+
|
|
3699
|
+
// if no editor was created, set the focus back on the grid
|
|
3700
|
+
if (!currentEditor) {
|
|
3701
|
+
setFocus();
|
|
3702
|
+
}
|
|
3703
|
+
}
|
|
3704
|
+
|
|
3705
|
+
|
|
3706
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
3707
|
+
// IEditor implementation for the editor lock
|
|
3708
|
+
|
|
3709
|
+
function commitCurrentEdit() {
|
|
3710
|
+
var item = getDataItem(activeRow);
|
|
3711
|
+
var column = columns[activeCell];
|
|
3712
|
+
|
|
3713
|
+
if (currentEditor) {
|
|
3714
|
+
if (currentEditor.isValueChanged()) {
|
|
3715
|
+
var validationResults = currentEditor.validate();
|
|
3716
|
+
|
|
3717
|
+
if (validationResults.valid) {
|
|
3718
|
+
if (activeRow < getDataLength()) {
|
|
3719
|
+
var editCommand = {
|
|
3720
|
+
row: activeRow,
|
|
3721
|
+
cell: activeCell,
|
|
3722
|
+
editor: currentEditor,
|
|
3723
|
+
serializedValue: currentEditor.serializeValue(),
|
|
3724
|
+
prevSerializedValue: serializedEditorValue,
|
|
3725
|
+
execute: function () {
|
|
3726
|
+
this.editor.applyValue(item, this.serializedValue);
|
|
3727
|
+
updateRow(this.row);
|
|
3728
|
+
trigger(self.onCellChange, {
|
|
3729
|
+
row: this.row,
|
|
3730
|
+
cell: this.cell,
|
|
3731
|
+
item: item,
|
|
3732
|
+
grid: self
|
|
3733
|
+
});
|
|
3734
|
+
},
|
|
3735
|
+
undo: function () {
|
|
3736
|
+
this.editor.applyValue(item, this.prevSerializedValue);
|
|
3737
|
+
updateRow(this.row);
|
|
3738
|
+
trigger(self.onCellChange, {
|
|
3739
|
+
row: this.row,
|
|
3740
|
+
cell: this.cell,
|
|
3741
|
+
item: item,
|
|
3742
|
+
grid: self
|
|
3743
|
+
});
|
|
3744
|
+
}
|
|
3745
|
+
};
|
|
3746
|
+
|
|
3747
|
+
if (options.editCommandHandler) {
|
|
3748
|
+
makeActiveCellNormal();
|
|
3749
|
+
options.editCommandHandler(item, column, editCommand);
|
|
3750
|
+
} else {
|
|
3751
|
+
editCommand.execute();
|
|
3752
|
+
makeActiveCellNormal();
|
|
3753
|
+
}
|
|
3754
|
+
|
|
3755
|
+
} else {
|
|
3756
|
+
var newItem = {};
|
|
3757
|
+
currentEditor.applyValue(newItem, currentEditor.serializeValue());
|
|
3758
|
+
makeActiveCellNormal();
|
|
3759
|
+
trigger(self.onAddNewRow, {item: newItem, column: column, grid: self});
|
|
3760
|
+
}
|
|
3761
|
+
|
|
3762
|
+
// check whether the lock has been re-acquired by event handlers
|
|
3763
|
+
return !getEditorLock().isActive();
|
|
3764
|
+
} else {
|
|
3765
|
+
// Re-add the CSS class to trigger transitions, if any.
|
|
3766
|
+
$(activeCellNode).removeClass("invalid");
|
|
3767
|
+
$(activeCellNode).width(); // force layout
|
|
3768
|
+
$(activeCellNode).addClass("invalid");
|
|
3769
|
+
|
|
3770
|
+
trigger(self.onValidationError, {
|
|
3771
|
+
editor: currentEditor,
|
|
3772
|
+
cellNode: activeCellNode,
|
|
3773
|
+
validationResults: validationResults,
|
|
3774
|
+
row: activeRow,
|
|
3775
|
+
cell: activeCell,
|
|
3776
|
+
column: column,
|
|
3777
|
+
grid: self
|
|
3778
|
+
});
|
|
3779
|
+
|
|
3780
|
+
currentEditor.focus();
|
|
3781
|
+
return false;
|
|
3782
|
+
}
|
|
3783
|
+
}
|
|
3784
|
+
|
|
3785
|
+
makeActiveCellNormal();
|
|
3786
|
+
}
|
|
3787
|
+
return true;
|
|
3788
|
+
}
|
|
3789
|
+
|
|
3790
|
+
function cancelCurrentEdit() {
|
|
3791
|
+
makeActiveCellNormal();
|
|
3792
|
+
return true;
|
|
3793
|
+
}
|
|
3794
|
+
|
|
3795
|
+
function rowsToRanges(rows) {
|
|
3796
|
+
var ranges = [];
|
|
3797
|
+
var lastCell = columns.length - 1;
|
|
3798
|
+
for (var i = 0; i < rows.length; i++) {
|
|
3799
|
+
ranges.push(new Slick.Range(rows[i], 0, rows[i], lastCell));
|
|
3800
|
+
}
|
|
3801
|
+
return ranges;
|
|
3802
|
+
}
|
|
3803
|
+
|
|
3804
|
+
function getSelectedRows() {
|
|
3805
|
+
if (!selectionModel) {
|
|
3806
|
+
throw new Error("Selection model is not set");
|
|
3807
|
+
}
|
|
3808
|
+
return selectedRows;
|
|
3809
|
+
}
|
|
3810
|
+
|
|
3811
|
+
function setSelectedRows(rows) {
|
|
3812
|
+
if (!selectionModel) {
|
|
3813
|
+
throw new Error("Selection model is not set");
|
|
3814
|
+
}
|
|
3815
|
+
selectionModel.setSelectedRanges(rowsToRanges(rows));
|
|
3816
|
+
}
|
|
3817
|
+
|
|
3818
|
+
|
|
3819
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
3820
|
+
// Debug
|
|
3821
|
+
|
|
3822
|
+
this.debug = function () {
|
|
3823
|
+
var s = "";
|
|
3824
|
+
|
|
3825
|
+
s += ("\n" + "counter_rows_rendered: " + counter_rows_rendered);
|
|
3826
|
+
s += ("\n" + "counter_rows_removed: " + counter_rows_removed);
|
|
3827
|
+
s += ("\n" + "renderedRows: " + renderedRows);
|
|
3828
|
+
s += ("\n" + "numVisibleRows: " + numVisibleRows);
|
|
3829
|
+
s += ("\n" + "maxSupportedCssHeight: " + maxSupportedCssHeight);
|
|
3830
|
+
s += ("\n" + "n(umber of pages): " + n);
|
|
3831
|
+
s += ("\n" + "(current) page: " + page);
|
|
3832
|
+
s += ("\n" + "page height (ph): " + ph);
|
|
3833
|
+
s += ("\n" + "vScrollDir: " + vScrollDir);
|
|
3834
|
+
|
|
3835
|
+
alert(s);
|
|
3836
|
+
};
|
|
3837
|
+
|
|
3838
|
+
// a debug helper to be able to access private members
|
|
3839
|
+
this.eval = function (expr) {
|
|
3840
|
+
return eval(expr);
|
|
3841
|
+
};
|
|
3842
|
+
|
|
3843
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
3844
|
+
// Public API
|
|
3845
|
+
|
|
3846
|
+
$.extend(this, {
|
|
3847
|
+
"slickGridVersion": "2.3.16",
|
|
3848
|
+
|
|
3849
|
+
// Events
|
|
3850
|
+
"onScroll": new Slick.Event(),
|
|
3851
|
+
"onSort": new Slick.Event(),
|
|
3852
|
+
"onHeaderMouseEnter": new Slick.Event(),
|
|
3853
|
+
"onHeaderMouseLeave": new Slick.Event(),
|
|
3854
|
+
"onHeaderContextMenu": new Slick.Event(),
|
|
3855
|
+
"onHeaderClick": new Slick.Event(),
|
|
3856
|
+
"onHeaderCellRendered": new Slick.Event(),
|
|
3857
|
+
"onBeforeHeaderCellDestroy": new Slick.Event(),
|
|
3858
|
+
"onHeaderRowCellRendered": new Slick.Event(),
|
|
3859
|
+
"onFooterRowCellRendered": new Slick.Event(),
|
|
3860
|
+
"onBeforeHeaderRowCellDestroy": new Slick.Event(),
|
|
3861
|
+
"onBeforeFooterRowCellDestroy": new Slick.Event(),
|
|
3862
|
+
"onMouseEnter": new Slick.Event(),
|
|
3863
|
+
"onMouseLeave": new Slick.Event(),
|
|
3864
|
+
"onClick": new Slick.Event(),
|
|
3865
|
+
"onDblClick": new Slick.Event(),
|
|
3866
|
+
"onContextMenu": new Slick.Event(),
|
|
3867
|
+
"onKeyDown": new Slick.Event(),
|
|
3868
|
+
"onAddNewRow": new Slick.Event(),
|
|
3869
|
+
"onBeforeAppendCell": new Slick.Event(),
|
|
3870
|
+
"onValidationError": new Slick.Event(),
|
|
3871
|
+
"onViewportChanged": new Slick.Event(),
|
|
3872
|
+
"onColumnsReordered": new Slick.Event(),
|
|
3873
|
+
"onColumnsResized": new Slick.Event(),
|
|
3874
|
+
"onCellChange": new Slick.Event(),
|
|
3875
|
+
"onBeforeEditCell": new Slick.Event(),
|
|
3876
|
+
"onBeforeCellEditorDestroy": new Slick.Event(),
|
|
3877
|
+
"onBeforeDestroy": new Slick.Event(),
|
|
3878
|
+
"onActiveCellChanged": new Slick.Event(),
|
|
3879
|
+
"onActiveCellPositionChanged": new Slick.Event(),
|
|
3880
|
+
"onDragInit": new Slick.Event(),
|
|
3881
|
+
"onDragStart": new Slick.Event(),
|
|
3882
|
+
"onDrag": new Slick.Event(),
|
|
3883
|
+
"onDragEnd": new Slick.Event(),
|
|
3884
|
+
"onSelectedRowsChanged": new Slick.Event(),
|
|
3885
|
+
"onCellCssStylesChanged": new Slick.Event(),
|
|
3886
|
+
|
|
3887
|
+
// Methods
|
|
3888
|
+
"registerPlugin": registerPlugin,
|
|
3889
|
+
"unregisterPlugin": unregisterPlugin,
|
|
3890
|
+
"getColumns": getColumns,
|
|
3891
|
+
"setColumns": setColumns,
|
|
3892
|
+
"getColumnIndex": getColumnIndex,
|
|
3893
|
+
"updateColumnHeader": updateColumnHeader,
|
|
3894
|
+
"setSortColumn": setSortColumn,
|
|
3895
|
+
"setSortColumns": setSortColumns,
|
|
3896
|
+
"getSortColumns": getSortColumns,
|
|
3897
|
+
"autosizeColumns": autosizeColumns,
|
|
3898
|
+
"getOptions": getOptions,
|
|
3899
|
+
"setOptions": setOptions,
|
|
3900
|
+
"getData": getData,
|
|
3901
|
+
"getDataLength": getDataLength,
|
|
3902
|
+
"getDataItem": getDataItem,
|
|
3903
|
+
"setData": setData,
|
|
3904
|
+
"getSelectionModel": getSelectionModel,
|
|
3905
|
+
"setSelectionModel": setSelectionModel,
|
|
3906
|
+
"getSelectedRows": getSelectedRows,
|
|
3907
|
+
"setSelectedRows": setSelectedRows,
|
|
3908
|
+
"getContainerNode": getContainerNode,
|
|
3909
|
+
"updatePagingStatusFromView": updatePagingStatusFromView,
|
|
3910
|
+
|
|
3911
|
+
"render": render,
|
|
3912
|
+
"invalidate": invalidate,
|
|
3913
|
+
"invalidateRow": invalidateRow,
|
|
3914
|
+
"invalidateRows": invalidateRows,
|
|
3915
|
+
"invalidateAllRows": invalidateAllRows,
|
|
3916
|
+
"updateCell": updateCell,
|
|
3917
|
+
"updateRow": updateRow,
|
|
3918
|
+
"getViewport": getVisibleRange,
|
|
3919
|
+
"getRenderedRange": getRenderedRange,
|
|
3920
|
+
"resizeCanvas": resizeCanvas,
|
|
3921
|
+
"updateRowCount": updateRowCount,
|
|
3922
|
+
"scrollRowIntoView": scrollRowIntoView,
|
|
3923
|
+
"scrollRowToTop": scrollRowToTop,
|
|
3924
|
+
"scrollCellIntoView": scrollCellIntoView,
|
|
3925
|
+
"scrollColumnIntoView": scrollColumnIntoView,
|
|
3926
|
+
"getCanvasNode": getCanvasNode,
|
|
3927
|
+
"getUID": getUID,
|
|
3928
|
+
"getHeaderColumnWidthDiff": getHeaderColumnWidthDiff,
|
|
3929
|
+
"getScrollbarDimensions": getScrollbarDimensions,
|
|
3930
|
+
"getHeadersWidth": getHeadersWidth,
|
|
3931
|
+
"getCanvasWidth": getCanvasWidth,
|
|
3932
|
+
"focus": setFocus,
|
|
3933
|
+
"scrollTo": scrollTo,
|
|
3934
|
+
|
|
3935
|
+
"getCellFromPoint": getCellFromPoint,
|
|
3936
|
+
"getCellFromEvent": getCellFromEvent,
|
|
3937
|
+
"getActiveCell": getActiveCell,
|
|
3938
|
+
"setActiveCell": setActiveCell,
|
|
3939
|
+
"getActiveCellNode": getActiveCellNode,
|
|
3940
|
+
"getActiveCellPosition": getActiveCellPosition,
|
|
3941
|
+
"resetActiveCell": resetActiveCell,
|
|
3942
|
+
"editActiveCell": makeActiveCellEditable,
|
|
3943
|
+
"getCellEditor": getCellEditor,
|
|
3944
|
+
"getCellNode": getCellNode,
|
|
3945
|
+
"getCellNodeBox": getCellNodeBox,
|
|
3946
|
+
"canCellBeSelected": canCellBeSelected,
|
|
3947
|
+
"canCellBeActive": canCellBeActive,
|
|
3948
|
+
"navigatePrev": navigatePrev,
|
|
3949
|
+
"navigateNext": navigateNext,
|
|
3950
|
+
"navigateUp": navigateUp,
|
|
3951
|
+
"navigateDown": navigateDown,
|
|
3952
|
+
"navigateLeft": navigateLeft,
|
|
3953
|
+
"navigateRight": navigateRight,
|
|
3954
|
+
"navigatePageUp": navigatePageUp,
|
|
3955
|
+
"navigatePageDown": navigatePageDown,
|
|
3956
|
+
"navigateTop": navigateTop,
|
|
3957
|
+
"navigateBottom": navigateBottom,
|
|
3958
|
+
"navigateRowStart": navigateRowStart,
|
|
3959
|
+
"navigateRowEnd": navigateRowEnd,
|
|
3960
|
+
"gotoCell": gotoCell,
|
|
3961
|
+
"getTopPanel": getTopPanel,
|
|
3962
|
+
"setTopPanelVisibility": setTopPanelVisibility,
|
|
3963
|
+
"getPreHeaderPanel": getPreHeaderPanel,
|
|
3964
|
+
"setPreHeaderPanelVisibility": setPreHeaderPanelVisibility,
|
|
3965
|
+
"getHeader": getHeader,
|
|
3966
|
+
"getHeaderColumn": getHeaderColumn,
|
|
3967
|
+
"setHeaderRowVisibility": setHeaderRowVisibility,
|
|
3968
|
+
"getHeaderRow": getHeaderRow,
|
|
3969
|
+
"getHeaderRowColumn": getHeaderRowColumn,
|
|
3970
|
+
"setFooterRowVisibility": setFooterRowVisibility,
|
|
3971
|
+
"getFooterRow": getFooterRow,
|
|
3972
|
+
"getFooterRowColumn": getFooterRowColumn,
|
|
3973
|
+
"getGridPosition": getGridPosition,
|
|
3974
|
+
"flashCell": flashCell,
|
|
3975
|
+
"addCellCssStyles": addCellCssStyles,
|
|
3976
|
+
"setCellCssStyles": setCellCssStyles,
|
|
3977
|
+
"removeCellCssStyles": removeCellCssStyles,
|
|
3978
|
+
"getCellCssStyles": getCellCssStyles,
|
|
3979
|
+
|
|
3980
|
+
"init": finishInitialization,
|
|
3981
|
+
"destroy": destroy,
|
|
3982
|
+
|
|
3983
|
+
// IEditor implementation
|
|
3984
|
+
"getEditorLock": getEditorLock,
|
|
3985
|
+
"getEditController": getEditController
|
|
3986
|
+
});
|
|
3987
|
+
|
|
3988
|
+
init();
|
|
3989
|
+
}
|
|
3990
|
+
}(jQuery));
|