Skip to content

Commit e16e690

Browse files
adivp-mwpgaborbernat
authored andcommitted
Added fix for bug where context menu ends up far at the bottom of the page.
Fix involves correcting Lumino math that forces nonnegative y-coordinates. Signed-off-by: Adiv Paradise <[email protected]>
1 parent 80d72c1 commit e16e690

File tree

1 file changed

+54
-1
lines changed

1 file changed

+54
-1
lines changed

js/core/gridContextMenu.ts

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,61 @@ export class FeatherGridContextMenu extends GridContextMenu {
158158
throw 'unreachable';
159159
}
160160

161+
// Get the current height of the main viewport.
162+
const px = window.pageXOffset;
163+
const py = window.pageYOffset;
164+
const cw = document.documentElement.clientWidth;
165+
const ch = document.documentElement.clientHeight;
166+
const bodyh = document.documentElement.scrollHeight;
167+
var style = window.getComputedStyle(document.body);
168+
const extraspaceX = parseFloat(style.marginLeft)+parseFloat(style.paddingLeft)+parseFloat(style.borderLeftWidth);
169+
const extraspaceY = parseFloat(style.marginTop)+parseFloat(style.paddingTop)+parseFloat(style.borderTopWidth);
170+
161171
// Open context menu at location of the click event
162-
this._menu.open(hit.x, hit.y);
172+
this._menu.open(hit.x, 0); //Using 0 so it's at least at the bottom
173+
//of the parent div and not a mile down
174+
175+
// Now that it's open, move it to the correct position.
176+
// Lumino won't allow a negative y-coordinate, but we
177+
// need it to be negative with absolute positioning. This
178+
// position-reposition thing isn't ideal, since there's a
179+
// split-second that the menu is not where it ought to be,
180+
// but in practice this is usually going to be so brief a
181+
// moment that nobody will notice; it's functionally a
182+
// performance hit in a spot where people likely won't notice
183+
// a performance hit.
184+
185+
// We're going to do the full coordinate recalculation,
186+
// since the conditions below are part of the Lumino
187+
// menu's positioning math for a reason. They show up in
188+
// ipydatagrid's InteractiveFilterDialog positioning math
189+
// as well.
190+
191+
let node = this._menu.node;
192+
let { width, height } = node.getBoundingClientRect();
193+
194+
let hitx = hit.x;
195+
let hity = hit.y;
196+
197+
// Adjust the X position of the menu to fit on-screen.
198+
if (hitx + width > px + cw) {
199+
hitx = px + cw - width;
200+
}
201+
202+
// Adjust the Y position of the menu to fit on-screen.
203+
if (hity + height > py + ch) {
204+
if (hity > py + ch) {
205+
hity = py + ch - height;
206+
} else {
207+
hity = hity - height;
208+
}
209+
}
210+
211+
hitx = hitx - extraspaceX;
212+
hity = hity - bodyh + extraspaceY;
213+
214+
// Update the position of the menu to the computed position.
215+
this._menu.node.style.transform = `translate(${Math.max(0, hitx)}px, ${hity}px`;
163216
}
164217
}
165218

0 commit comments

Comments
 (0)