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.