Skip to content

Commit f4fffa8

Browse files
committed
feat: implement double-click auto-fit for dgrid columns
Signed-off-by: Gordon Smith <GordonJSmith@gmail.com>
1 parent c37c597 commit f4fffa8

File tree

9 files changed

+523
-272
lines changed

9 files changed

+523
-272
lines changed

package-lock.json

Lines changed: 446 additions & 265 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/dgrid-shim/src/gridHelper.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,35 @@ export const GridHelper = declare(null, {
1313
postCreate: function postCreate(inherited) {
1414
this.inherited(postCreate, arguments);
1515

16+
// Emit dgrid-column-autofit on double-mousedown over a resize handle.
17+
// A native dblclick is never fired because dgrid calls e.preventDefault()
18+
// on every mousedown on .dgrid-resize-handle.
19+
// We use a capture-phase listener on headerNode so we fire BEFORE dgrid's
20+
// bubble-phase delegated handler, allowing us to stopPropagation on the
21+
// second click to prevent dgrid from starting a resize drag.
22+
const self = this;
23+
let _lastResizeDownTime = 0;
24+
let _lastResizeColId: string | null = null;
25+
this.headerNode.addEventListener("mousedown", function (evt: MouseEvent) {
26+
const target = evt.target as any;
27+
if (!target.classList.contains("dgrid-resize-handle")) return;
28+
const colId: string = target.columnId;
29+
const now = Date.now();
30+
const delta = now - _lastResizeDownTime;
31+
if (colId === _lastResizeColId && delta <= 300) {
32+
_lastResizeDownTime = 0;
33+
_lastResizeColId = null;
34+
evt.stopPropagation();
35+
evt.preventDefault();
36+
const detail = self.columns[colId];
37+
if (!detail) return;
38+
self.domNode.dispatchEvent(new CustomEvent("dgrid-column-autofit", { detail, bubbles: true, cancelable: true }));
39+
} else {
40+
_lastResizeDownTime = now;
41+
_lastResizeColId = colId;
42+
}
43+
}, { capture: true });
44+
1645
this.__hpcc_tooltip_header = new Tooltip({
1746
connectId: [this.id],
1847
selector: ".dgrid-resize-header-container",
@@ -53,6 +82,26 @@ export const GridHelper = declare(null, {
5382
node.checked = false;
5483
node.indeterminate = false;
5584
});
85+
},
86+
87+
applyWidth: function (id: string, cssWidth: string) {
88+
const existingRule = this._columnSizes?.[id];
89+
if (existingRule?.set) {
90+
existingRule.set("width", cssWidth);
91+
} else {
92+
this.styleColumn(id, `width: ${cssWidth}`);
93+
}
94+
},
95+
96+
resizeColumn: function resizeColumn(colId: string, widthPx: number) {
97+
this.applyWidth(colId, `${widthPx}px`);
98+
99+
// Reset the last visible column to auto so it fills remaining space.
100+
const lastColId: string | undefined = this._getResizedColumnWidths?.()?.lastColId;
101+
if (lastColId && lastColId !== colId) {
102+
this.applyWidth(lastColId, "auto");
103+
}
104+
this.resize();
56105
}/*,
57106
58107
_onNotify(object, existingId) {

packages/dgrid/src/Common.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
import { HTMLWidget } from "@hpcc-js/common";
1+
import { HTMLWidget, Selection } from "@hpcc-js/common";
22
import { Grid, PagingGrid } from "./dgrid-shim.ts";
33
import { DBStore } from "./DBStore.ts";
4+
import { type ColumnType } from "./RowFormatter.ts";
45

56
import "../src/Common.css";
67

78
export class Common extends HTMLWidget {
8-
protected _columns = [];
9+
protected _columns: ColumnType[] = [];
910
protected _store = new DBStore(this._db);
10-
protected _dgridDiv;
11-
protected _dgrid;
12-
protected _prevPaging;
11+
protected _dgridDiv: Selection<HTMLDivElement, unknown, HTMLElement, unknown>;
12+
protected _dgrid: typeof PagingGrid | typeof Grid;
13+
protected _prevPaging: boolean;
1314
private _prevSortBy: string;
1415
private _prevSortByDescending: boolean;
1516
private _prevMultiSelect: boolean;
@@ -107,6 +108,14 @@ export class Common extends HTMLWidget {
107108
this.click(this.rowToObj(evt.rows[0].data.__origRow), "", false, { selection: this.selection() });
108109
}
109110
});
111+
this._dgrid.on("dgrid-column-autofit", (evt) => {
112+
if (this._supressEvents) return;
113+
if (evt.detail?.label) {
114+
const column = this._columns.find(c => c.label === evt.detail.label);
115+
if (!column) return;
116+
this.dblclickColResize(column.label, column);
117+
}
118+
});
110119
this._dgrid.refresh({});
111120
}
112121
this._dgrid.noDataMessage = `<span class='dojoxGridNoData'>${this.noDataMessage()}</span>`;
@@ -130,6 +139,9 @@ export class Common extends HTMLWidget {
130139

131140
click(row, col, sel, more) {
132141
}
142+
143+
dblclickColResize(column, dgridColumn) {
144+
}
133145
}
134146
Common.prototype._class += " dgrid_Common";
135147

packages/dgrid/src/DBStore.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export class DBStore {
2828
idx,
2929
className: "resultGridCell",
3030
sortable,
31+
hidden: false,
3132
isSet: false
3233
};
3334
switch (field.type()) {

packages/dgrid/src/DatasourceStore.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export class DatasourceStore {
7979
idx,
8080
className: "resultGridCell",
8181
sortable: true,
82+
hidden: false,
8283
isSet: false
8384
};
8485
if (field.type === "dataset") {

packages/dgrid/src/RowFormatter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export interface ColumnType {
3030
idx: number;
3131
className: string;
3232
sortable: boolean;
33+
hidden: boolean;
3334
isSet: boolean;
3435
width?: number;
3536
formatter?: CellFormatter;

packages/dgrid/src/Table.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,11 @@ export class Table extends Common {
235235
// Events ---
236236
click(row, col, sel) {
237237
}
238+
239+
dblclickColResize(column: string, dgridColumn: any): void {
240+
this.guessWidth([dgridColumn], this.data());
241+
this._dgrid.resizeColumn(dgridColumn.id, dgridColumn.width);
242+
}
238243
}
239244
Table.prototype._class += " dgrid_Table";
240245

packages/dgrid/src/dgrid-shim.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type * as dgrid_shim from "@hpcc-js/dgrid-shim";
22

33
// Note: Resolved at build time and inlined into the dgrid bundle.
4-
// @ts-ignore
4+
// @ts-expect-error
55
import dgridShimBundle from "@hpcc-js/dgrid-shim/dist/index.js?raw";
66
const loadDgridShim = new Function("globalThis", "var self = globalThis; var window = globalThis;" + dgridShimBundle);
77

packages/eclwatch/src/WUResultStore.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ function safeEncode(item) {
1414
case "[object String]":
1515
return entitiesEncode(item);
1616
default:
17-
console.warn("Unknown cell type: " + Object.prototype.toString.call(item));
17+
console.warn("Unknown cell type: " + Object.prototype.toString.call(item));
1818
}
1919
return item;
2020
}
@@ -52,6 +52,7 @@ export class Store {
5252
idx,
5353
label: label + (keyed ? " (i)" : ""),
5454
className: "resultGridCell",
55+
hidden: false,
5556
sortable: false,
5657
width: keyed ? 16 : 0,
5758
isSet: node.isSet

0 commit comments

Comments
 (0)