From e16e690fbb5e55e8e5a9c398b132348bc707f0a1 Mon Sep 17 00:00:00 2001 From: Adiv Paradise Date: Wed, 6 Sep 2023 20:50:12 -0400 Subject: [PATCH] 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 --- js/core/gridContextMenu.ts | 55 +++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/js/core/gridContextMenu.ts b/js/core/gridContextMenu.ts index 6f6acbc8..bc9fcefa 100644 --- a/js/core/gridContextMenu.ts +++ b/js/core/gridContextMenu.ts @@ -158,8 +158,61 @@ export class FeatherGridContextMenu extends GridContextMenu { throw 'unreachable'; } + // Get the current height of the main viewport. + const px = window.pageXOffset; + const py = window.pageYOffset; + const cw = document.documentElement.clientWidth; + const ch = document.documentElement.clientHeight; + const bodyh = document.documentElement.scrollHeight; + var style = window.getComputedStyle(document.body); + const extraspaceX = parseFloat(style.marginLeft)+parseFloat(style.paddingLeft)+parseFloat(style.borderLeftWidth); + const extraspaceY = parseFloat(style.marginTop)+parseFloat(style.paddingTop)+parseFloat(style.borderTopWidth); + // Open context menu at location of the click event - this._menu.open(hit.x, hit.y); + this._menu.open(hit.x, 0); //Using 0 so it's at least at the bottom + //of the parent div and not a mile down + + // Now that it's open, move it to the correct position. + // Lumino won't allow a negative y-coordinate, but we + // need it to be negative with absolute positioning. This + // position-reposition thing isn't ideal, since there's a + // split-second that the menu is not where it ought to be, + // but in practice this is usually going to be so brief a + // moment that nobody will notice; it's functionally a + // performance hit in a spot where people likely won't notice + // a performance hit. + + // We're going to do the full coordinate recalculation, + // since the conditions below are part of the Lumino + // menu's positioning math for a reason. They show up in + // ipydatagrid's InteractiveFilterDialog positioning math + // as well. + + let node = this._menu.node; + let { width, height } = node.getBoundingClientRect(); + + let hitx = hit.x; + let hity = hit.y; + + // Adjust the X position of the menu to fit on-screen. + if (hitx + width > px + cw) { + hitx = px + cw - width; + } + + // Adjust the Y position of the menu to fit on-screen. + if (hity + height > py + ch) { + if (hity > py + ch) { + hity = py + ch - height; + } else { + hity = hity - height; + } + } + + hitx = hitx - extraspaceX; + hity = hity - bodyh + extraspaceY; + + // Update the position of the menu to the computed position. + this._menu.node.style.transform = `translate(${Math.max(0, hitx)}px, ${hity}px`; } }