2009-06-15 8 views
3

Ich zeige eine Reihe von Beiträgen von Benutzern auf einer Seite an. Ich habe das Hauptelternteil div mit dem Klassennamen 'Beiträge' und jeder Beitrag wird in einem div mit dem Klassennamen 'row' innerhalb davon ausgegeben. Also gibt es eine Menge div.row in den div.posts. Jeder sieht so aus.jQuery Ereignisdelegation + Zielhilfe für Kinder

<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 wird die Aktionen-Spalte zur Anzeige eingestellt: keine standardmäßig. Wenn ein Benutzer mouseover ein Post (div.row) ist, möchte ich die actions-column anzeigen. Meine anfängliche Art, dies zu tun, bestand darin, selbst für jede Zeile einen Mouseover zu setzen, was sich auf den Browser auswirkte und die Dinge verlangsamte. Ich recherchierte und stolperte über die Delegation von Veranstaltungen und beschloss, es zu versuchen. Bis jetzt bin ich in der Lage zu erkennen, welche Zeile anvisiert wird, aber ich kann nicht herausfinden, wie ich mit der 'actions-column' der Klasse auf die Kind-Div-Datei ausrichten soll.

-Code so weit ...

$(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 

    }); 

}); 

Antwort

6

Sie könnten verwenden live:

$('div.row').live('mouseover', function() { 
    $(this).find('div.actions-column').show(); 
}).live('mouseout', function() { 
    $(this).find('div.actions-column').hide(); 
}); 

Da die Dokumentation Hinweise:

Wenn Sie ein "Live" -Ereignis binden, wird es an alle aktuellen und zukünftigen Elemente auf der Seite gebunden (mithilfe der Ereignisdelegierung).

Noch ein paar Anmerkungen:

  • Ich sehe, Sie sind mit dem $(window).load() Ereignis. Sie möchten wahrscheinlich
  • Sie sollten Advantange von jQuery Chaining-Funktionen statt Abfragen für $('.posts') zweimal, können Sie einfach den zweiten Anruf am Ende (wie ich in meinem Beispiel oben) anhängen - das ist viel effizienter und die bevorzugte Möglichkeit, mehrere Dinge zu 1 Selektor in jQuery zu tun.
  • Der Code, den Sie schreiben möchten, um den nächsten div.row im HTML-Baum zu finden, wurde bereits von jQuerys closest()-Methode implementiert.

Sie könnten damit so etwas tun:

$('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(); 
}); 

Aber dies ist nicht notwendig, weil die live Funktionalität, die ich oben zeigte.

  • Denken Sie über die Effizienz Ihrer Abfragen nach. Wenn Sie nur eine einzige <div> mit einer Klasse von Posts haben, sollten Sie ihr ein ID-Attribut geben. Dies ist bei weitem die effizienteste Methode zum Auswählen von Elementen in einem Dokument, und es ist sinnvoll, sie Elementen zu geben, die nur einmal vorkommen.
  • Wenn Sie nach einem Element nach Klassen suchen, empfiehlt es sich, den Tag-Namen vor die Klasse zu setzen (es sei denn, Sie erwarten natürlich, dass es in vielen verschiedenen Tags vorhanden ist) - statt also nach .row zu suchen Gewohnheit, stattdessen nach div.row zu suchen. Es ist nur schneller.
+1

Es ist erwähnenswert, dass sich die JS-Best Practices für Klassenselektoren von den CSS-Best Practices unterscheiden, da JS keinen nativen Klassenselektor besitzt. CSS tut dies jedoch und da sollte das Element-Tag weggelassen werden. Referenz: http://code.google.com/speed/page-speed/docs/rendering.html – PatrikAkerstrand

+0

$ .live() ist eine performante Verschwendung. $ .delegate() sollte stattdessen verwendet werden. –

+0

Einverstanden; 'live()' ist ein schlechter Weg, dies zu tun. 'delegate()' ist viel besser (wenn Sie den nächsten nicht zerstörten Vorgänger auswählen) und in letzter Zeit (lange nachdem diese Frage gestellt und der Vorgänger akzeptiert wurde), ist '.on()' mit Delegierungssyntax die bevorzugte Methode geworden. –

0

:

$('div.actions-column', $row).show(); // .hide() 

UPDATE:

Es ist besser, jQuery closest([expr]) verwenden:

var $tgt = $(e.target); 
var $row = $tgt.closest('.row'); 

statt:

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;   
} 
0

Versuchen:

$row.find (".actions-column").hide(); 

Und

$row.find (".actions-column").show(); 
1

Versuchen Sie mit jQuery's live() Methode. Es verwendet intern die Ereignisdelegierung, um seine Aktionen auszuführen, sodass Sie nicht einmal daran denken müssen, die Ereignisdelegierung ordnungsgemäß einzurichten.

$('.row').live('mouseover', function() { 
    $(this).find('.actions-column').show(); 
}).live('mouseout', function() { 
    $(this).find('.actions-column').hide(); 
}); 
0

Es sei denn, Sie wirklich dies mit jQuery dann natürlich etwas mit einer Reihe von CSS werden können verwaltet tun wollte:

div.row:hover div.actions-column { display:block; } 
2

Ich weiß, dies wurde bereits beantwortet, aber da jQuery 1.5 fügt eine explizite "Delegate" -Methode hinzu, die jetzt eine bessere Lösung sein könnte. Da dieser Thread bei Suchanfragen verwendet wird, posten ich diese Antwort für andere Nutzer, die danach suchen. (I Refactoring auch für weitere Prägnanz unter Verwendung von "schweben" und "Toggle()" statt 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(); 
}); 

mit jQuery 1.5 oder höher könnte geschrieben als:

$(".posts").delegate("div.row", "hover", function(){ 
    $(this).find("div.actions-column").toggle(); 
}); 

es in Aktion:

http://jsfiddle.net/SM6Jv/