mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-01-27 16:57:00 -06:00
242 lines
7.3 KiB
JavaScript
242 lines
7.3 KiB
JavaScript
/////////////////////////////////////////////////////////////
|
|
//
|
|
// pgAdmin 4 - PostgreSQL Tools
|
|
//
|
|
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
|
// This software is released under the PostgreSQL Licence
|
|
//
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
define([
|
|
'jquery',
|
|
'underscore',
|
|
'sources/selection/range_selection_helper',
|
|
'sources/window',
|
|
'slickgrid',
|
|
], function ($, _, RangeSelectionHelper, pgWindow) {
|
|
var XCellSelectionModel = function (options) {
|
|
|
|
var KEY_ARROW_RIGHT = 39;
|
|
var KEY_ARROW_LEFT = 37;
|
|
var KEY_ARROW_UP = 38;
|
|
var KEY_ARROW_DOWN = 40;
|
|
|
|
var Slick = window.Slick;
|
|
var _grid;
|
|
var _ranges = [];
|
|
var _self = this;
|
|
var _selector = new Slick.CellRangeSelector({
|
|
selectionCss: {
|
|
border: '2px solid black',
|
|
},
|
|
offset: {
|
|
top: 0,
|
|
left: -1,
|
|
height: 2,
|
|
width: 1,
|
|
},
|
|
});
|
|
var _options;
|
|
var _defaults = {
|
|
selectActiveCell: true,
|
|
};
|
|
|
|
|
|
function init(grid) {
|
|
_options = $.extend(true, {}, _defaults, options);
|
|
_grid = grid;
|
|
_grid.onActiveCellChanged.subscribe(handleActiveCellChange);
|
|
_grid.onKeyDown.subscribe(handleKeyDown);
|
|
grid.registerPlugin(_selector);
|
|
_selector.onCellRangeSelected.subscribe(handleCellRangeSelected);
|
|
_selector.onBeforeCellRangeSelected.subscribe(handleBeforeCellRangeSelected);
|
|
$(pgWindow.default).on('mouseup',handleWindowMouseUp);
|
|
}
|
|
|
|
function destroy() {
|
|
_grid.onActiveCellChanged.unsubscribe(handleActiveCellChange);
|
|
_grid.onKeyDown.unsubscribe(handleKeyDown);
|
|
_selector.onCellRangeSelected.unsubscribe(handleCellRangeSelected);
|
|
_selector.onBeforeCellRangeSelected.unsubscribe(handleBeforeCellRangeSelected);
|
|
_grid.unregisterPlugin(_selector);
|
|
$(pgWindow.default).off('mouseup', handleWindowMouseUp);
|
|
}
|
|
|
|
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) {
|
|
// simple check for: empty selection didn't change, prevent firing onSelectedRangesChanged
|
|
if ((!_ranges || _ranges.length === 0) && (!ranges || ranges.length === 0)) { return; }
|
|
|
|
_ranges = removeInvalidRanges(ranges);
|
|
_self.onSelectedRangesChanged.notify(_ranges);
|
|
}
|
|
|
|
function getSelectedRanges() {
|
|
return _ranges;
|
|
}
|
|
|
|
function setSelectedRows(rows) {
|
|
_ranges = [];
|
|
|
|
for(var i = 0 ; i < rows.length ; i++) {
|
|
_ranges.push(RangeSelectionHelper.rangeForRow(_grid, rows[i]));
|
|
}
|
|
}
|
|
|
|
function handleBeforeCellRangeSelected(e) {
|
|
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 arrowKeyPressed(event) {
|
|
return event.which == KEY_ARROW_RIGHT
|
|
|| event.which == KEY_ARROW_LEFT
|
|
|| event.which == KEY_ARROW_UP
|
|
|| event.which == KEY_ARROW_DOWN;
|
|
}
|
|
|
|
function shiftArrowKeyPressed(event) {
|
|
return event.shiftKey && !event.ctrlKey && !event.altKey &&
|
|
(arrowKeyPressed(event));
|
|
}
|
|
|
|
function needUpdateRange(newRange) {
|
|
return removeInvalidRanges([newRange]).length;
|
|
}
|
|
|
|
function handleKeyDown(e) {
|
|
var ranges;
|
|
var lastSelectedRange;
|
|
var anchorActiveCell = _grid.getActiveCell();
|
|
|
|
function isKey(key) { return e.which === key; }
|
|
|
|
function getKeycode() { return e.which; }
|
|
|
|
function shouldScrollToBottommostRow() { return anchorActiveCell.row === newSelectedRange.fromRow; }
|
|
|
|
function shouldScrollToRightmostColumn() { return anchorActiveCell.cell === newSelectedRange.fromCell; }
|
|
|
|
function getMobileCellFromRange(range, activeCell) {
|
|
var localMobileCell = {};
|
|
|
|
localMobileCell.row = range.fromRow === activeCell.row ? range.toRow : range.fromRow;
|
|
localMobileCell.cell = range.fromCell === activeCell.cell ? range.toCell : range.fromCell;
|
|
|
|
return localMobileCell;
|
|
}
|
|
|
|
function getNewRange(rangeCorner, oppositeCorner) {
|
|
var newFromCell = rangeCorner.cell <= oppositeCorner.cell ? rangeCorner.cell : oppositeCorner.cell;
|
|
var newToCell = rangeCorner.cell <= oppositeCorner.cell ? oppositeCorner.cell : rangeCorner.cell;
|
|
|
|
var newFromRow = rangeCorner.row <= oppositeCorner.row ? rangeCorner.row : oppositeCorner.row;
|
|
var newToRow = rangeCorner.row <= oppositeCorner.row ? oppositeCorner.row : rangeCorner.row;
|
|
|
|
return new Slick.Range(
|
|
newFromRow,
|
|
newFromCell,
|
|
newToRow,
|
|
newToCell
|
|
);
|
|
}
|
|
|
|
if (anchorActiveCell && shiftArrowKeyPressed(e)) {
|
|
ranges = getSelectedRanges();
|
|
if (!ranges.length) {
|
|
ranges.push(new Slick.Range(anchorActiveCell.row, anchorActiveCell.cell));
|
|
}
|
|
|
|
// keyboard can work with last range only
|
|
lastSelectedRange = ranges.pop();
|
|
|
|
// can't handle selection out of active cell
|
|
if (!lastSelectedRange.contains(anchorActiveCell.row, anchorActiveCell.cell)) {
|
|
lastSelectedRange = new Slick.Range(anchorActiveCell.row, anchorActiveCell.cell);
|
|
}
|
|
|
|
var mobileCell = getMobileCellFromRange(lastSelectedRange, anchorActiveCell);
|
|
|
|
switch (getKeycode()) {
|
|
case KEY_ARROW_LEFT:
|
|
mobileCell.cell -= 1;
|
|
break;
|
|
case KEY_ARROW_RIGHT:
|
|
mobileCell.cell += 1;
|
|
break;
|
|
case KEY_ARROW_UP:
|
|
mobileCell.row -= 1;
|
|
break;
|
|
case KEY_ARROW_DOWN:
|
|
mobileCell.row += 1;
|
|
break;
|
|
}
|
|
|
|
var newSelectedRange = getNewRange(anchorActiveCell, mobileCell);
|
|
|
|
if (needUpdateRange(newSelectedRange)) {
|
|
var rowToView = shouldScrollToBottommostRow() ? newSelectedRange.toRow : newSelectedRange.fromRow;
|
|
var columnToView = shouldScrollToRightmostColumn() ? newSelectedRange.toCell : newSelectedRange.fromCell;
|
|
|
|
if (isKey(KEY_ARROW_RIGHT) || isKey(KEY_ARROW_LEFT)) {
|
|
_grid.scrollColumnIntoView(columnToView);
|
|
} else if (isKey(KEY_ARROW_UP) || isKey(KEY_ARROW_DOWN)) {
|
|
_grid.scrollRowIntoView(rowToView);
|
|
}
|
|
ranges.push(newSelectedRange);
|
|
} else {
|
|
ranges.push(lastSelectedRange);
|
|
}
|
|
|
|
setSelectedRanges(ranges);
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
}
|
|
}
|
|
|
|
function handleWindowMouseUp() {
|
|
var selectedRange = _selector.getCurrentRange();
|
|
if (!_.isUndefined(selectedRange)) {
|
|
_grid.onDragEnd.notify({range: selectedRange});
|
|
}
|
|
}
|
|
|
|
$.extend(this, {
|
|
'getSelectedRanges': getSelectedRanges,
|
|
'setSelectedRanges': setSelectedRanges,
|
|
'setSelectedRows': setSelectedRows,
|
|
|
|
'init': init,
|
|
'destroy': destroy,
|
|
|
|
'onSelectedRangesChanged': new Slick.Event(),
|
|
});
|
|
};
|
|
return XCellSelectionModel;
|
|
});
|