slickgrid added to third-party
[myslice.git] / third-party / slickgrid-2.1 / plugins / slick.rowselectionmodel.js
1 (function ($) {
2   // register namespace
3   $.extend(true, window, {
4     "Slick": {
5       "RowSelectionModel": RowSelectionModel
6     }
7   });
8
9   function RowSelectionModel(options) {
10     var _grid;
11     var _ranges = [];
12     var _self = this;
13     var _handler = new Slick.EventHandler();
14     var _inHandler;
15     var _options;
16     var _defaults = {
17       selectActiveRow: true
18     };
19
20     function init(grid) {
21       _options = $.extend(true, {}, _defaults, options);
22       _grid = grid;
23       _handler.subscribe(_grid.onActiveCellChanged,
24           wrapHandler(handleActiveCellChange));
25       _handler.subscribe(_grid.onKeyDown,
26           wrapHandler(handleKeyDown));
27       _handler.subscribe(_grid.onClick,
28           wrapHandler(handleClick));
29     }
30
31     function destroy() {
32       _handler.unsubscribeAll();
33     }
34
35     function wrapHandler(handler) {
36       return function () {
37         if (!_inHandler) {
38           _inHandler = true;
39           handler.apply(this, arguments);
40           _inHandler = false;
41         }
42       };
43     }
44
45     function rangesToRows(ranges) {
46       var rows = [];
47       for (var i = 0; i < ranges.length; i++) {
48         for (var j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
49           rows.push(j);
50         }
51       }
52       return rows;
53     }
54
55     function rowsToRanges(rows) {
56       var ranges = [];
57       var lastCell = _grid.getColumns().length - 1;
58       for (var i = 0; i < rows.length; i++) {
59         ranges.push(new Slick.Range(rows[i], 0, rows[i], lastCell));
60       }
61       return ranges;
62     }
63
64     function getRowsRange(from, to) {
65       var i, rows = [];
66       for (i = from; i <= to; i++) {
67         rows.push(i);
68       }
69       for (i = to; i < from; i++) {
70         rows.push(i);
71       }
72       return rows;
73     }
74
75     function getSelectedRows() {
76       return rangesToRows(_ranges);
77     }
78
79     function setSelectedRows(rows) {
80       setSelectedRanges(rowsToRanges(rows));
81     }
82
83     function setSelectedRanges(ranges) {
84       _ranges = ranges;
85       _self.onSelectedRangesChanged.notify(_ranges);
86     }
87
88     function getSelectedRanges() {
89       return _ranges;
90     }
91
92     function handleActiveCellChange(e, data) {
93       if (_options.selectActiveRow && data.row != null) {
94         setSelectedRanges([new Slick.Range(data.row, 0, data.row, _grid.getColumns().length - 1)]);
95       }
96     }
97
98     function handleKeyDown(e) {
99       var activeRow = _grid.getActiveCell();
100       if (activeRow && e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey && (e.which == 38 || e.which == 40)) {
101         var selectedRows = getSelectedRows();
102         selectedRows.sort(function (x, y) {
103           return x - y
104         });
105
106         if (!selectedRows.length) {
107           selectedRows = [activeRow.row];
108         }
109
110         var top = selectedRows[0];
111         var bottom = selectedRows[selectedRows.length - 1];
112         var active;
113
114         if (e.which == 40) {
115           active = activeRow.row < bottom || top == bottom ? ++bottom : ++top;
116         } else {
117           active = activeRow.row < bottom ? --bottom : --top;
118         }
119
120         if (active >= 0 && active < _grid.getDataLength()) {
121           _grid.scrollRowIntoView(active);
122           _ranges = rowsToRanges(getRowsRange(top, bottom));
123           setSelectedRanges(_ranges);
124         }
125
126         e.preventDefault();
127         e.stopPropagation();
128       }
129     }
130
131     function handleClick(e) {
132       var cell = _grid.getCellFromEvent(e);
133       if (!cell || !_grid.canCellBeActive(cell.row, cell.cell)) {
134         return false;
135       }
136
137       var selection = rangesToRows(_ranges);
138       var idx = $.inArray(cell.row, selection);
139
140       if (!e.ctrlKey && !e.shiftKey && !e.metaKey) {
141         return false;
142       }
143       else if (_grid.getOptions().multiSelect) {
144         if (idx === -1 && (e.ctrlKey || e.metaKey)) {
145           selection.push(cell.row);
146           _grid.setActiveCell(cell.row, cell.cell);
147         } else if (idx !== -1 && (e.ctrlKey || e.metaKey)) {
148           selection = $.grep(selection, function (o, i) {
149             return (o !== cell.row);
150           });
151           _grid.setActiveCell(cell.row, cell.cell);
152         } else if (selection.length && e.shiftKey) {
153           var last = selection.pop();
154           var from = Math.min(cell.row, last);
155           var to = Math.max(cell.row, last);
156           selection = [];
157           for (var i = from; i <= to; i++) {
158             if (i !== last) {
159               selection.push(i);
160             }
161           }
162           selection.push(last);
163           _grid.setActiveCell(cell.row, cell.cell);
164         }
165       }
166
167       _ranges = rowsToRanges(selection);
168       setSelectedRanges(_ranges);
169       e.stopImmediatePropagation();
170
171       return true;
172     }
173
174     $.extend(this, {
175       "getSelectedRows": getSelectedRows,
176       "setSelectedRows": setSelectedRows,
177
178       "getSelectedRanges": getSelectedRanges,
179       "setSelectedRanges": setSelectedRanges,
180
181       "init": init,
182       "destroy": destroy,
183
184       "onSelectedRangesChanged": new Slick.Event()
185     });
186   }
187 })(jQuery);