I'm trying to migrate some jQuery code to pure JavaScript. The current jQuery code toggles a class named is-page-scrolled
in the body
element when the user scrolls down to a specific offset set in a data
attribute in the body element named data-page-scrolled-offset
. If the user scrolls up again to the top of the page, the class is toggled off.
My working jQuery code:
var scrolled_page_offset = parseInt( $( 'body' ).data( 'pageScrolledOffset' ) );
var scrolled_page = function() {
var scroll_top = window.pageYOffset;
$( 'body' ).toggleClass( 'is-page-scrolled', scroll_top > scrolled_page_offset );
};
$( window ).on( 'scroll', function() {
scrolled_page();
} );
scrolled_page();
My non-working pure JavaScript code:
var scrolled_page_offset = parseInt( document.body.dataset.pageScrolledOffset );
var scrolled_page = function() {
var scroll_top = window.pageYOffset;
if ( scroll_top > scrolled_page_offset ) {
document.body.classList.toggle( 'is-page-scrolled' );
}
};
window.addEventListener( 'scroll', function() {
scrolled_page();
} );
scrolled_page();
My proposed pure Javascript code is not working as expected because it toggles the class on and off intermittently when the user scrolls down in the page.
What am I doing wrong?
CodePudding user response:
Explanation of the current problem, copied from my comment:
jQuery's
toggleClass()
is setting the class on/off based on thescroll_top > scrolled_page_offset
. Yourif
toggle()
is inverting the on/off state of the class every timescroll_top > scrolled_page_offset
istrue
.
If we compare "does the class exist" to "do we want the class to exist", we avoid accidentally inverting the state of the class.
If this example I've added:
const isEnabled = document.body.classList.contains(className)
const shouldBeEnabled = scroll_top > scrolled_page_offset
if (shouldBeEnabled !== isEnabled) { ... }
Which will only run the if
when we expect the class to change.
(In this demo, the background turns green to show when the class is added)
// Set up the demo, ignore this
document.body.dataset.pageScrolledOffset = 200;
//
const className = 'is-page-scrolled'
const scrolled_page_offset = parseInt(document.body.dataset.pageScrolledOffset);
const scrolled_page = function() {
const scroll_top = window.pageYOffset;
const isEnabled = document.body.classList.contains(className)
const shouldBeEnabled = scroll_top > scrolled_page_offset
if (shouldBeEnabled !== isEnabled) {
document.body.classList.toggle(className);
}
};
window.addEventListener('scroll', function() {
scrolled_page();
});
scrolled_page();
#scrollable {
height: 10000px;
}
.is-page-scrolled {
background: #060;
}
<div id="scrollable">
Scroll down
</div>