0

I was looking at the code on this SO question and thought it would be useful in toggling a div's visibility, like a navbar, dependent upon another element on the page being visible on screen or not. Here is the code I used from the page:

function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();

var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();

return ((docViewTop < elTop) && (docViewBottom > elBottom));
}

I tried constructing a function to do this, but unfortunately I suck at programming. Here is what I used:

$('#magicnav').hide();
var intro = $('#intro');
$(document).ready(function () {
   if (intro.isScrolledIntoView()) {
    $('#magicnav').fadeOut();
   } else {
    $('#magicnav').fadeIn();
    }
  });

I tried the statement if(isScrolledIntoView($intro)) as well, but obviously that's incorrect as well. Can anyone help me out?

Here is a jsfiddle of the page for reference. My goal is to have a fixed navbar at the top of the screen that only shows when a specific div (also containing nav links) is NOT on screen.

You may notice that I have stuck the 'magicnav' div in the middle of the page. This was on purpose, as I wanted to keep it from being fixed to the top at present and needed to ensure that I could quickly see whether or not my jQuery was working.

Community
  • 1
  • 1
huzzah
  • 1,773
  • 2
  • 21
  • 40
  • Where are you adding the scroll event? – megawac Nov 09 '13 at 22:26
  • I actually tried starting my function with $(window).scroll(), and it immediately showed the 'magicnav' div (which is wrong since the intro div is showing), plus the 'magicnav' div never disappeared with scrolling. – huzzah Nov 09 '13 at 22:31

2 Answers2

3

$(document).ready() only checks the state of the element once. Instead, use $(window).on('scroll');

I fixed it in this JSFiddle

Borre Mosch
  • 3,584
  • 1
  • 16
  • 28
1

Basic troubleshooting

The first step to troubleshooting a script: always check your console for errors. By checking the console when your Fiddle is loaded, I see this error:

Uncaught TypeError: Object [object Object] has no method 'isScrolledIntoView'

This is because there is no method called .isScrolledIntoView. It is a simple JS function, where you supply the element's identification (class or ID), which it then returns if the said element is in view or not. It should be used something like this:

// For class
if(isScrolledIntoView(".class")) {...} else {...}

// For ID
if(isScrolledIntoView("#id")) {...} else {...}

This is because the function evaluates the element based on this line:

var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();

Also, elTop and elBottom are actually not defined. I believe it is a typo. Here is the fixed function:

function isScrolledIntoView(elem) { var docViewTop = $(window).scrollTop(); var docViewBottom = docViewTop + $(window).height();

var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();

return ((docViewTop < elemTop) && (docViewBottom > elemBottom));

}


Your fiddle

When manipulating your DOM, always do them when the DOM is ready, i.e.:

$(document).ready(function () {
    $('#magicnav').hide();
    $(window).scroll(function() {
        if (isScrolledIntoView('#intro')) {
            $('#magicnav').fadeOut();
        } else {
            $('#magicnav').fadeIn();
        }
    });
});

Note that I have moved the .hide() method into the DOM ready event, too. Also, the function isScrolledIntoView is only fired once upon DOM ready in your original Fiddle. You will have to fire it every time a scroll event is detected, so I have wrapped your conditional statement inside the $(window).scroll() event.

I have fixed your fiddle — http://jsfiddle.net/teddyrised/XN82s/10/


Additional Notes

When listening to .scroll() events, some browsers do it too many times when you start to move the scrollbar. A good practice would be to throttle this, e.g. using this nifty plugin.

Your code only requires minimal modification:

$(document).ready(function () {
    $('#magicnav').hide();

    // Here we throttle the scroll event to firing once every 250ms
    $(window).scroll($.throttle(250, function() {
        if (isScrolledIntoView('#intro')) {
            $('#magicnav').fadeOut();
        } else {
            $('#magicnav').fadeIn();
        }
    }));
});
Terry
  • 48,492
  • 9
  • 72
  • 91
  • This is an excellent explanation and helped me learn, so THANK YOU. I had initially set my function up with a $(window).scroll() function, and with my if statement being if(isScrolledIntoView('#intro')), and because it didn't work I abandoned it (stupidly apparently!). Your solution works except that it fires while the 'intro' div is still in view. The problem was in the return statement, I needed to be comparing tops/bottoms, not tops/tops, bottoms/bottoms. – huzzah Nov 10 '13 at 01:13