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