views:

678

answers:

3

I'm creating a page with an image at the top, and a menu below. When the user clicks on on of the 3 menu buttons, the image slideUp and the page scrolls down so the menu is at the top of the page, then the right .content div fades in. The slideUp should only happen the first time the user clicks on of the buttons.

What the absolute best way to do this with jQuery? (no plugins)

I also need to know how I can't prevent it to fade in the page that is already visible if i click the same button twice?

I'm using rel instead of href, since the href made the page jump, even with return false.

This is what I have so far:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"&gt;&lt;/script&gt;
<script type="text/javascript">
$(function(){

 imgVisible = true;

 $('#mainmenu a').click(function(){
  var $activeTab = $(this).attr('rel');
  if(!imgVisible){
   $('html:not(:animated),body:not(:animated)').animate({scrollTop:$('#mainmenu').offset().top-20},500);
   $('.content').hide();
   $($activeTab).fadeIn();
  } else{
   $('#imgholder').slideUp(500,function(){
    imgVisible = false;
    $('#mainmenu a[rel="'+$activeTab+'"]').click();
   });
  }
  return false;
 });

});
</script>

<div id="imgholder"><img src="image.jpg" /></div>

<div id="mainmenu">
 <ul>
  <li><a rel="#tab1"></a></li>
  <li><a rel="#tab2"></a></li>
  <li><a rel="#tab3"></a></li>
 </ul>
</div>

<div id="container">

 <div class="content" id="tab1">
  content
 </div>


 <div class="content" id="tab2">
  content
 </div>


 <div class="content" id="tab3">
  content 
 </div>

</div>
+2  A: 

I think this is a great example of what your looking for: Organic Tabs

Phill Pafford
+2  A: 

The following code accomplishes what you need:

$('#mainmenu a').click(function(){  
    var myrel=$(this).attr('rel');
    $('.content:not([id='+myrel+'])').hide();
    $('#imgholder').slideUp(500,function(){      
        $('#'+myrel).fadeIn();
    });         
});

....
    <li><a href='#' rel='tab0'></a></li>

I have removed the '#' sign from your rel='' piece ;-)

I am not sure why you would want to scroll the page. When a user clicks on the menu, he/she already has it focused (so it is visible inside the current viewport). But do you have a very large top image? If that is the case, let me know and I will modify the snippet. (Still, it depends on the amount of content below the menu visible when the page first loads.)

Also, for SEO reasons you might want to use the href instead of the rel attribute and create separate content holding pages. The following snippet would remove the navigation action.

$('#mainmenu a').each(function(){
    var myhref = $(this).attr('href');
    $(this).attr('href','#').attr('rel',myhref);
}).click(function(){
    var myrel=$(this).attr('rel');
    $('.content:not([id='+myrel+'])').hide();
    //....etc
Ivanhoe
I do have a large image on top, so I need the animated scrolling. And the slideUp only happens once, and since the fadeIn code is a callback of the slideUp, it only fades in the first time you click, that's wrong. The point is, the slideUp should only happen the first time the user click on of the buttons.
mofle
Did you run the code I provided? When the slideUp is invoked for the second time, the fadeIn works perfect. I'll try to submit the scrolling code later.Cheers,
Ivanhoe
Yes, I've run the code now. It actually does work. I thought of something like this before, but I didn't think fadeIn would work, since it was inside the slideUp. Anyway, thanks :D
mofle
+1  A: 
var imgVisible = true;
var $activeTab, $lastTab;
var $mainmenu = $('#mainmenu');
var offset = $mainmenu.offset().top - 20;

$mainmenu.find('a').click(function() {

    $activeTab = $($(this).attr('rel'));

    if (!imgVisible) {
        // dont fire any events if already open
        if ($lastTab.attr('id') == $activeTab.attr('id')) return false;
        $lastTab.fadeOut('normal', function() {
            $activeTab.fadeIn(500, function() {
                $lastTab = $activeTab;
            });
        });
    } else {
        $('#imgholder').slideUp(500, function() {
            imgVisible = false;
            window.scrollTo(0, offset);
            $activeTab.fadeIn(500, function() {
                $lastTab = $activeTab;
            });
        });
    }

    return false;

});

I highly suggest adding <a href="#"> as this will not make the page jump when done properly and will ensure validation on your anchor links. Someone let me know if I missed something, it can be resolved quickly (or you can do it for me if you have an optimization or improvement).

cballou
Found one bug: If you click the <a>'s in the mainmenu fast back and forth, 2 of the buttons will loose their function, and don't do anything when clicked. any ideas why?
mofle
Found out it happens if i first click a link and while animating click another one.
mofle
It could very well be that **imgVisible = false** was triggered but you clicked another button before **$lastTab** was set. You could move **imgVisible = false** to after **$lastTab = $activeTab** to see if that works.
cballou