Skip to content

Commit

Permalink
Add support for keyboard shortcuts that allow sorting columns (#10410)
Browse files Browse the repository at this point in the history
The PR adds support for new keyboard shortcuts that allows sorting the
column/multiple columns based on the currently selected column header. The
keyboard shortcuts are active only when the header is focused.

Expected working new keyboard shortcuts
* Enter Sorts the column (if the ColumnSorting or MultipleColumnSorting plugins
are enabled) in a specific order: Ascending > Descending > Restore original
order. If there is initialized the multiple columns order, the whole state is
cleared, and only the selected column is sorted;
* Ctrl/Cmd+Enter Sorts the column in the same order as above, and it works only
if the MultipleColumnSorting plugin is enabled. Sorting other columns does not
clear the previous columns sorting state but adds new sorting order to the
stack.
  • Loading branch information
budnix committed Jun 15, 2023
1 parent c61336b commit b848875
Show file tree
Hide file tree
Showing 8 changed files with 538 additions and 5 deletions.
8 changes: 8 additions & 0 deletions .changelogs/10410.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"issuesOrigin": "private",
"title": "Added support for column sorting using a keyboard shortcut.",
"type": "added",
"issueOrPR": 10410,
"breaking": false,
"framework": "none"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
describe('ColumnSorting keyboard shortcut', () => {
const id = 'testContainer';

beforeEach(function() {
this.$container = $(`<div id="${id}"></div>`).appendTo('body');
});

afterEach(function() {
if (this.$container) {
destroy();
this.$container.remove();
}
});

function columnHeader(renderedColumnIndex, TH) {
const visualColumnsIndex = renderedColumnIndex >= 0 ?
this.columnIndexMapper.getVisualFromRenderableIndex(renderedColumnIndex) : renderedColumnIndex;

this.view.appendColHeader(visualColumnsIndex, TH);
}

describe('"Enter"', () => {
it('should be possible to sort columns with correct sort order', () => {
handsontable({
data: createSpreadsheetData(3, 8),
colHeaders: true,
rowHeaders: true,
navigableHeaders: true,
columnSorting: true
});

selectCell(-1, 1);
keyDownUp('enter');

expect(getPlugin('columnSorting').getSortConfig()).toEqual([{
column: 1,
sortOrder: 'asc',
}]);

keyDownUp('enter');

expect(getPlugin('columnSorting').getSortConfig()).toEqual([{
column: 1,
sortOrder: 'desc',
}]);

keyDownUp('enter');

expect(getPlugin('columnSorting').getSortConfig()).toEqual([]);

keyDownUp('enter');

expect(getPlugin('columnSorting').getSortConfig()).toEqual([{
column: 1,
sortOrder: 'asc',
}]);

selectCell(-1, 3);
keyDownUp('enter');

expect(getPlugin('columnSorting').getSortConfig()).toEqual([{
column: 3,
sortOrder: 'asc',
}]);
});

it('should be possible to sort a column when a range of the columns are selected', () => {
handsontable({
data: createSpreadsheetData(3, 8),
colHeaders: true,
rowHeaders: true,
navigableHeaders: true,
columnSorting: true
});

selectColumns(1, 4, -1);
listen();
keyDownUp('enter');

expect(getPlugin('columnSorting').getSortConfig()).toEqual([{
column: 1,
sortOrder: 'asc',
}]);
});

it('should be possible to sort columns only by triggering the action from the lowest column header', () => {
handsontable({
data: createSpreadsheetData(3, 8),
colHeaders: true,
rowHeaders: true,
navigableHeaders: true,
columnSorting: true,
afterGetColumnHeaderRenderers(headerRenderers) {
headerRenderers.push(columnHeader.bind(this));
headerRenderers.push(columnHeader.bind(this));
},
});

selectCell(-1, -1); // corner
keyDownUp('enter');

expect(getPlugin('columnSorting').getSortConfig()).toEqual([]);

selectCell(1, -1); // row header
keyDownUp('enter');

expect(getPlugin('columnSorting').getSortConfig()).toEqual([]);

selectCell(-3, 1); // the first (top) column header
keyDownUp('enter');

expect(getPlugin('columnSorting').getSortConfig()).toEqual([]);

selectCell(-2, 1); // the second column header
keyDownUp('enter');

expect(getPlugin('columnSorting').getSortConfig()).toEqual([]);

selectCell(-1, 1); // the third (bottom) column header
keyDownUp('enter');

expect(getPlugin('columnSorting').getSortConfig()).toEqual([{
column: 1,
sortOrder: 'asc',
}]);
});

it('should not trigger the editor to be opened', () => {
handsontable({
data: createSpreadsheetData(3, 8),
colHeaders: true,
rowHeaders: true,
navigableHeaders: true,
columnSorting: true,
});

selectCell(-1, 1);
keyDownUp('enter');

expect(getActiveEditor()).toBeUndefined();
});
});
});
40 changes: 38 additions & 2 deletions handsontable/src/plugins/columnSorting/columnSorting.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ import { registerRootComparator, sort } from './sortService';

export const PLUGIN_KEY = 'columnSorting';
export const PLUGIN_PRIORITY = 50;
const APPEND_COLUMN_CONFIG_STRATEGY = 'append';
const REPLACE_COLUMN_CONFIG_STRATEGY = 'replace';
export const APPEND_COLUMN_CONFIG_STRATEGY = 'append';
export const REPLACE_COLUMN_CONFIG_STRATEGY = 'replace';
const SHORTCUTS_GROUP = PLUGIN_KEY;

registerRootComparator(PLUGIN_KEY, rootComparator);

Expand Down Expand Up @@ -164,6 +165,7 @@ export class ColumnSorting extends BasePlugin {
this.loadOrSortBySettings();
}

this.registerShortcuts();
super.enablePlugin();
}

Expand Down Expand Up @@ -199,9 +201,43 @@ export class ColumnSorting extends BasePlugin {
this.columnMetaCache = null;
this.columnStatesManager = null;

this.unregisterShortcuts();
super.disablePlugin();
}

/**
* Register shortcuts responsible for toggling column sorting functionality.
*
* @private
*/
registerShortcuts() {
this.hot.getShortcutManager()
.getContext('grid')
.addShortcut({
keys: [['Enter']],
callback: () => {
const { highlight } = this.hot.getSelectedRangeLast();

if (highlight.row === -1 && highlight.col >= 0) {
this.sort(this.getColumnNextConfig(highlight.col));
}
},
runOnlyIf: () => this.hot.getSelectedRangeLast()?.highlight.isHeader(),
group: SHORTCUTS_GROUP,
});
}

/**
* Unregister shortcuts responsible for toggling column sorting functionality.
*
* @private
*/
unregisterShortcuts() {
this.hot.getShortcutManager()
.getContext('grid')
.removeShortcutsByGroup(SHORTCUTS_GROUP);
}

// DIFF - MultiColumnSorting & ColumnSorting: changed function documentation.
/**
* Sorts the table by chosen columns and orders.
Expand Down
2 changes: 2 additions & 0 deletions handsontable/src/plugins/columnSorting/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ export {
PLUGIN_KEY,
PLUGIN_PRIORITY,
ColumnSorting,
APPEND_COLUMN_CONFIG_STRATEGY,
REPLACE_COLUMN_CONFIG_STRATEGY
} from './columnSorting';

0 comments on commit b848875

Please sign in to comment.