views:

4777

answers:

10

I would like to show a div based on the Onclick event of an link.

First Click - Show div1
Second Click - Hide remaining div's and Show div2
Third Click - Hide remaining div's and show div3
Fourth Click - Hide remaining div's and show div1 => repeat the loop and goes on..

Code Follows:

<div class="toggle_button">
      <a href="javascript:void(0);" id="toggle_value">Toggle</a>
</div>


<div id='div1' style="display:none;"> 
  <!-- content -->
</div>

<div id='div2' style="display:none;"> 
  <!-- content -->
</div>

<div id='div3' style="display:none;"> 
  <!-- content -->
</div>

Jquery Code :

$(document).ready(function() {
        $("#toggle_value").click(function(){
           $("#div1").show("fast");
           $("#div2").show("fast");
           $("#div3").show("fast");
        });
});

The above code shows all divs on first click itself but it should show div1 on first click as mentioned.

+1  A: 

You should add a counter in the function.

$(document).ready(function() {
    var count = 0;

    $("#toggle_value").click(function(){
        if (count == 0) {
            $("#div1").show("fast");
            $('#div2').hide();
            count++;
        }
        else if (count == 1) {
            $("#div2").show("fast");
            ...
            count++;
        }
        else if (count == 2) {
            $("#div3").show("fast");
            ....
            count++;
        }
        else {
             $('div').hide();
             count=0;
        }
    });
});
Peter Stuifzand
that last else-statement should probably also show the first div, as he wants it to loop.
peirix
Thanks Peter . And as peirix mentioned ya it need to show the first div as a loop.But in that 4th click it will hide all divs rather than showing the first div.
Webrsk
Yep this code is crap.
Peter Stuifzand
This is one of the different solution and will work if we change the else case to $('#div2').hide();$("#div").show("fast");$('#div1').hide();count=1;
Webrsk
A: 

A simple way would be to introduce a variable that tracked clicks, so something like this:

var tracker = 0;    
$(document).ready(function() {
    $("#toggle_value").click(function(){
       if(tracker == 0)
       {
          $("#div1").show("fast");
       }else if(tracker ==1)

       etc etc

       tracker ++;

    });
});
ilivewithian
A: 

My solution is a little different - I'd do it dependant on the state of the divs at the current time (on click). See below for what I mean by this.

$(document).ready(function() {
    $("#toggle_value").click(function(){
       if ($("#div1).is(':visible')) { // Second click
            // Hide all divs and show d2
            $("#div1").hide();
            $("#div2").show("fast");
            $("#div3").hide();
            $("#div4").hide();
       } else if ($("#div2").is(':visible')) { // Third click
            // follow above example for hiding all and showing div3
       } else if ($("#div3").is(':visible')) { // Fouth click
            // follow above example for hiding all and showing div1
       } else { // first click
            // All divs should be hidden first. Show div1 only.
            $("#div1").show("fast");
       }
    });
});

Just to warn you - I have not tested this code :) Based upon the following for determining visibility: http://docs.jquery.com/Frequently_Asked_Questions#How_do_I_determine_the_state_of_a_toggled_element.3F

Hope it helps

Splash
Don't hard code something that can be dynamic. What if you want to change this code to incorporate 100 divs? Are you going to code 400 lines of confusing ifs and repeated code?
Antony Carthy
Well that'd be a different question, and not what was asked. I took it more to mean that there were only the 3 divs, and the div names would not normally be numbered and may be actual names. I take your point however.
Splash
+1  A: 

I'll try my shot.


EDIT: After second though, to avoid global variable use it's better to do the following

$(document).ready(function() {
        $("#toggle_value").click((function(){
        var counter = 0;
        return function()
        {
           $("#div" + counter).hide("fast");
           counter = (counter % 3) + 1;
           $("#div" + counter).show("fast");
        }
        })());
});
Artem Barger
Hmm... that's interesting. But on 4th click it hides all div and it on 5th click it shows the div1 again.Missing any cases ?!
Webrsk
I've missed the point it have to iterate all the time. Fixed.
Artem Barger
Artem while it was works fine when the var is global, after i tried the recent posted code it stops working ..
Webrsk
This assumes that "#div" + counter is actually the next div to show. This is the exact same constraint you criticize in my answer. You rely on predictable names, I rely on document order. Where is the difference?
Tomalak
@Tomalak: First of all it's was described in the question. And second it could be easily changed to use the mapping array of strings with divs names. While your solution is for more narrow case.@Webrsk: Thanks for pointing to mistake. Has been fixed.And for those who loves to downvote, please be kind and explain yourself, I can understand down voting of completely unhelpful answer but what was wrong here?
Artem Barger
Thanks for the update. Will try it out :) The answer was helpful +1
Webrsk
So, who on earth has down voted it?
Artem Barger
I didn't, if that's what you're asking.
Tomalak
Actually I haven't mentioned you. Moreover I don't believe our debating regarding your answer might lead to something like this.
Artem Barger
A: 
var c = 1;
$("#toggle_value").click(function()
{
   $("#div" + c).hide("fast");        
   $("#div" + ++c).show("fast");
   if (c > 3) c=1;       
});
Antony Carthy
Thanks for posting it. Just fixed the syntax error of the code which you posted and tried.var c = 1;$("#toggle_value").click(function(){$("#div" + c).hide("fast"); if (c > 3) c=1;$("#div" + c++).show("fast"); });First 3 clicks works fine after that it shows 2 divs at same time...
Webrsk
use my second solution on this page rather...
Antony Carthy
I have edited this one - should work now...
Antony Carthy
A: 

I would probably do something like: (The following assumes all your <div>s are in a container with id "container")

$(document).ready(function() {
  var $allDivs = $("#container > div");
  var counter = 0;

  $("#container > div").click(function(){
    counter = counter < $allDivs.length - 1 ? counter + 1 : 0;
    $allDivs.not(":eq("+counter +")").hide("fast");
    $allDivs.eq(counter).show("fast");
  });
});
Tomalak
here you make very strong assumption that div's is ordered in container according to id number, which might be false in general
Artem Barger
don't you think there is more divs in the container than described?
Artem Barger
Thinking about it, your are right. On the other hand, if they are to be shown sequentially in a particular order, why not lay them out in that particular order right away? Instead of creating "ordered" id attributes for an unordered set of elements.
Tomalak
It could some design constraint.
Artem Barger
Could be. OTOH, most of the time you are writing JavaScript, you also have control over the HTML generation process. Ordering the divs the proper way should be not too complicated, and the question implies they already are. Well... if this is not possible, the above solution does, admittedly, not work.
Tomalak
But who say that sequential order is the right order for those divs?
Artem Barger
That's what I was saying (read my previous comment again if it was not apparent) Anyway: My guess is that they a) are in the right order already, b) can easily be brought into the right order, or c) that it doesn't matter and this whole discussion is purely academic.
Tomalak
Do you know what the difference? I'm trying to say that you cannot count on order and there is couldn't be the "right" in general case, since you don't know anything about design constraint. Example: each of those divs can be easily encapsulated within another more global divs.
Artem Barger
Then maybe the question should have been asked differently. The approach the OP took does not imply anything more complicated than what he was showing. So why solve problems that are not part of the question.
Tomalak
I didn't tell you solution is wrong, only pointed it wouldn't work in general case.
Artem Barger
A: 

I prefer to use "filter" method and make a little easier work with counter:

(function () {
    var divCounter = 0, divs;

    $(function () {
        divs = $('#div1, #div2, #div3');
        $('#toggle_value').click(function (e) {
            divs.hide() // hide other divs
                .filter(function (index) { return index == divCounter % 3; }) // select appropriate div
                .show('fast'); // and show it

            divCounter++;
        });
    });

})();
Alexander Ulizko
A: 

The .toggle function in jQuery takes any number of argument functions, so the problem is already solved. See the docs under Events.

A: 
$("#toggle_value").click(function()
{
   $("#div" + (++c) % 3).show().siblings().hide();        
}
Antony Carthy
and what if those divs are not siblings?
Artem Barger
They are in the example. Its like saying what if they are not on the same page? What if they are text boxes. What if you are running this on the iPhone?
Antony Carthy
Funny O_o. In the example you have the shorten code sample, which I believe in real much more complicated in general, so by your code you will hide all sibling no matter what.
Artem Barger
+1  A: 

How about this

Working Example here - add /edit to URL to edit the code

$('html').addClass('js'); // prevent hiding divs on DOM ready from 'flashing'

$(function() {

  var counter = 1;

  $('#toggle_value').click(function() {
    $('div','#container')
      // to stop current animations - clicking really fast could originally
      // cause more than one div to show 
      .stop() 
      // hide all divs in the container
      .hide() 
      // filter to only the div in question
      .filter( function() { return this.id.match('div' + counter); })
      // show the div 
      .show('fast');

    // increment counter or reset to 1 if counter equals 3
    counter == 3? counter = 1 : counter++; 

    // prevent default anchor click event
    return false; 

  });

});

and HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"&gt;&lt;/script&gt;
<title>Div Example</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<style type="text/css" media="screen">

    body { background-color: #fff; font: 16px Helvetica, Arial; color: #000; }
    .display { width:300px; height:200px; border: 2px solid #000; }
    .js .display { display:none; }

</style>
</head>
<body>
<div class="toggle_button">
      <a href="#" id="toggle_value">Toggle</a>
</div>
<br/>
<div id='container'>
    <div id='div1' class='display' style="background-color: red;"> 
        div1
    </div>

    <div id='div2' class='display' style="background-color: green;"> 
        div2
    </div>

    <div id='div3' class='display' style="background-color: blue;"> 
        div3
    </div>
<div>

</body>
</html>

This could easily be wrapped up in a plugin

Russ Cam