Trying to use variables to shorten my jquery

I'm trying to shorten the following code(which works) using variables. It seems pretty redundant, so yeah.

<script type="text/javascript">
$(document).ready(function(){
    $("div.first").click(function()
    {
        if ($('#firsthidden').css('display') == "block")
        {
            $("#firsthidden").hide("blind", "slow");
            $("div.outer").animate({height:200},"slow");
        }
        else
        {
            $("#firsthidden").show("blind", "slow");
            $("div.outer").animate({height:390},"slow");
        }
        if ($('#secondhidden').css('display') == "block")
        {
            $("#secondhidden").hide("blind", "slow");
        }
        if ($('#thirdhidden').css('display') == "block")
        {
            $("#thirdhidden").hide("blind", "slow");
        }
    });
    $("div.second").click(function()
    {
        if ($('#secondhidden').css('display') == "block")
        {
            $("#secondhidden").hide("blind", "slow");
            $("div.outer").animate({height:200},"slow");
        }
        else
        {
            $("#secondhidden").show("blind", "slow");
            $("div.outer").animate({height:390},"slow");
        }
        if ($('#firsthidden').css('display') == "block")
        {
            $("#firsthidden").hide("blind", "slow");
        }
        if ($('#thirdhidden').css('display') == "block")
        {
            $("#thirdhidden").hide("blind", "slow");
        }
    });
    $("div.third").click(function()
    {
        if ($('#thirdhidden').css('display') == "block")
        {
            $("#thirdhidden").hide("blind", "slow");
            $("div.outer").animate({height:200},"slow");
        }
        else
        {
            $("#thirdhidden").show("blind", "slow");
            $("div.outer").animate({height:390},"slow");
        }
        if ($('#secondhidden').css('display') == "block")
        {
            $("#secondhidden").hide("blind", "slow");
        }
        if ($('#firsthidden').css('display') == "block")
        {
            $("#firsthidden").hide("blind", "slow");
        }
    });

});
</script>

So I'm trying to shorten this using variables. I've got the code logic down, so I guess it's a syntax/formatting issue. Here's my attempt:

<script type="text/javascript">
var x = null;
var a = null;
var b = null;

$(document).ready(function(){
    $("#first").click(function()
    {
        x = $("#firsthidden");
        a = $("#secondhidden");
        b = $("#thirdhidden");
    });
    $("#second").click(function()
    {
        x = $("#secondhidden");
        a = $("#firsthidden");
        b = $("#thirdhidden");
    });
    $("#third").click(function()
    {
        x = $("#thirdhidden");
        a = $("#firsthidden");
        b = $("#secondhidden");
    });
    $("div.clicked").click(function()
    {
        if (x.css('display') == "block")
        {
            $(x.hide("blind", "slow");
            $("div.outer").animate({height:200},"slow");
        }
        else
        {
            x.show("blind", "slow");
            $("div.outer").animate({height:390},"slow");
        }
        if (a.css('display') == "block")
        {
            a.hide("blind", "slow");
        }
        if (b.css('display') == "block")
        {
            b.hide("blind", "slow");
        }
    });
});
</script>

Answers


You should be able to reduce all that code down to this:

$(document).ready(function() {

    var all = $('#firsthidden, #secondhidden, #thirdhidden'),
        arr = ['div.first', 'div.second', 'div.third'];

    all.each(function(i) {
        var this_hidden = this;

        $(arr[i]).click(function() {
            var the_height = $(this_hidden).css('display') == 'block' ? 200 : 390;
            $(this_hidden).toggle("slow", "linear");
            $("div.outer").animate({height: the_height },"slow");
            all.not(this_hidden).hide("slow", "linear");
        });
    });

});
  • cache the '#firsthidden, #secondhidden, #thirdhidden' elements in all

  • make an Array of the selectors that get the click handlers 'div.first', 'div.second', 'div.third'

  • use the toggle()[docs] method to show or hide the "#...hidden" element (this_hidden) instead of using an if statement

  • use the "#...hidden" element represented by this_hidden to determine the proper height to animate "div.outer"

  • simply .hide() the other two "#...hidden" elements without the if, excluding the one that is toggled by using the not()[docs] method.


EDIT: Replaced the missing line that animated "div.outer". Thanks to @natedavisolds for pointing it out.

EDIT 2: My selector for the hidden elements was wrong. I had $('#firsthidden', '#secondhidden', '#thirdhidden') instead of $('#firsthidden, #secondhidden, #thirdhidden').

Also, I copied the reversed "blind" and "slow" from the question.

Fixed.

EDIT 3: I was setting the the_height variable too late. Moved it up a line so it runs before the animation begins, and it works.

Shame on me for not testing my code!!!

Example: http://jsfiddle.net/NnyGR/


 $("div.clicked").click(function()
    {
        if (x.css('display') == "block")
        {
            $(x.hide("blind", "slow");
            $("div.outer").animate({height:200},"slow");
        }

Needs to be

 $("div.clicked").click(function()
    {
        if (x.css('display') == "block")
        {
            x.hide("blind", "slow");
            $("div.outer").animate({height:200},"slow");
        }

Try this.

$(document).ready(function(){
    $("#first").click(function()
    {
        MyFunction($("#firsthidden"), $("#secondhidden"), $("#thirdhidden"));
    });
    $("#second").click(function()
    {
        MyFunction($("#secondhidden"), $("#firsthidden"), $("#thirdhidden"));
    });
    $("#third").click(function()
    {
        MyFunction($("#thirdhidden"), $("#secondhidden"), $("#firsthidden"));
    });
    function MyFunction(x, a, b)
    {
        if (x.css('display') == "block")
        {
            $(x.hide("blind", "slow");
            $("div.outer").animate({height:200},"slow");
        }
        else
        {
            x.show("blind", "slow");
            $("div.outer").animate({height:390},"slow");
        }
        if (a.css('display') == "block")
        {
            a.hide("blind", "slow");
        }
        if (b.css('display') == "block")
        {
            b.hide("blind", "slow");
        }
    });
});

If you're going for something like a tabbed content. There are plugins or you can write it on your own. Could be something along the lines of this http://jsfiddle.net/XYGHQ/6/


Need Your Help

RestKit Doing a Post With Object and Getting Object Response

ios post restkit restkit-0.20

I am new to both IOS and RestKit and can not figure out how to do the following:

PrimeFaces Dialog Incorrect Header Size

css google-chrome jsf jsf-2 primefaces

PrimeFaces 4.0 Dialog headers fit well to dialog window in IE and Firefox but not in Chrome unless i move mouse cursor over the dialog header. When I move the cursor to dialog header it scales and ...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.