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
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?How can I make this work, without recreating the
<span>
and it's click handler on each AJAX table referesh?