鼠标悬停在绝对定位的 div 上触发

发布于 2024-08-29 23:36:36 字数 2931 浏览 6 评论 0原文

目标

当将鼠标悬停在表格单元格上时,该表格单元格的右上角会出现一个小的放大镜图标。将鼠标悬停在放大镜图标上并单击它将打开一个对话框窗口,以显示有关特定表格单元格中的项目的详细信息。我想为数百个表格单元重复使用相同的图标,而不是每次都重新创建它。

部分解决方案

有一个绝对定位和隐藏的 。当 _previewable 表格单元格悬停时, 将移动到正确的位置并显示。此 也会在 DOM 中移动,成为 _previewable 表格单元格的子级。这使得附加到 的点击处理程序能够找到 _previewable 父级,并从它的 jquery data() 对象中获取信息,该对象用于填充对话框。

这是我的 HTML 的一个非常简化的版本:

<body>
    <span id="options">
        <a class="ui-state-default ui-corner-all">
            <span class="ui-icon ui-icon-search"></span>
            Preview
        </a>
    </span>
    <table>
         <tr>
             <td class="_previewable">
                 <img scr="user_1.png"/>
                 <span>Bob Smith</span>
             </td>
        </tr>
   </table>
</body>

以及这个 CSS:

#options {
    position: absolute;
    display: none;
}

使用这个 jQuery 代码:

var $options = $('#options');
$options.click(function() {
    $item = $(this).parents("._previewable");
    // Show popup based on data in $item.data("id");
    Layout.renderPopup($item.data("id"),$item.data("popup"));               
});

$('._previewable').live('mouseover mouseout',function(event) {
    if (event.type == 'mouseover') {
        var $target = $(this);
        var $parent = $target.offsetParent()[0];

        var left = $parent.scrollLeft + $target.position().left 
            + $target.outerWidth() - $options.outerWidth() + 1;
        var top = $parent.scrollTop + $target.position().top + 2;

        $options.appendTo($target);
        $options.css({
            "left": left + "px",
            "top": top + "px"
        }).show();
    }
    else {
        // On mouseout, $options continues to be a child of $(this)
        $options.hide();
    }
});     

问题

这个解决方案可以完美地工作,直到我的表的内容通过 AJAX 重新加载或更改。由于 已从 移至单元格的子级,因此它会在 AJAX 调用期间被丢弃并被替换。所以我的第一个想法是在鼠标移出表格单元格时将 移回正文,如下所示:

    else {
        // On mouseout, $options is moved back to be a child of body
        $options.appendTo("body");
        $options.hide();
    }

但是,有了这个,鼠标悬停后立即消失。当鼠标移入 时,mouseout 事件似乎会在 _previewable 上调用,即使 _previewable 的子级,并完全显示在 _previewable 表格单元格的边界内。目前,我只在 Chrome 中对此进行了测试。

问题

  1. 当鼠标仍在 _previewable 的边界内时,为什么会在 _previewable 上调用 mouseout?是因为 是绝对定位的吗?

  2. 如何在不重新创建 及其每个 AJAX 表引用上的点击处理程序的情况下完成这项工作?

    如何

Objective

Have a small magnifying glass icon that appears in the top right corner of a table cell when the table cell is hovered over. Mousing over the magnifying glass icon and clicking it will open a dialog window to show detailed information about the item in that particular table cell. I want to reuse the same icon for hundreds of table cells without recreating it each time.

Partial Solution

Have a single <span> that is absolutely positioned and hidden. When a _previewable table cell is hovered, the <span> is moved to the correct location and shown. This <span> is also moved in the DOM to be a child of the _previewable table cell. This enables a click handler attached to the <span> to find the _previewable parent, and get information from it's jquery data() object that is used to populate the contents of the dialog.

Here is a very simplified version of my HTML:

<body>
    <span id="options">
        <a class="ui-state-default ui-corner-all">
            <span class="ui-icon ui-icon-search"></span>
            Preview
        </a>
    </span>
    <table>
         <tr>
             <td class="_previewable">
                 <img scr="user_1.png"/>
                 <span>Bob Smith</span>
             </td>
        </tr>
   </table>
</body>

And this CSS:

#options {
    position: absolute;
    display: none;
}

With this jQuery code:

var $options = $('#options');
$options.click(function() {
    $item = $(this).parents("._previewable");
    // Show popup based on data in $item.data("id");
    Layout.renderPopup($item.data("id"),$item.data("popup"));               
});

$('._previewable').live('mouseover mouseout',function(event) {
    if (event.type == 'mouseover') {
        var $target = $(this);
        var $parent = $target.offsetParent()[0];

        var left = $parent.scrollLeft + $target.position().left 
            + $target.outerWidth() - $options.outerWidth() + 1;
        var top = $parent.scrollTop + $target.position().top + 2;

        $options.appendTo($target);
        $options.css({
            "left": left + "px",
            "top": top + "px"
        }).show();
    }
    else {
        // On mouseout, $options continues to be a child of $(this)
        $options.hide();
    }
});     

Problem

This solution works perfectly until the contents of my table are reloaded or changed via AJAX. Because the <span> was moved from the <body> to be a child of the cell, it gets thrown out and replaced during the AJAX call. So my first thought is to move the <span> back to the body on mouseout of the table cell, like this:

    else {
        // On mouseout, $options is moved back to be a child of body
        $options.appendTo("body");
        $options.hide();
    }

However, with this, the <span> disappears as soon as it is mouseover. The mouseout event seems to be called on _previewable when the mouse moves into the <span>, even though the <span> is a child of _previewable and fully displayed within the boundaries of the _previewable table cell. At this point, I've only tested this in Chrome.

Questions

  1. Why would mouseout be called on _previewable, when the mouse is still within the boundaries of _previewable? Is it because the <span> is absolutely positioned?

  2. How can I make this work, without recreating the <span> and it's click handler on each AJAX table referesh?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

用心笑 2024-09-05 23:36:36

如果您更改事件,那么您拥有的其余部分(附加到 )将起作用,如下所示:

$('._previewable').live('mousenter mouseleave',function(event) {

mouseovermouseout 不同>,当移动到子级或从子级移出时,mouseentermouseleave 事件不会触发,因此在这种情况下它们的行为将如您所愿。

不过,为了保持整洁,我会分别绑定 .live('mouseenter) 和 .live('mouseleave') 并删除 if() ,查看并了解正在发生的事情要容易得多,但可能只有我一个人:)

If you change your events then the rest of what you have (appending to <body>) will work, like this:

$('._previewable').live('mousenter mouseleave',function(event) {

Unlike mouseover and mouseout, the mousenter and mouseleave events won't fire when moving to or from a child, so they'll behave like you want in this case.

For cleanliness though, I'd bind .live('mouseenter) and .live('mouseleave') separately and remove the if(), it's much easier to look and see what's going on, might be just me though :)

忘羡 2024-09-05 23:36:36

为了避免每个单元格中出现微小的图像,这看起来需要做大量的工作。仅“重用”该元素的一个实例并没有真正获得太多好处。浏览器只需下载图像一次。从性能的角度来看,摆弄 DOM 树比仅仅切换突出显示元素的显示属性需要更多的资源。

最简单的方法可能就是将 放入您打印出来的每个单元格中,然后使用 CSS 隐藏/显示。

That looks like a whole lot of work just to avoid having the little tiny image in each cell. You're not really gaining very much by "reusing" just one instance of the element. Browsers will only have to download the image once. And from a performance point of view, fiddling with the DOM tree takes more resources than just switching the display property of a highlighted element.

Simplest approach may just be to put the <span> in every cell you ever print out, then use CSS to hide/display.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文