0

I've been having some trouble with some code I am using.

Context:
I am using Twitter Bootstrap 3 for a website and I want the navigation bar fixed at the top. When I scroll down I want the navigation bar to get a white background and different color text. This is triggered when I scroll down 60px.

As Bootstrap has a collapsible menu I want have the whole navbar to get a white background as soon as I click on the "navbar-toggle". So far so good and everything works, BUT here's the thing. The menu takes a couple of milliseconds to collapse and I don't want the white background of the navbar to turn transparent at the same time the navbar collapses. (hope that makes sense) So what I did was create 2 functions that would turn a css class on or off. (for the record: i used css transitions and they work perfectly ;) )

The problem arose when I made a click and scroll event watcher in javascript. When I click on the "navbar-toggle" the delay kicks in and the collapse menu is gone and than the navbar turns transparent. But when I scroll it doesn't and turns transparent immediately after I scroll a pixel.

Hope it makes a sense and hope you can help me out on this one. Also please note that I have 4 situations atm that will collapse the navbar. 1. clicking a link IN the navigation 2. clicking outside the navigation 3. scrolling 4. Clicking on the navbar-toggle itself

Javascript:

// Pixels from the top before navbar turns on (gets white background)
var header_toggle_height = 60;

$('.navbar-toggle').click(function(event) {
    if (!close_header('turnOff')) {
        headerOn(); 
    }
});

// Close the header parts
function close_header(option){

    // set default option 
    option = typeof option !== 'undefined' ? option : 'close_header';

    // Set var to tell if navigation is expanded
    var expanded = $('.navbar-collapse').attr('aria-expanded');

    // Default result
    var result = false;

    switch(option) {
        case 'close_header':
            close_header('delOff')
            break;
        case 'collapse_nav':
            collapse_nav();
            break;
        case 'turnOff':
            if ( expanded === 'true' ) { 
                close_header('delOff'); 
            } else {
                result = headerOff();
            }
            break;
        case 'delOff':
            collapse_nav();
            setTimeout("result = headerOff()",300);
            break;
    }

    return result;
}

// When the user scrolls collapse the navigation and at certain hight from top turn off navbar (make it transparent)
$(window).scroll(function(event){
    if ($(window).scrollTop() >= header_toggle_height) {
        headerOn();
    } else if ($(window).scrollTop() < header_toggle_height) {
        close_header('turnOff'); 
    }
});

// Turn the header on (make it white)
function headerOn() {

    if ( !$('.navbar').hasClass('scrolled') ) { 
        $('.navbar').addClass('scrolled');  
        return true;
    } else {
        return false;
    }

 }

// Turn the header off (Make it transparant), when at a certain point from the top.
function headerOff () {

    if ($('.navbar').hasClass('scrolled') && $(window).scrollTop() <= header_toggle_height ) {
        $('.navbar').toggleClass('scrolled');   
        return true;
    } else {
        return false;
    }

}

//Collapse navigation on mobile
function collapse_nav () {
    $('.navbar-collapse').collapse('hide');
}

HTML note: don't mind the php in the navbar classes. that is for something different

    <header>
        <!-- NAVBAR
        ===========================================-->
        <nav class="navbar-wrapper">
            <div class="navbar navbar-collapsed-lg   navbar-default navbar-fixed-top <?php if (isset($_GET['FlightCode'])){ ?> navbar-fixed-top-calc <?php } ?>" id="autoscroll" role="navigation">
                <div class="container" >
                    <div class="navbar-header">
                        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse" >
                            <span class="sr-only">Toggle navigation</span>
                            <span class="icon-bar"></span>
                            <span class="icon-bar"></span>
                            <span class="icon-bar"></span>
                        </button>
                        <a class="navbar-brand" href="/"><?php echo $to_title_p1; ?><span><?php echo $to_title_p2 ?></span><?php echo $to_title_p3 ?></a>
                    </div> <!-- navbar-header -->
                    <?php
                        wp_nav_menu( array (

                            'theme_location'    => 'primary',
                            'container'         => 'nav',
                            'container_class'   => 'navigation-scroll navbar-collapse navbar-header-collapse collapse',
                            'menu_class'        => 'nav navbar-nav navbar-right'

                        ) );    
                    ?>
                </div> <!-- container -->
            </div> <!-- navbar -->
        </nav> <!-- navbar-wrapper -->
    </header> <!-- header -->
Controvi
  • 487
  • 1
  • 6
  • 16
  • Please, provide `html` code too. – Alexandr Lazarev Sep 22 '15 at 12:56
  • `setTimeout` is asynchronous, meaning you cannot have it do `result = X` and still `return result;` in the code following it. – Niet the Dark Absol Sep 22 '15 at 13:03
  • See http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call for relevant information. – Niet the Dark Absol Sep 22 '15 at 13:05
  • As I state in the context it works fine if I click on the "navbar-toggle" but when I scroll it doesn't. So that can't be the problem. Also note that the click function even uses the returned value for an if statement – Controvi Sep 22 '15 at 13:06
  • When you just call `result = headerOff();`, that's synchronous. When you call `setTimeout(/* anything really*/)` that's asynchronous. The result from an asynchronous call will not be available to the calling function. You need a proper callback that can finish the rest of what you want done in your close_header or headerOn function to call from your timeout. This will also let you avoid using the `eval` that's inherent in passing a string to settimeout. – Patrick M Sep 22 '15 at 13:18
  • Ok I think I understand but the timeout is the last step of the process so nothing after it is run. still I don't understand why the clicking does work but the scrolling isn't – Controvi Sep 22 '15 at 13:25
  • I also don't understand, that's why I didn't make an answer. Have you tried making a minimal example? A bit of code that just includes the scroll stuff could help diagnose what's wrong with the rest of it. – Patrick M Sep 22 '15 at 14:34
  • This is everything that has to do with with the scroll stuff. I included the click action so I could mention that that works. I have been playing around with the order of things but that isn't working either :/ Looks like I'm gonna be bussy for a while XD – Controvi Sep 22 '15 at 14:37

0 Answers0