5
\$\begingroup\$

I have been working on a toggle script, but I find myself repeating my code. Is there a way of combining it all?

jQuery(document).ready(function($) {
    var topContainer = $("#alles");  
    var topButton = $(".abutton"); 
    topButton.click(function() {
        topContainer.slideToggle(1200, 'easeInOutQuart');
        $(".hideable").slideToggle(1200, 'easeInOutQuart');
    }); 

    var topContainer2 = $("#voorbeelden");  
    var topButton2 = $(".bbutton"); 
    topButton2.click(function() {
        topContainer2.slideToggle(1200, 'easeInOutQuart');
        $(".hideable").slideToggle(1200, 'easeInOutQuart');
    }); 

    var topContainer3 = $("#contact");  
    var topButton3 = $(".cbutton"); 
    topButton3.click(function() {
        topContainer3.slideToggle(1200, 'easeInOutQuart');
         $(".hideable").slideToggle(1200, 'easeInOutQuart');
    }); 
});
.container {
    display:block;
    width:500px;
    margin:0 auto;
}

.hideable {
	width: 500px;
	margin: 0 auto;
}


#alles {
    float:left;
    width:500px;
    height:500px;
    background:#ff4000;
}

#voorbeelden {
    float:left;
    width:500px;
    height:100px;
    border-top:1px solid #ddd;
    background:#cc6600;
}

#contact {
    float:left;
    width:500px;
    height:100px;
    border-top:1px solid #ddd;
    background:#bb3300;
}

.toggleable {
    display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
        <header>
	    <h1>stuff</h1>
	    <h2>more stuff</h2>
    </header>	

    <div id="main" class="hideable"><img src="imgs/rk.svg" alt="image"></div> 
    
 <div id="alles" class="toggleable"></div> 
 <div id="voorbeelden" class="toggleable"></div> 
 <div id="contact" class="toggleable"></div> 
	  
	  <ul>
	      <li>
	          <a href="#" class="abutton">             
		   <h2 class="orsp-title">a</h2>
		   <span class="orsp-category">stuff</span>
		   </a>
	      </li>
              <li>
                <a href="#" class="bbutton">
                    
                    <h2 class="orsp-title">b</h2>
                    <span class="orsp-category">stuff</span>
                </a>
            </li>
            <li>
                <a href="#" class="cbutton">
                    <h2 class="orsp-title cbutton">c</h2>
                    <span class="orsp-category">stuff</span>
		    </a>
		   </li>
	  </ul>
    
</div> <!--/container-->

\$\endgroup\$
  • \$\begingroup\$ Have you looked at event delegation? \$\endgroup\$ – cimmanon Sep 16 '13 at 14:54
3
\$\begingroup\$

First, let's clean up your code a bit more to reduce it to it's basics (demo see here http://jsfiddle.net/bjelline/azfXy/):

<div id="alles" class="toggleable">alles content</div>
<div id="voorbeelden" class="toggleable">voorbeelden content</div>
<div id="contact" class="toggleable">contact content</div>
<ul>
    <li><a href="#" class="abutton">show alles</a></li>
    <li><a href="#" class="bbutton">show voorbeelden</a></li>
    <li><a href="#" class="cbutton">show contact</a></li> 
</ul>

there are three buttons that are supposed to toggle three divs in another part of the page.

First we have to create a connection between the buttons and the divs. that's easy: you already made them links to #, we can just add the id of the corresponding div here. Also, I changed the class on the three buttons to be the same - we have the href to distinguish them:

<div id="alles" class="toggleable">alles content</div>
<div id="voorbeelden" class="toggleable">voorbeelden content</div>
<div id="contact" class="toggleable">contact content</div>
<ul>
    <li><a href="#alles" class="button">show alles</a></li>
    <li><a href="#voorbeelden" class="button">show voorbeelden</a></li>
    <li><a href="#contact" class="button">show contact</a></li> 
</ul>

Now handling the click on the button is the same for all buttons: preven the normal funktioning of the link, read out the href, toggle the correspondig div:

$('.button').click(function (event) {
    event.preventDefault();
    var id = $(this).attr('href');
    $(id).slideToggle(200);
});

Working Demo at http://jsfiddle.net/bjelline/ZmAK4/

And while you are learning jQuery: always try to uphold two principles:

  • the page should still be readable without javascript (progressive enhancement)
  • put all javascript into tags or js-files, not in html attributes

how can we make the page usabel without javascript? easy: without javascript, everything should be visible. how do we achive that? don't use CSS to hide the .togglables but use the first line of javascript instead.

$('.togglables').hide();

P.S. now I try to add the image that indicates if any of the divs is visible (demo see here http://jsfiddle.net/bjelline/HmCWr/)

$('.button').click(function (event) {
    event.preventDefault();
    var id = $(this).attr('href');
    $(id).toggle();

    $('.hideable').toggle( $('.toggleable:visible').length > 0 );
});

Here $('.toggleable:visible').length counts the number of divs that are visible. if theres more then one visible, the image is show, else it is hidden (with the method toggle(true/false) )

Notice that I removed the Slide-Animation. I'm avoiding the following problem: With the slide animation the div that is just closing still count's as open.

If you insist on the slide animation you probably need javascript variables to record the open/close state of each div.....

\$\endgroup\$
  • \$\begingroup\$ thank you bjelli for cleaning up, only one important element got lost during the cleaning :) the image that needs to be hidden when a hidden div is toggled, and needs to re-appear after that same div is hidden again. \$\endgroup\$ – Jonathan 79 Sep 17 '13 at 7:43
  • \$\begingroup\$ is there only one image? that should be visible if any of the divs is shown? \$\endgroup\$ – bjelli Sep 17 '13 at 7:44
  • \$\begingroup\$ Its the other way around, there is one image that is shown unless one or more toggleable divs are shown, then it needs to be hidden. Thank you by the way very much for helping out here! \$\endgroup\$ – Jonathan 79 Sep 17 '13 at 9:38
  • \$\begingroup\$ Maybe the first solution you have written: jsfiddle.net/bjelline/ZmAK4 is combinable with an if else statement that says: if .toggleable = shown .hideable needs to be hidden else (when .togglebale is not visible) .hideable needs to be visible. or doesnt it work like that? \$\endgroup\$ – Jonathan 79 Sep 17 '13 at 9:52
  • \$\begingroup\$ yes, it worked! jsfiddle.net/HmCWr/5 \$\endgroup\$ – Jonathan 79 Sep 17 '13 at 10:38
3
\$\begingroup\$

You can either write a method that is bound to the global scope and takes two arguments, the onClick element and the slideToggle element, and does just what you want (without writing redundant code).

function bindToggleTwo(cElem, tElem) {
   $(cElem).click(function() {
      $(tElem).slideToggle(1200, 'easeInOutQuart');
      $(".hideable").slideToggle(1200, 'easeInOutQuart');
   });
}

jQuery(document).ready(function($) {
    bindToggleTwo("#alles", ".abutton");
    bindToggleTwo("#voorbeelden", ".bbutton");
    bindToggleTwo("#contact", ".cbutton");
});

Alternatively, you could write a jQuery function that is called on a jQuery object to do the very same. Basically this is a function that expects to be scoped such that this is a jQuery object. Anyway, both of these methods work, and will simplify your code. :)

jQuery.fn.bindToggleTwo = function(tElem) {
  $(this[0]).click(function() {
     $(tElem).slideToggle(1200, 'easeInOutQuart');
     $(".hideable").slideToggle(1200, 'easeInOutQuart');
  });
}

jQuery(document).ready(function($) {
    $("#alles").bindToggleTwo(".abutton");
    $("#voorbeelden").bindToggleTwo(".bbutton");
    $("#contact").bindToggleTwo(".cbutton");
});
\$\endgroup\$
  • 2
    \$\begingroup\$ I would +1 this if you had a description of what you are suggesting, and why you are suggesting it. \$\endgroup\$ – Jeff Vanzella Sep 16 '13 at 16:32
  • \$\begingroup\$ added brief explanation \$\endgroup\$ – Sam Grondahl Sep 16 '13 at 18:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.