mirror of
https://github.com/phishingclub/phishingclub.git
synced 2026-07-14 07:47:24 +02:00
@@ -26,30 +26,32 @@
|
||||
activeFormElement.set(dropdownId);
|
||||
|
||||
const viewportHeight = window.innerHeight;
|
||||
const viewportWidth = window.innerWidth;
|
||||
const buffer = 20;
|
||||
const minHeight = 64;
|
||||
const maxHeight = 400;
|
||||
const gap = 8;
|
||||
|
||||
let clickViewportY, pageX, pageY;
|
||||
|
||||
if (e.clientY !== undefined && e.pageX !== undefined) {
|
||||
clickViewportY = e.clientY;
|
||||
pageX = e.pageX;
|
||||
pageY = e.pageY;
|
||||
let x, y;
|
||||
if (e.clientX !== undefined && e.clientY !== undefined) {
|
||||
x = e.clientX;
|
||||
y = e.clientY;
|
||||
} else {
|
||||
const rect = buttonRef.getBoundingClientRect();
|
||||
clickViewportY = rect.top;
|
||||
pageX = rect.left + window.scrollX;
|
||||
pageY = rect.top + window.scrollY;
|
||||
x = rect.left + rect.width / 2;
|
||||
y = rect.top;
|
||||
}
|
||||
|
||||
const spaceAbove = clickViewportY - buffer;
|
||||
const spaceBelow = viewportHeight - clickViewportY - buffer;
|
||||
const spaceAbove = y - buffer;
|
||||
const spaceBelow = viewportHeight - y - buffer;
|
||||
const shouldShowAbove = spaceBelow < minHeight && spaceAbove > spaceBelow;
|
||||
const availableSpace = shouldShowAbove ? spaceAbove : spaceBelow;
|
||||
const optimalHeight = Math.min(Math.max(availableSpace, minHeight), maxHeight);
|
||||
const gap = 8;
|
||||
menuX = pageX - 256;
|
||||
|
||||
const menuWidth = 256;
|
||||
const spaceOnRight = viewportWidth - x - buffer;
|
||||
menuX = spaceOnRight >= menuWidth ? x : x - menuWidth;
|
||||
menuX = Math.max(buffer, Math.min(menuX, viewportWidth - menuWidth - buffer));
|
||||
|
||||
if (shouldShowAbove) {
|
||||
menuRef.style.visibility = 'hidden';
|
||||
@@ -57,9 +59,9 @@
|
||||
const actualMenuHeight = menuRef.scrollHeight;
|
||||
menuRef.style.display = '';
|
||||
menuRef.style.visibility = '';
|
||||
menuY = pageY - actualMenuHeight - gap;
|
||||
menuY = y - actualMenuHeight - gap;
|
||||
} else {
|
||||
menuY = pageY + gap;
|
||||
menuY = y + gap;
|
||||
}
|
||||
|
||||
menuRef.style = `left: ${menuX}px; top: ${menuY}px; max-height: ${optimalHeight}px`;
|
||||
@@ -127,7 +129,7 @@
|
||||
|
||||
<div
|
||||
bind:this={menuRef}
|
||||
class="absolute bg-white dark:bg-gray-900/90 drop-shadow-md dark:shadow-gray-900/50 border dark:border-gray-700/60 z-20 w-64 rounded-md overflow-y-scroll transition-colors duration-200 {scrollBarClassesVertical}"
|
||||
class="fixed bg-white dark:bg-gray-900/90 drop-shadow-md dark:shadow-gray-900/50 border dark:border-gray-700/60 z-50 w-64 rounded-md overflow-y-scroll transition-colors duration-200 {scrollBarClassesVertical}"
|
||||
class:hidden={!isMenuVisible}
|
||||
>
|
||||
<ul class="flex flex-col text-left">
|
||||
|
||||
@@ -26,54 +26,43 @@
|
||||
activeFormElement.set(dropdownId); // set this as active, closing others
|
||||
|
||||
const viewportHeight = window.innerHeight;
|
||||
const buffer = 20; // extra space to ensure some padding from viewport edges
|
||||
const minHeight = 64; // minimum dropdown height
|
||||
const maxHeight = 400; // maximum dropdown height
|
||||
const viewportWidth = window.innerWidth;
|
||||
const buffer = 20;
|
||||
const minHeight = 64;
|
||||
const maxHeight = 400;
|
||||
const gap = 8;
|
||||
|
||||
let clickViewportY, pageX, pageY;
|
||||
|
||||
// handle both mouse and keyboard events
|
||||
if (e.clientY !== undefined && e.pageX !== undefined) {
|
||||
// mouse event
|
||||
clickViewportY = e.clientY;
|
||||
pageX = e.pageX;
|
||||
pageY = e.pageY;
|
||||
// use viewport (fixed) coordinates so positioning is independent of DOM ancestors
|
||||
let x, y;
|
||||
if (e.clientX !== undefined && e.clientY !== undefined) {
|
||||
x = e.clientX;
|
||||
y = e.clientY;
|
||||
} else {
|
||||
// keyboard event - use button position
|
||||
const buttonRect = buttonRef.getBoundingClientRect();
|
||||
clickViewportY = buttonRect.top;
|
||||
pageX = buttonRect.left + window.scrollX;
|
||||
pageY = buttonRect.top + window.scrollY;
|
||||
x = buttonRect.left + buttonRect.width / 2;
|
||||
y = buttonRect.top;
|
||||
}
|
||||
|
||||
// calculate available space above and below
|
||||
const spaceAbove = clickViewportY - buffer;
|
||||
const spaceBelow = viewportHeight - clickViewportY - buffer;
|
||||
|
||||
// choose position based on available space, with preference for below
|
||||
const spaceAbove = y - buffer;
|
||||
const spaceBelow = viewportHeight - y - buffer;
|
||||
const shouldShowAbove = spaceBelow < minHeight && spaceAbove > spaceBelow;
|
||||
const availableSpace = shouldShowAbove ? spaceAbove : spaceBelow;
|
||||
|
||||
// calculate optimal height within bounds
|
||||
const optimalHeight = Math.min(Math.max(availableSpace, minHeight), maxHeight);
|
||||
|
||||
// find position
|
||||
const gap = 8; // small gap between menu and cursor/button
|
||||
menuX = pageX - 256;
|
||||
const menuWidth = 256;
|
||||
const spaceOnRight = viewportWidth - x - buffer;
|
||||
menuX = spaceOnRight >= menuWidth ? x : x - menuWidth;
|
||||
menuX = Math.max(buffer, Math.min(menuX, viewportWidth - menuWidth - buffer));
|
||||
|
||||
if (shouldShowAbove) {
|
||||
// calculate actual menu height by temporarily showing it
|
||||
menuRef.style.visibility = 'hidden';
|
||||
menuRef.style.display = 'block';
|
||||
const actualMenuHeight = menuRef.scrollHeight;
|
||||
menuRef.style.display = '';
|
||||
menuRef.style.visibility = '';
|
||||
|
||||
// position above by moving up by the actual menu height
|
||||
menuY = pageY - actualMenuHeight - gap;
|
||||
menuY = y - actualMenuHeight - gap;
|
||||
} else {
|
||||
// for below positioning, use original click/button position
|
||||
menuY = pageY + gap;
|
||||
menuY = y + gap;
|
||||
}
|
||||
|
||||
menuRef.style = `left: ${menuX}px; top: ${menuY}px; max-height: ${optimalHeight}px`;
|
||||
@@ -160,7 +149,7 @@
|
||||
|
||||
<div
|
||||
bind:this={menuRef}
|
||||
class="absolute bg-white dark:bg-gray-900/90 drop-shadow-md dark:shadow-gray-900/50 border dark:border-gray-700/60 z-20 w-64 rounded-md overflow-y-scroll transition-colors duration-200 {scrollBarClassesVertical}"
|
||||
class="fixed bg-white dark:bg-gray-900/90 drop-shadow-md dark:shadow-gray-900/50 border dark:border-gray-700/60 z-50 w-64 rounded-md overflow-y-scroll transition-colors duration-200 {scrollBarClassesVertical}"
|
||||
class:hidden={!isMenuVisible}
|
||||
>
|
||||
<ul class="flex flex-col text-left">
|
||||
|
||||
Reference in New Issue
Block a user