--- /dev/null
+(function ($) {
+ // register namespace
+ $.extend(true, window, {
+ "Slick": {
+ "CellSelectionModel": CellSelectionModel
+ }
+ });
+
+
+ function CellSelectionModel(options) {
+ var _grid;
+ var _canvas;
+ var _ranges = [];
+ var _self = this;
+ var _selector = new Slick.CellRangeSelector({
+ "selectionCss": {
+ "border": "2px solid black"
+ }
+ });
+ var _options;
+ var _defaults = {
+ selectActiveCell: true
+ };
+
+
+ function init(grid) {
+ _options = $.extend(true, {}, _defaults, options);
+ _grid = grid;
+ _canvas = _grid.getCanvasNode();
+ _grid.onActiveCellChanged.subscribe(handleActiveCellChange);
+ _grid.onKeyDown.subscribe(handleKeyDown);
+ grid.registerPlugin(_selector);
+ _selector.onCellRangeSelected.subscribe(handleCellRangeSelected);
+ _selector.onBeforeCellRangeSelected.subscribe(handleBeforeCellRangeSelected);
+ }
+
+ function destroy() {
+ _grid.onActiveCellChanged.unsubscribe(handleActiveCellChange);
+ _grid.onKeyDown.unsubscribe(handleKeyDown);
+ _selector.onCellRangeSelected.unsubscribe(handleCellRangeSelected);
+ _selector.onBeforeCellRangeSelected.unsubscribe(handleBeforeCellRangeSelected);
+ _grid.unregisterPlugin(_selector);
+ }
+
+ function removeInvalidRanges(ranges) {
+ var result = [];
+
+ for (var i = 0; i < ranges.length; i++) {
+ var r = ranges[i];
+ if (_grid.canCellBeSelected(r.fromRow, r.fromCell) && _grid.canCellBeSelected(r.toRow, r.toCell)) {
+ result.push(r);
+ }
+ }
+
+ return result;
+ }
+
+ function setSelectedRanges(ranges) {
+ _ranges = removeInvalidRanges(ranges);
+ _self.onSelectedRangesChanged.notify(_ranges);
+ }
+
+ function getSelectedRanges() {
+ return _ranges;
+ }
+
+ function handleBeforeCellRangeSelected(e, args) {
+ if (_grid.getEditorLock().isActive()) {
+ e.stopPropagation();
+ return false;
+ }
+ }
+
+ function handleCellRangeSelected(e, args) {
+ setSelectedRanges([args.range]);
+ }
+
+ function handleActiveCellChange(e, args) {
+ if (_options.selectActiveCell && args.row != null && args.cell != null) {
+ setSelectedRanges([new Slick.Range(args.row, args.cell)]);
+ }
+ }
+
+ function handleKeyDown(e) {
+ /***
+ * Кey codes
+ * 37 left
+ * 38 up
+ * 39 right
+ * 40 down
+ */
+ var ranges, last;
+ var active = _grid.getActiveCell();
+
+ if ( active && e.shiftKey && !e.ctrlKey && !e.altKey &&
+ (e.which == 37 || e.which == 39 || e.which == 38 || e.which == 40) ) {
+
+ ranges = getSelectedRanges();
+ if (!ranges.length)
+ ranges.push(new Slick.Range(active.row, active.cell));
+
+ // keyboard can work with last range only
+ last = ranges.pop();
+
+ // can't handle selection out of active cell
+ if (!last.contains(active.row, active.cell))
+ last = new Slick.Range(active.row, active.cell);
+
+ var dRow = last.toRow - last.fromRow,
+ dCell = last.toCell - last.fromCell,
+ // walking direction
+ dirRow = active.row == last.fromRow ? 1 : -1,
+ dirCell = active.cell == last.fromCell ? 1 : -1;
+
+ if (e.which == 37) {
+ dCell -= dirCell;
+ } else if (e.which == 39) {
+ dCell += dirCell ;
+ } else if (e.which == 38) {
+ dRow -= dirRow;
+ } else if (e.which == 40) {
+ dRow += dirRow;
+ }
+
+ // define new selection range
+ var new_last = new Slick.Range(active.row, active.cell, active.row + dirRow*dRow, active.cell + dirCell*dCell);
+ if (removeInvalidRanges([new_last]).length) {
+ ranges.push(new_last);
+ var viewRow = dirRow > 0 ? new_last.toRow : new_last.fromRow;
+ var viewCell = dirCell > 0 ? new_last.toCell : new_last.fromCell;
+ _grid.scrollRowIntoView(viewRow);
+ _grid.scrollCellIntoView(viewRow, viewCell);
+ }
+ else
+ ranges.push(last);
+
+ setSelectedRanges(ranges);
+
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ }
+
+ $.extend(this, {
+ "getSelectedRanges": getSelectedRanges,
+ "setSelectedRanges": setSelectedRanges,
+
+ "init": init,
+ "destroy": destroy,
+
+ "onSelectedRangesChanged": new Slick.Event()
+ });
+ }
+})(jQuery);