refactor: optimize context menu positioning logic
Improvements: - change position to `fixed` so menu stays on top and doesn't get cut off by the sidebar's container - use `getBoundingClientRect` to calc exact position relative to the screen, better when sidebar collapsed - fix rtl alignment - off-screen fix add a safety check to make sure the menu never slides off the left edge of the window
This commit is contained in:
parent
631e35bf18
commit
00680fb776
1 changed files with 20 additions and 34 deletions
|
|
@ -179,48 +179,27 @@ frappe.ui.menu = class ContextMenu {
|
|||
|
||||
show(event) {
|
||||
this.make();
|
||||
const offset = $(this.parent).offset();
|
||||
const height = $(this.parent).outerHeight();
|
||||
this.left_offset = 0;
|
||||
const parent_rect = this.parent.get(0).getBoundingClientRect();
|
||||
this.gap = 4;
|
||||
let top, left;
|
||||
if (this.opts.nested && this.opts.parent_menu) {
|
||||
let top =
|
||||
this.parent.get(0).getBoundingClientRect().bottom -
|
||||
this.parent.get(0).getBoundingClientRect().height;
|
||||
let dropdown = frappe.menu_map[this.opts.parent_menu].template;
|
||||
let width = dropdown.outerWidth();
|
||||
let offset = $(dropdown).offset();
|
||||
let left = offset.left;
|
||||
let parent_menu_el = frappe.menu_map[this.opts.parent_menu].template;
|
||||
let parent_menu_rect = parent_menu_el.get(0).getBoundingClientRect();
|
||||
top = parent_rect.top;
|
||||
if (frappe.utils.is_rtl()) {
|
||||
left = left - width - this.gap;
|
||||
left = parent_menu_rect.left - this.template.outerWidth() - this.gap;
|
||||
} else {
|
||||
left = left + width + this.gap;
|
||||
left = parent_menu_rect.right + this.gap;
|
||||
}
|
||||
this.template.css({
|
||||
display: "block",
|
||||
position: "absolute",
|
||||
top: top + "px",
|
||||
left: left + "px",
|
||||
});
|
||||
} else {
|
||||
this.template.css({
|
||||
display: "block",
|
||||
position: "absolute",
|
||||
top: offset.top + height + this.gap + "px",
|
||||
left: offset.left,
|
||||
});
|
||||
top = parent_rect.bottom + this.gap;
|
||||
left = parent_rect.left;
|
||||
if (this.open_on_left || frappe.utils.is_rtl()) {
|
||||
left = parent_rect.right - this.template.outerWidth();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.open_on_left) {
|
||||
this.left_offset = this.parent.get(0).getBoundingClientRect().width;
|
||||
this.template.css({
|
||||
left:
|
||||
offset.left -
|
||||
this.template.get(0).getBoundingClientRect().width +
|
||||
this.left_offset +
|
||||
"px",
|
||||
});
|
||||
}
|
||||
if (left < 0) left = 10;
|
||||
|
||||
if (this.opts.right_click) {
|
||||
this.template.css({
|
||||
|
|
@ -229,6 +208,13 @@ frappe.ui.menu = class ContextMenu {
|
|||
});
|
||||
}
|
||||
|
||||
this.template.css({
|
||||
display: "block",
|
||||
position: "fixed",
|
||||
top: top + "px",
|
||||
left: left + "px",
|
||||
});
|
||||
|
||||
this.visible = true;
|
||||
frappe.visible_menus.push(this);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue