Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

JavaScript

Liam Maclachlan
Liam Maclachlan
22,805 Points

Why is this 'toggle()' function requiring two clicks before it fires?

I have this function that will hide a table and then replaces the 'up-arrow' image with a 'down-arrow' image but it takes 2 clicks to fire it off the first time.

    $('#test').on('click', '.lsm-toggle-arrow', function() {

        var selectorNum = $(this).attr('value')
        var tableNumber = $('#table'+selectorNum)

        var downArrow = function() {
            $(this).attr('src', pluginURL+'/images/up-arrow.png')
        tableNumber.show()
        }

        var upArrow = function() {
            $(this).attr('src', pluginURL+'/images/down-arrow.png')
        tableNumber.hide()
        }

        $(this).toggle(upArrow, downArrow)

    })

Any idea why this happens and also how to resolve it?

Cheers :)

2 Answers

Hey Liam,

Have you tried testing to see which arrow is currently displayed and then changing the arrow based on that? That might be an easy way to solve your problem. Also, I believe that the toggle() method isn't being used correctly here. You can give callback functions for certain events, but it always starts with either a duration keyword/value and then the options or with an empty object that contains the set of options. toggle displays/hides the elements it's called on, so each call to toggle wants to hide or display the element. It sounds like you shouldn't use toggle here because you don't want the image to disappear, only change.

Try this out. By my syntax, I believe it should do what you want it to do.

    $('#test').on('click', '.lsm-toggle-arrow', function() {
        var selectorNum = $(this).attr('value');
        var tableNumber = $('#table'+selectorNum);
        //if currently up arrow
        if ($(this).attr('src') === pluginURL+'/images/up-arrow.png') {
            //change to down arrow
            //if you don't want this to change instantaneously just use
            //jQuery fadeIn and fadeOut
            //this can be easily done and if you'd like I can show you
            $(this).attr('src', pluginURL+'/images/down-arrow.png');
            tableNumber.show();
        }
        else {
        //else if down arrow, change to up arrow
            $(this).attr('src', pluginURL+'/images/up-arrow.png');
            tableNumber.hide();   
        }
    });
Liam Maclachlan
Liam Maclachlan
22,805 Points

Lol. This is exactly the method I had come up with on previous projects. I stumbled across people using the toggle for functions and thought I would give it a try. Thanks for the suggestion, dude :)

No problem man! You can specify certain functions for toggle, but it just always wants to hide/show the element, and it sounds like you just want the image to change, not hide. Btw, you can get a nice transition effect by using fadeIn and fadeOut. I use that kind of effect for my navigation menu on my main website.

Hi Liam,

Can you simply use the jQuery .hide and show with a few added classes?

$('#test').click(function() {

  $('#myTable').toggleClass('showTable');
  $('#myArrow').toggleClass('rotateArrow');

});

Then you can just use your css to add background images or icons/ add transition duration's to the show and hide classes..

This may not work exactly in your case but it would simplify the code if you could.

Craig

To be more helpful, here is something i have done recently with custom post types for a toggle section on this site under things to know;

                    <div class="drop-group-title">

                          <h2>Things To Know!</h2>

                    </div>

                    <!-- Declare Custom Post Type for Custom Query -->
                    <?php 

                        $args = array(

                            'post_type' => 'info-dropdown'

                        );

                        $infoDropdown = new WP_Query( $args );

                    ?>
                    <!-- //Close Custom Query Declaraiton -->

                    <!-- Open Panel Group For Custom Query Info -->
                    <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">

                        <!-- Open Panel For Looped Content to be Displayed Inside -->
                        <div class="panel panel-default">

                            <!-- Custom Query Loop For Info-Dropdown -->
                            <?php if ( have_posts() ) : while ( $infoDropdown->have_posts() ) : $infoDropdown->the_post(); ?>

                                <!-- Get Items From Custom Post Type Info-Dropdown -->
                                <?php 

                                    //Get Custom Post Type By Slug and Declare as Variable
                                    $title = get_field('title');

                                    //Get Custom Post Type By Slug and Declare as Variable
                                    $info = get_field('description');

                                    //List ID Modifiers For href attr Drop Down Links 
                                    $dropdownContols = array( 'One', 'Two', 'Three', 'Four', 'Five' );
                                    $i = $infoDropdown->current_post;

                                ?>

                            <!-- Open Panel Heading -->
                            <div class="panel-heading red-bg" role="tab" id="headingOne">

                                <h4 class="panel-title page-header">

                                    <a  class="panel-toggle-control"
                                        data-toggle="collapse"
                                        data-parent="#accordion"

                                        href="#collapse<?php echo $dropdownContols[$i]; ?>"

                                        aria-expanded="true"
                                        aria-controls="collapse<?php echo $dropdownContols[$i]; ?>">

                                        <!-- -->  
                                        <?php the_title(); ?>


                                    <i class="fa fa-lg fa-toggle-off"></i>

                                    </a>

                                </h4>



                            </div>
                            <!-- //Close Panel Heading -->

                            <div id="collapse<?php echo $dropdownContols[$i]; ?>"
                                 class="panel-collapse collapse <?php if( $infoDropdown->current_post == 0 ) : ?>in<?php endif; ?>"
                                 role="tabpanel"
                                 aria-labelledby="headingOne">

                                <div class="panel-body">

                                    <?php echo $info ?>

                                </div>

                            </div>        

                            <?php endwhile; endif; ?>
                            <!-- //Close Custom Query Loop -->

                        </div>
                        <!-- //Close Panel for Looped Content -->

                    </div>
                    <!-- Close Panel Group -->
    $('a[href*="#collapseOne"]').children().addClass( 'fa-toggle-on' );
    $('a[href*="#collapse"]').click(function (e) {
        $('a[href*="#collapse"]').children().removeClass( 'fa-toggle-on' );
        $(this).children().addClass( 'fa-toggle-on');
    }); 

This may be more helpful :)

Craig

Liam Maclachlan
Liam Maclachlan
22,805 Points

Hey man. Thanks for the response :) I think that Marcus's answer is better suited this time around but I like you thinking :) I try to avoid using the rotate function due to compatability problems with Dum-dum-duuuuum... IE. Lol :)