jQuery - slideToggle Button select

Hi All

I have a jsfiddle here - http://jsfiddle.net/eYV4n/

Really simple navigation and a hidden div block beneath it.

When you click the second link in the nav the div block slides down with slideToggle.

When the div block slides down I would like the button clicked to be selected.

I can do this when it’s clicked by changing the background color.

Is it possible to deselect the link (change it’s color back) when the div block slides again.

jquery.hover() handler hover-in and hover-out. Is it possible to do the same thing with slideToggle.


<!DOCTYPE html>
<html>
  <meta charset="UTF-8">
  <meta name="description" content="">
  <meta name="keywords" content="">
  <meta name="robots" content="">
  <title>Title of the document</title>

  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />

  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>

  <style type="text/css">
    *{
      margin:0;
      padding:0;
    }
    body{
      background:#eee;
    }
    #wrap{
      background:#fff;
      max-width:800px;
      margin:0 auto;
      height:1000px;
    }
    ul{
      list-style:none;
      overflow:auto;
    }
    ul li{
      display:inline;
    }
    ul li a {
      float:left;
      display:block;
      color:#222;
      padding:10px;
      margin:0 5px 0 0;
    }
    #block{
      width:100%;
      margin:0 auto;
      height:200px;
      background:red;
      display:none;
    }
  </style>

  </head>

<body>
  <div id="wrap">
    <nav>
      <ul>
        <li><a href="">One</a></li>
        <li><a href="" id="btn">Two &darr;</a></li>
        <li><a href="">Three</a></li>
        <li><a href="">Four</a></li>
      </ul>
    </nav>

  <div id="block">

  </div>

  </div><!-- #wrap -->


  <script>

    $('#btn').click(function(e){
      e.preventDefault();
      $('#block').slideToggle('2000')
        $('#btn').css('background','red');
    })


  </script>
</body>

</html>

Yes, you can do it by not changing the CSS class directly, and by using a class name instead. That allows you to then use toggleClass.

[css]
.selected {
background: red;
}
[/css]


$('#block').slideToggle('2000');
$('#btn').classToggle('selected');

But then you will notice that the button background gets toggles before the slide has completed. You can deal with that by checking if the block is visible or not, so that the button class can be toggled after the slide has finished, or beforehand.

It’s possible to delay something by supplying it as a callback to the slideToggle function, but we only want to do that half of the time, when the block is being slid up. So a function where we can provide the a function, a callback, and a boolean that decides whether to use it as a normal callback or to run the callback beforehand, would be a good idea. That function could be something like this:


function useCallback(func, callback, precallCallback) {
    if (precallCallback) {
        callback();
        func();
    } else {
        func(callback);
    }
}

Although, the names useCallback and precallCallback might want to have more thought applied to their names.

I’ve also placed the block and button references in to a variable, so that they can be consistantly accessed without a duplication of their names.
It also means that if the “btn” id is moved to a different nav link, that things continue to work without any trouble.


var button = this,
    block = '#block',
    slideBlock = function (callback) {
        $(block).slideToggle('2000', callback);
    },
    toggleButton = function () {
        $(button).toggleClass('selected');
    },
    blockHidden = !$(block).is(':visible');
    
useCallback(slideBlock, toggleButton, blockHidden);

You can see an example of this in action over at http://jsfiddle.net/pmw57/eYV4n/1/

Can anyone think of a more appropriate way to name the parts of this function?


function useCallback(func, callback, precallCallback) {