views:

80

answers:

3

Hiya,

I'm trying to get a toggle effect but not quite sure how to do it or what to look for. (i jave Jquery loaded).

assume html similar to

<table class="left-dates">
    <tr><td>All Dates</td></tr>
    <tr><td>01 dec 2009</td></tr>
    <tr><td>02 dec 2009</td></tr> 
    <tr><td>03 dec 2009</td></tr> 
    <tr><td>04 dec 2009</td></tr> 
</table>

<div class="box 01-dec-2009">
    foo
</div>

<div class="box 03-dec 2009">
    bar
</div>

<div class="box 04-dec-2009">
    foobar
</div>

Steps to take

  1. All div's are shown
  2. Clicking on a td for a date will hide all but the div with the class of the day clicked
  3. clicking "All dates" will show everything again

any idea how i could achive this cleanly? ideally using JQuery.

+1  A: 

I would try it this way:

var $boxes = $('div.box');

$('.left-dates td:gt(0)').click(function(e){
   var class = this.innerHTML.replace(/ /g, '-'); // Convert text to class
   $boxes.filter(':visible').not('.' + class).hide(); // All visible div.box that don't have the class we are going to show.
   $boxes.filter('.' + class).show(); // Show this class
});
$('.left-dates td:first').click(function(e){
   $boxes.show();
});

EDIT: I swapped .click() in for .live('click'). If there were going to be a ton of rows, it might be better to use .live() instead of binding a click() event to each td

Also, the HTML you posted has an error. The 03 div is missing a hyphen before the 2009

Doug Neiner
Just posted a small fix to my code. The replace function was only finding the first space, not all the spaces.
Doug Neiner
Large overhead for a live selector. It will run this on every document click event. It is best to keep any live events to simple selectors, otherwise use native event delegation
redsquare
I thought so to until I attended #jqcon in Boston and was told otherwise by the core team mebers. `live` is surprisingly faster and leaner than binding a separate click method to each event.
Doug Neiner
I think the issue is the fact that the selector gets run over and over on each doc click. Thats why they are adding context to live for 1.4 so you can delegate to a container rather than the doc all the time
redsquare
@redsquare Haha... thats what I get for over optimizing the code :) Per your suggestion I updated my example, and left a recommendation for .live if there were lots of rows.
Doug Neiner
A: 

Here is a working example with jQuery.

Note that I had to change your div classes and td labels to remove whitespace so that the labels would be equivalent to the class-names. If you didn't want dashes in the labels you could do string manipulation in Javascript to remove white-space or give the tds the same classname as their corresponding div and then look at the classname of the clicked td rather than its inner-text.

<html>
<head>
    <title>jQuery hiding example</title>

    <script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js'&gt;&lt;/script&gt;

    <script type='text/javascript'>
     $(document).ready(function(){
      $('td').click(function() {
       var target = $(this).text();
       if (target == 'All Dates') {
        $('div.box').show();
       } else {
        $('div.box').hide();
        $('div.' + target).show();
       }
      });
     });
    </script>
</head>
<body>
    <table class="left-dates">
     <tr><td>All Dates</td></tr>
     <tr><td>01-dec-2009</td></tr>
     <tr><td>02-dec-2009</td></tr>       
     <tr><td>03-dec-2009</td></tr>       
     <tr><td>04-dec-2009</td></tr>       
    </table>

    <div class="box 01-dec-2009">
     foo
    </div>

    <div class="box 03-dec-2009">
     bar
    </div>

    <div class="box 04-dec-2009">
     foobar
    </div>
</body>
</html>
Adam Franco
update: Added case for 'All Dates'.
Adam Franco
Quick and clean, i implemented a hacked version of this but you gave me all the info i needed, thank you. Accepted :)
Shadi Almosri
A: 

Identify your <td>All Dates</td> uniquely. Assign the same class or some other identifier to all your date <td>s. Give them a click handler that hides all the .box elements except the one with the same date. In your example you're not consistent with making the date in the <td> the same as the class name of the date in your divs, which you'll need for what I'll do.

<table class="left-dates">
    <tr><td id="alldates">All Dates</td></tr>
    <tr><td id="date">01 dec 2009</td></tr>
    <tr><td id="date">02 dec 2009</td></tr>       
    <tr><td id="date">03 dec 2009</td></tr>       
    <tr><td id="date">04 dec 2009</td></tr>       
</table>

// unhide all box elements
$("#alldates").click(function(e){ $(".box").show(); });

// For each date <td> element
$("#date").each(function(){
   // assign a click event
   $(this).click(function(e){
      // when the user clicks, get the
      // <td>'s text contents
      var myval = $(this).text();
      // and grab each element with the
      // 'box' css class
      $(".box").each(function(){
         // for each of these 'box' elements,
         // if it has a class matching the date
         // they selected, return
         if($(this).has(myval))
         {
            return;
         }
         else
         {
            // otherwise, hide itself
            $(this).hide();
         }
      });
   });
});
Jonathon