I display a bunch of posts from users on a page. I have the main parent div with the class name 'posts' and each post is outputted in a div with class name 'row' inside of it. So there's a whole lot of div.row's inside the div.posts. Each look like this.
<div class="row clearfix">
<div class="left-column">
<img src="..." title="" />
</div>
<div class="main-column">
<div class="row-text">Post Text...</div>
<div class="row-date">Posted Date...</div>
</div>
<div class="actions-column">
<a href="#">Link</a>
<a href="#">Link 2</a>
<a href="#">Link 3 etc.</a>
</div>
</div>
Via CSS the actions-column is set to display:none by default. When a user mouseover's a post (div.row) I want to show the actions-column. My initial way of doing it was by setting a mouseover even for each row and that was taking it's toll on the browser and slowing things down. I did some research and stumbled upon event delegation and decided to give it a try. So far I am able to identify which row is being targeted, however, I cannot figure out how to target it's child-div with the class 'actions-column'.
Code so far...
$(window).load(function(){
$('.posts').mouseover(function(e){
var $row, $tgt = $(e.target);
if ($tgt.hasClass("row")) {
$row = $tgt;
} else {
if ($tgt.parent().parent().hasClass('row'))
$row = $tgt.parent().parent();
else if ($tgt.parent().hasClass('row'))
$row = tgt.parent();
else
return false;
}
//code here to select div.actions-column and show it
});
$('.posts').mouseover(function(e){
var $row, $tgt = $(e.target);
if ($tgt.hasClass("row")) {
$row = $tgt;
} else {
if ($tgt.parent().parent().hasClass('row'))
$row = $tgt.parent().parent();
else if ($tgt.parent().hasClass('row'))
$row = tgt.parent();
else
return false;
}
//code here to select div.actions-column and hide it
});
});
You could use live:
$('div.row').live('mouseover', function() {
$(this).find('div.actions-column').show();
}).live('mouseout', function() {
$(this).find('div.actions-column').hide();
});
As the documentation notes:
When you bind a "live" event it will bind to all current and future elements on the page (using event delegation).
A couple more notes:
$(window).load() event. You probably want $(document).ready()$('.posts') twice, you can just append the second call at the end (like I did in my example above) - this is much more efficient and the preferred way of doing multiple things to 1 selector in jQuery.div.row up the HTML tree has already been implemented by jQuery's closest() method.You could do something like this with it:
$('div.posts').hover(function(e) {
var row = $(e.target).closest('div.row');
$row.find('div.actions-column').show();
}, function(e) {
var row = $(e.target).closest('div.row');
$row.find('div.actions-column').hide();
});
But this is not necessary because of the live functionality I showed above.
<div> with a class of posts, consider giving it an id attribute. This is by far the most efficient method of selecting elements in a document, and it makes sense to give it to elements that only occur once..row, make a habit of looking for div.row instead. It's just faster.I realize this has already been answered, but since jQuery 1.5 adds an explicit "delegate" method, that might be a better solution now. Since this thread will come up in searches, I post this answer for other people searching for it. (I also refactor for further conciseness by using "hover" and "toggle()" instead of mouseenter/mouseleave + show()/hide().)
http://api.jquery.com/delegate/
$('div.row').live('mouseover', function() {
$(this).find('div.actions-column').show();
}).live('mouseout', function() {
$(this).find('div.actions-column').hide();
});
with jQuery 1.5 or higher could be written as:
$(".posts").delegate("div.row", "hover", function(){
$(this).find("div.actions-column").toggle();
});
See it in action:
http://jsfiddle.net/SM6Jv/

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With