Skip to content

Commit

Permalink
Merge pull request #1707 from ghiscoding/bugfix/column-picker-autopos
Browse files Browse the repository at this point in the history
fix: Column Picker should auto-position left/right with available space
  • Loading branch information
ghiscoding authored Oct 10, 2024
2 parents 359ccbf + 801ea8c commit cd6cb96
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 2 deletions.
21 changes: 21 additions & 0 deletions packages/common/src/extensions/__tests__/slickColumnPicker.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const gridStub = {
applyHtmlCode: (elm, val) => elm.innerHTML = val || '',
getColumnIndex: vi.fn(),
getColumns: vi.fn(),
getGridPosition: vi.fn(),
getOptions: vi.fn(),
getSelectedRows: vi.fn(),
getUID: () => gridUid,
Expand Down Expand Up @@ -362,6 +363,26 @@ describe('ColumnPickerControl', () => {
expect(control.menuElement?.classList.contains('slick-dark-mode')).toBeTruthy();
});

it('should reposition menu to the left when no available space on the right', () => {
vi.spyOn(gridStub, 'getGridPosition').mockReturnValue({ left: 50, top: 0, right: 0, bottom: 200, height: 22, width: 300, visible: true });
vi.spyOn(gridStub, 'getColumnIndex').mockReturnValue(undefined as any).mockReturnValue(1);

control.init();

const groupElm = createDomElement('div', { className: 'slick-column-name' });
gridStub.onPreHeaderContextMenu.notify({ node: groupElm, grid: gridStub }, { ...new SlickEventData(), preventDefault: vi.fn(), target: groupElm, pageX: 305 } as any, gridStub);
vi.spyOn(control, 'createPickerMenu').mockImplementation(() => {
if (control.menuElement) {
Object.defineProperty(control.menuElement, 'clientWidth', { writable: true, value: 122 });
return control.menuElement;
}
return document.createElement('div');
});
gridStub.onPreHeaderContextMenu.notify({ node: groupElm, grid: gridStub }, { ...new SlickEventData(), preventDefault: vi.fn(), target: groupElm, pageX: 305 } as any, gridStub);
Object.defineProperty(control.menuElement, 'clientWidth', { writable: true, value: 122 });
expect(control.menuElement?.style.left).toBe('183px');
});

describe('onColumnsReordered event', () => {
it('should reorder some columns', () => {
const columnsUnorderedMock: Column[] = [
Expand Down
12 changes: 10 additions & 2 deletions packages/common/src/extensions/slickColumnPicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ export class SlickColumnPicker {
/** Mouse header context handler when doing a right+click on any of the header column title */
protected handleHeaderContextMenu(e: SlickEventData): void {
e.preventDefault();
emptyElement(this._listElm);
emptyElement(this._menuElm);
this._columnCheckboxes = [];

this._menuElm = this.createPickerMenu();
Expand All @@ -221,8 +221,16 @@ export class SlickColumnPicker {
protected repositionMenu(event: DOMMouseOrTouchEvent<HTMLDivElement> | SlickEventData): void {
const targetEvent: MouseEvent | Touch = (event as TouchEvent)?.touches?.[0] ?? event;
if (this._menuElm) {
// auto-positioned menu left/right by available viewport space
const gridPos = this.grid.getGridPosition();
const menuWidth = this._menuElm.clientWidth || 0;
let menuOffsetLeft = targetEvent.pageX || 0;
if (gridPos?.width && (menuOffsetLeft + menuWidth >= gridPos.width)) {
menuOffsetLeft = menuOffsetLeft - menuWidth;
}

this._menuElm.style.top = `${targetEvent.pageY - 10}px`;
this._menuElm.style.left = `${targetEvent.pageX - 10}px`;
this._menuElm.style.left = `${menuOffsetLeft}px`;
this._menuElm.style.minHeight = findWidthOrDefault(this.addonOptions.minHeight, '');
this._menuElm.style.maxHeight = findWidthOrDefault(this.addonOptions.maxHeight, `${window.innerHeight - targetEvent.clientY}px`);
this._menuElm.style.display = 'block';
Expand Down

0 comments on commit cd6cb96

Please sign in to comment.