在鼠标位置上显示弹出窗口

Ges*_*set 2 html javascript jquery

我无法在鼠标单击的确切位置出现弹出窗口。我希望能够单击一个 DIV(位于表格单元格内),并在单击该 div 时显示一个弹出窗口。

现在我的弹出窗口正在工作,但是无论我尝试什么,弹出 DIV 都位于页面的中间位置。

超文本标记语言

<ul class="customdropdown" style="display:none;" id="xxx<?php echo $fetch['unit_no']; ?>" role="menu" aria-labelledby="menuitems">
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#"</i>Link 1</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#"</i>Link 2</a></li>

</ul>
Run Code Online (Sandbox Code Playgroud)

查询

$(document).ready(function () {
        $('#myDiv<?php echo $fetch['unit_no']; ?>').click(function (e) {
            var myDiv = document.getElementById('myDiv<?php echo $fetch['unit_no']; ?>');
            var leftx = e.pageX-myDiv.offsetLeft;
            var topy = e.pageY-myDiv.offsetTop;

            $("#xxx<?php echo $fetch['unit_no']; ?>")
                .css({
                    position: 'absolute',
                    left: leftx,
                    top: topy,
                    display: 'block'
                })
           
        });
    });
Run Code Online (Sandbox Code Playgroud)

下面是发生的情况的屏幕截图:

在此输入图像描述

这和DIV的定位有关吗?

Rok*_*jan 10

这取决于您的弹出窗口(工具提示)是否处于位置absolutefixed父级是否有任何position其他static设置,以及弹出窗口是否位于包装器内部;或者是 的直接子代body

\n

前面三个例子:

\n
    \n
  1. 绝对弹出窗口作为非静态父级的子级(有优点和缺点
  2. \n
  3. 固定弹出窗口(有优点和缺点
  4. \n
  5. 绝对弹出窗口作为文档的直接子级<body>最佳
  6. \n
\n

1. 将绝对子级移动到父级内的 X,Y 坐标

\n

案例:在父级position: absolute;内部弹出position: relative;

\n
    \n
  • 如果父级有滚动条overflow值不是visible
  • \n
\n
X = Event.pageX + Parent.scrollLeft - Parent.offsetLeft\nY = Event.pageY + Parent.scrollTop - Parent.offsetTop\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 如果父级没有滚动条(不要使用这个!):
  • \n
\n
// !! Bad practice !!\nX = Event.pageX - Parent.offsetLeft   \nY = Event.pageY - Parent.offsetTop    \n
Run Code Online (Sandbox Code Playgroud)\n

例子:

\n

\r\n
\r\n
const el = (sel, par) => (par||document).querySelector(sel);\n\nconst elArea  = el("#area");\nconst elPopup = el("#popup");\n\nconst showPopup = (evt) => {\n  const elBtn = evt.currentTarget;\n  \n  Object.assign(elPopup.style, {\n    left: `${evt.pageX + elBtn.scrollLeft - elBtn.offsetLeft}px`,\n    top:  `${evt.pageY + elBtn.scrollTop - elBtn.offsetTop}px`,\n    display: `block`,\n  });\n};\n\nelArea.addEventListener("click", showPopup);
Run Code Online (Sandbox Code Playgroud)\r\n
body {\n  height: 300vh; /* Just to force some scrollbars */\n}\n\n#area {\n  position: relative;  /* this is needed! */  \n  height: 150px;\n  background: #eee;\n  margin: 40px;\n}\n\n#popup {\n  position: absolute;\n  height: 30px;\n  background: gold;\n  display: none;\n}
Run Code Online (Sandbox Code Playgroud)\r\n
<div id="area">\n  Click here to shop popup, and scroll the window\n  <div id="popup">Popup</div>\n</div>
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n

优点:

\n
    \n
  • 即使页面滚动,弹出窗口仍保持在包装元素内
  • \n
\n

缺点:

\n
    \n
  • 如果是实际事件,则需要附加代码来防止弹出窗口移动target- 以允许与内部内容交互并且弹出窗口不移动。
  • \n
  • 弹出窗口需要是特定父元素的子元素,这会导致代码可重用性较差。PS:解决方案是使用:SomeClickedElement.append(EL_popup) .
  • \n
  • 包装父元素 ( #area) 需要一个position集合(除了static),即:position: relative;
  • \n
\n

2.将固定元素移动到X,Y坐标

\n

案例:position: fixed;在父级外部(或内部)弹出,但通常作为子级<body>

\n
X = Event.clientX  \nY = Event.clientY\n
Run Code Online (Sandbox Code Playgroud)\n

例子:

\n

\r\n
\r\n
const el = (sel, par) => (par||document).querySelector(sel);\n\nconst elArea  = el("#area");\nconst elPopup = el("#popup");\n\nconst showPopup = (evt) => {\n  Object.assign(elPopup.style, {\n    left: `${evt.clientX}px`,\n    top: `${evt.clientY}px`,\n    display: `block`,\n  });\n};\n\nelArea.addEventListener("click", showPopup);
Run Code Online (Sandbox Code Playgroud)\r\n
body {\n  height: 300vh; /* Just to force some scrollbars */\n}\n\n#area {\n  /* position: relative; /* not necessary any more */\n  height: 150px;\n  background: #eee;\n  margin: 40px;\n}\n\n#popup {\n  position: fixed;\n  height: 30px;\n  background: gold;\n  display: none;\n}
Run Code Online (Sandbox Code Playgroud)\r\n
<div id="area">\n  Click here to shop popup, and scroll the window\n</div>\n\n<div id="popup">Popup fixed</div>
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n

优点:

\n
    \n
  • 如果放置在父级之外(#area- 如果单击在父级 ( ) 内部启动,则不需要额外的代码来阻止其移动。
  • \n
  • 更好的代码可重用性。根据单击的元素,您可以通过更改其内容来重用相同的弹出窗口。
  • \n
  • 包装父元素 ( #area) 不需要position
  • \n
  • Event.clientXEvent.clientY就是将其移动到新位置所需的一切。
  • \n
\n

缺点:

\n
    \n
  • 如果页面滚动,则弹出位置相对于窗口是固定的。解决方案是使其隐藏在页面滚动上,或者更复杂 - 通过坐标差异移动它。
  • \n
\n

3.(最好!)将绝对(体内)元素移动到X,Y坐标

\n

案例:position: absolute;作为直接子项弹出body

\n
X = Event.clientX + window.scrollX\nY = Event.clientY + window.scrollY\n
Run Code Online (Sandbox Code Playgroud)\n

例子:

\n

\r\n
\r\n
const el = (sel, par) => (par||document).querySelector(sel);\n\nconst elArea  = el("#area");\nconst elPopup = el("#popup");\n\nconst showPopup = (evt) => {\n  Object.assign(elPopup.style, {\n    left: `${evt.clientX + window.scrollX}px`,\n    top: `${evt.clientY + window.scrollY}px`,\n    display: `block`,\n  });\n};\n\nelArea.addEventListener("click", showPopup);
Run Code Online (Sandbox Code Playgroud)\r\n
body {\n  height: 300vh; /* Just to force some scrollbars */\n}\n\n#area {\n  /* position: relative; /* not necessary any more */\n  height: 150px;\n  background: #eee;\n  margin: 40px;\n}\n\n#popup {\n  position: absolute;\n  height: 30px;\n  background: gold;\n  display: none;\n}
Run Code Online (Sandbox Code Playgroud)\r\n
<div id="area">\n  Click here to shop popup, and scroll the window\n</div>\n\n<div id="popup">Popup fixed</div>
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n

优点:

\n
    \n
  • 即使页面滚动,弹出位置也会“锚定”在相对于文档的相同位置,而不是相对于滚动窗口。
  • \n
  • (除非Event.currentTarget是整个"body")如果单击其内容,弹出窗口将不会更改位置。
  • \n
\n

针对所有情况的建议:

\n
    \n
  • 为了改进 UX(用户体验),“浮动”弹出窗口需要额外的计算,即 \xe2\x80\x94 确定剩余的可用空间约束,以防止弹出窗口溢出窗口右/下边缘
  • \n
  • 如果用户在弹出窗口外部单击,则需要附加代码来关闭弹出窗口。这可以通过简单地检查是否单击 \xe2\x80\x94 来实现(如果是则关闭弹出窗口)。有时这同样适用于Context-menus,但很少适用于以窗口为中心的模态\xe2\x80\x94 ,它有一个专用的关闭按钮。Event.target.closest("#popup") !== EL_popuptrue
  • \n
\n

最佳实践示例:

\n

\r\n
\r\n
// DOM utility functions:\n\nconst el = (sel, par) => (par||document).querySelector(sel);\n\n\n// Popup:\n\nlet elPopup; // To remember the currently active popup\n\nconst handlePopup = (evt) => {\n  // Get clicked target\n  const elTarget = evt.target;\n\n  // Clicked a popup, do nothing (Comment this line if not needed)\n  if (elTarget.closest(".popup")) return;\n\n  // Close currently open popup (if any):\n  if (elPopup) elPopup.classList.remove("is-active");\n\n  // Get initiator button\n  const elBtn = elTarget.closest("[data-popup]");\n\n  // Not a valid button\n  if (!elBtn) return;\n\n  // Get the popup\n  elPopup = el(elBtn.dataset.popup);  \n\n  // No matching popup in this page, do nothing\n  if (!elPopup) return; \n  \n  // Get its parent (BODY) so that we can calculate the min max\n  // available space\n  const elParent = elPopup.parentElement;\n  \n  // Position:\n  const absX = evt.clientX + window.scrollX;\n  const absY = evt.clientY + window.scrollY;\n  \n  const bcrParent = elParent.getBoundingClientRect();\n  const bcrPopup = elPopup.getBoundingClientRect();\n  \n  const maxX = bcrParent.width - bcrPopup.width;\n  const maxY = bcrParent.height - bcrPopup.height;\n  \n  const x = Math.max(0, Math.min(absX, maxX));\n  const y = Math.max(0, Math.min(absY, maxY));\n  \n  // Show popup\n  Object.assign(elPopup.style, {\n    left: `${x}px`,\n    top: `${y}px`,\n  });\n  elPopup.classList.add("is-active");\n\n};\n\nel("body").addEventListener("click", handlePopup);
Run Code Online (Sandbox Code Playgroud)\r\n
/*QuickReset*/ * { margin: 0; box-sizing: border-box; }\n\nbody {\n  min-height: 300vh; /* just to force some demo scrollbars */\n}\n\n#area {\n  background: #eee;\n  padding: 10px;\n}\n\n.popup {\n  position: absolute;\n  background: gold;\n  visibility: hidden;\n  pointer-events: none;\n  min-width: 100px;\n  padding: 1rem;\n}\n\n.popup.is-active {\n  visibility: visible;\n  pointer-events: auto;\n}
Run Code Online (Sandbox Code Playgroud)\r\n
<div id="area" data-popup="#popup-one">Show "popup one"</div>\n\n<button data-popup="#popup-two" type="button">Show "popup two"</button>\n\n<br>Click anywhere to close an open popup  \n<br>Click inside a popup. It will not close ()\n\n<div class="popup" id="popup-one">Popup one!</div>\n<div class="popup" id="popup-two">Popup TWO!</div>
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n