UNPKG

6.09 kBJavaScriptView Raw
1(function ($) {
2 // register namespace
3 $.extend(true, window, {
4 "Slick": {
5 "CellSelectionModel": CellSelectionModel
6 }
7 });
8
9 function CellSelectionModel(options) {
10 var _grid;
11 var _canvas;
12 var _ranges = [];
13 var _self = this;
14 var _selector;
15
16 if (typeof options === "undefined" || typeof options.cellRangeSelector === "undefined") {
17 _selector = new Slick.CellRangeSelector({
18 "selectionCss": {
19 "border": "2px solid black"
20 }
21 });
22 } else {
23 _selector = options.cellRangeSelector;
24 }
25
26 var _options;
27 var _defaults = {
28 selectActiveCell: true
29 };
30
31 function init(grid) {
32 _options = $.extend(true, {}, _defaults, options);
33 _grid = grid;
34 _canvas = _grid.getCanvasNode();
35 _grid.onActiveCellChanged.subscribe(handleActiveCellChange);
36 _grid.onKeyDown.subscribe(handleKeyDown);
37 grid.registerPlugin(_selector);
38 _selector.onCellRangeSelected.subscribe(handleCellRangeSelected);
39 _selector.onBeforeCellRangeSelected.subscribe(handleBeforeCellRangeSelected);
40 }
41
42 function destroy() {
43 _grid.onActiveCellChanged.unsubscribe(handleActiveCellChange);
44 _grid.onKeyDown.unsubscribe(handleKeyDown);
45 _selector.onCellRangeSelected.unsubscribe(handleCellRangeSelected);
46 _selector.onBeforeCellRangeSelected.unsubscribe(handleBeforeCellRangeSelected);
47 _grid.unregisterPlugin(_selector);
48 _canvas = null;
49 if (_selector && _selector.destroy) {
50 _selector.destroy();
51 }
52 }
53
54 function removeInvalidRanges(ranges) {
55 var result = [];
56
57 for (var i = 0; i < ranges.length; i++) {
58 var r = ranges[i];
59 if (_grid.canCellBeSelected(r.fromRow, r.fromCell) && _grid.canCellBeSelected(r.toRow, r.toCell)) {
60 result.push(r);
61 }
62 }
63
64 return result;
65 }
66
67 function rangesAreEqual(range1, range2) {
68 var areDifferent = (range1.length !== range2.length);
69 if (!areDifferent) {
70 for (var i = 0; i < range1.length; i++) {
71 if (
72 range1[i].fromCell !== range2[i].fromCell
73 || range1[i].fromRow !== range2[i].fromRow
74 || range1[i].toCell !== range2[i].toCell
75 || range1[i].toRow !== range2[i].toRow
76 ) {
77 areDifferent = true;
78 break;
79 }
80 }
81 }
82 return !areDifferent;
83 }
84
85 function setSelectedRanges(ranges) {
86 // simple check for: empty selection didn't change, prevent firing onSelectedRangesChanged
87 if ((!_ranges || _ranges.length === 0) && (!ranges || ranges.length === 0)) { return; }
88
89 // if range has not changed, don't fire onSelectedRangesChanged
90 var rangeHasChanged = !rangesAreEqual(_ranges, ranges);
91
92 _ranges = removeInvalidRanges(ranges);
93 if (rangeHasChanged) { _self.onSelectedRangesChanged.notify(_ranges); }
94 }
95
96 function getSelectedRanges() {
97 return _ranges;
98 }
99
100 function handleBeforeCellRangeSelected(e, args) {
101 if (_grid.getEditorLock().isActive()) {
102 e.stopPropagation();
103 return false;
104 }
105 }
106
107 function handleCellRangeSelected(e, args) {
108 _grid.setActiveCell(args.range.fromRow, args.range.fromCell, false, false, true);
109 setSelectedRanges([args.range]);
110 }
111
112 function handleActiveCellChange(e, args) {
113 if (_options.selectActiveCell && args.row != null && args.cell != null) {
114 setSelectedRanges([new Slick.Range(args.row, args.cell)]);
115 }
116 else if (!_options.selectActiveCell) {
117 // clear the previous selection once the cell changes
118 setSelectedRanges([]);
119 }
120 }
121
122 function handleKeyDown(e) {
123 /***
124 * Кey codes
125 * 37 left
126 * 38 up
127 * 39 right
128 * 40 down
129 */
130 var ranges, last;
131 var active = _grid.getActiveCell();
132 var metaKey = e.ctrlKey || e.metaKey;
133
134 if (active && e.shiftKey && !metaKey && !e.altKey &&
135 (e.which == 37 || e.which == 39 || e.which == 38 || e.which == 40)) {
136
137 ranges = getSelectedRanges().slice();
138 if (!ranges.length)
139 ranges.push(new Slick.Range(active.row, active.cell));
140
141 // keyboard can work with last range only
142 last = ranges.pop();
143
144 // can't handle selection out of active cell
145 if (!last.contains(active.row, active.cell))
146 last = new Slick.Range(active.row, active.cell);
147
148 var dRow = last.toRow - last.fromRow,
149 dCell = last.toCell - last.fromCell,
150 // walking direction
151 dirRow = active.row == last.fromRow ? 1 : -1,
152 dirCell = active.cell == last.fromCell ? 1 : -1;
153
154 if (e.which == 37) {
155 dCell -= dirCell;
156 } else if (e.which == 39) {
157 dCell += dirCell;
158 } else if (e.which == 38) {
159 dRow -= dirRow;
160 } else if (e.which == 40) {
161 dRow += dirRow;
162 }
163
164 // define new selection range
165 var new_last = new Slick.Range(active.row, active.cell, active.row + dirRow * dRow, active.cell + dirCell * dCell);
166 if (removeInvalidRanges([new_last]).length) {
167 ranges.push(new_last);
168 var viewRow = dirRow > 0 ? new_last.toRow : new_last.fromRow;
169 var viewCell = dirCell > 0 ? new_last.toCell : new_last.fromCell;
170 _grid.scrollRowIntoView(viewRow);
171 _grid.scrollCellIntoView(viewRow, viewCell);
172 }
173 else
174 ranges.push(last);
175
176 setSelectedRanges(ranges);
177
178 e.preventDefault();
179 e.stopPropagation();
180 }
181 }
182
183 $.extend(this, {
184 "getSelectedRanges": getSelectedRanges,
185 "setSelectedRanges": setSelectedRanges,
186
187 "init": init,
188 "destroy": destroy,
189 "pluginName": "CellSelectionModel",
190
191 "onSelectedRangesChanged": new Slick.Event()
192 });
193 }
194})(jQuery);