Mouseover is triggered on an absolute positioned div

goal

You have a small magnifying glass icon that appears in the upper right corner of a table cell when the table cell is hovered. Clicking on the magnifying glass icon and clicking on it will open a dialog box to display detailed information about the item in that particular table cell. I want to reuse the same icon for hundreds of table cells without repeating it every time.

Partial solution

You have the only one <span>

that is absolutely positioned and hidden. When a table cell _previewable

freezes, it <span>

moves to the desired location and displays. This one <span>

also moves to the DOM to be a child of the table cell _previewable

. This allows the click handler attached to the <span>

parent to find _previewable

and get information from it with jquery data (), which is used to populate the contents of the dialog.

Here's 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 fine until the content of my table is reloaded or modified using AJAX. Since it <span>

was moved from <body>

to be a child of the cell, it is thrown and replaced during the AJAX call. So I decided to first move <span>

back to the mouse body over the table cell, for example:

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

      

However, it <span>

disappears as soon as it hovers over the mouse. The mouseout event appears to be fired on _previewable

when the mouse is moved in <span>

, although it <span>

is a child _previewable

and is fully displayed within the borders of the table cell _previewable

. I have only tested this in Chrome at the moment.

Questions

  • Why is the mouse called on _previewable

    when the mouse is still within range _previewable

    ? Is it because it is <span>

    absolutely positioned?

  • How can I make this work without recreating <span>

    and having a click handler on each AJAX table?

+2


a source to share


2 answers


If you change your events, the rest of what you have (append to <body>

) will work like this:

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

      



Unlike mouseover

and mouseout

events mousenter

and mouseleave

will not fire when moved to or from the child, so they will behave the way you want in this case.

For cleanliness, I would tie .live('mouseenter

) and .live('mouseleave')

separately and delete if()

, much easier to look and see what happens, maybe just me :)

+5


a source


It seems like a whole lot of work to avoid having a little tiny image in each cell. You don't type very hard by "reusing" only one instance of the element. The browser will only need to load the image once. And from a performance standpoint, tinkering with the DOM tree requires more resources than just toggling the display property of the selected element.



The simplest approach is to just put <span>

in every cell you ever print and then use CSS to hide / show.

+1


a source







All Articles