views:

303

answers:

4

OK, I'm designing a site and thought I'd stick some jQuery in as I really need so js experience.

Page with my problem is here: http://new.focalpix.co.uk/moreinfo.php

JS in question is:

$(document).ready(function(){

    $(".answer").css("display","none");

    $("#maincontent a.animate").click(function() {
     $("#maincontent .answer").slideUp('slow');
     var id = $(this).attr('href');
     $(id).slideDown('slow');
     return false;
    });

});

This works fine, but if you click on a link where the answer has already slid down, then it slides up, then back down again.

I'm not sure on the cleanest way to stop this happening - any ideas?

+7  A: 

You should be using the .slideToggle() effect.

$(document).ready(function() {
    $(".answer").css("display","none");
    $("#maincontent a.animate").click(function() {
        $("#maincontent .answer").slideToggle('slow');
    });
});
Soviut
That toggles all the answers for every question, not just the one we want...
Rich Bradshaw
$("#maincontent a.animate").click(function() { var id = $(this).attr('href'); $(id).slideToggle('slow'); return false; });
Rich Bradshaw
A: 

try using the one method, something like:

 $(selector).one('effect', 'data for effect', callback function);

it makes sure an effect only happens once per element.

Pim Jager
+5  A: 

First, I'd suggest the following structure for your faq's:

<div id="faq">
  <div class="qa" id="faq_greenandflies">
 <span class="q">What is <a href="#faq_greenandflies">green and flies</a></span>
 <div class="a">
   Super Pickle!
 </div>
  </div>
  <div class="qa" id="faq_redandbadforteeth">
 <span class="q">What is <a href="#faq_redandbadforteeth">Red and bad for your teeth</a></span>
 <div class="a">
   a Brick
 </div>
  </div>
  <!--
  More FAQ's here

  -->
</div>

and then defining your jQuery as follows:

 <script type="text/javascript">
    $(function(){
  // hide all answers
  $('div#faq .qa .a').hide();

      // bind a click event to all questions
  $('div#faq .qa .q a').bind(
        'click',
        function(e){
          // roll up all of the other answers (See Ex.1)
          $(this).parents('.qa').siblings().children('.a').slideUp();
          // reveal this answer (See Ex.2)
          $(this).parents('.qa').children('.a').slideDown();
          // return true to keep any other click events    
          return true;
        });

      // check location.hash to see if we need to expand one (direct link)
      $(location.hash).find('.q a').click();
    });
</script>

Explanation:

(Ex.1)

  • this is the link that was clicked
  • get the element that contains this and has a class of 'qa' (the box that contains both question and answer)
  • select all of its siblings. (we now have all qa's as a jQ object)
  • hide the answers

(Ex.2)

  • this is the line or link that was clicked
  • get the element that contains this and has a class of 'qa' (the box that contains both question and answer)
  • reveal the answer

A working demo is here.

This does several things for you:

  • If a user deep-links to an answer, the answer is automatically revealed
  • If a user clicks on one answer, all other answers are hidden
  • You can give your divs proper ids, so which helps search engine optimization of links to individual answers
yaauie
I noticed that although you accepted my answer, your now-implemented page does not use this solution and thus bypasses a user's ability to link directly to an item (from outside the page itself)
yaauie
I've tried implementing it, but it just won't do anything on my site - can't work out the difference between your code and mine - even when I copy and paste! I'll have to keep trying!
Rich Bradshaw
Seems that if I put any tags inside the answer div then nothing works...
Rich Bradshaw
A: 

Use slideToggle() like Soviut said, but just as a tip -- you can declare the display property in the actual CSS file instead of declaring it inside the javascript. jQuery will pick up on the fact that it is hidden in the stylesheet and still perform the appropriate slide function.

You can also use $(".answer").hide();

Instead of setting the display CSS property. Just thought I would let you know.

Logan Serman
I wanted to set the css in jquery so that for UAs that don't have JS enabled they can still read it.
Rich Bradshaw