Make element stick to top when scrolling - javascript

I've written a function to make a div element stick to top when scrolling.
it works when it's written like this('#sticky-anchor-for-social' is to detect moving distance of the element, '#social-media' is the element sticks):
function sticky_socialmedia() {
var window_top = $(window).scrollTop();
var social_top = $('#sticky-anchor-for-social').offset().top - 88;
if (window_top >= social_top) {
$('#social-media').addClass('stick-social');
} else {
$('#social-media').removeClass('stick-social');
}
}
$(window).scroll(sticky_socialmedia);
sticky_socialmedia();
but it doesn't work when I write it like this:
function stickyWhenScroll(anchor, sticky) {
var window_top = $(window).scrollTop();
var filter_top = $(anchor).offset().top - 88;
if (window_top >= filter_top) {
$(sticky).addClass('stick-filter');
} else {
$(sticky).removeClass('stick-filter');
}
}
$(window).scroll(stickyWhenScroll);
stickyWhenScroll('#sticky-anchor-for-social','#social-media');
what could possibly go wrong?
many thanks!

You need to send your parameters to your function when adding the event, you can do that with bind:
$(window).bind('scroll', {
anchor: '#sticky-anchor-for-social',
sticky: '#social-media'
}, stickyWhenScroll).trigger('scroll');
By passing trigger('scroll') you can trigger the function straight away.
And in your function you can retrieve them by accesing the event.data:
function stickyWhenScroll(event) {
var data = event.data;
var anchor = data.anchor;
var sticky = data.sticky;
...
}
Fiddle

Because in your 2nd snippet the scroll event handler hasn't received any params. You could either pass params both times (load and scroll) or declare those as global variables and use them within the function.
(function stickyWhenScroll(anchor, sticky) {
var window_top = $(window).scrollTop();
var filter_top = $(anchor).offset().top - 88;
if (window_top >= filter_top) {
$(sticky).addClass('stick-filter');
} else {
$(sticky).removeClass('stick-filter');
}
}('#sticky-anchor-for-social', '#social-media'));
$(window).scroll(function() {
stickyWhenScroll('#sticky-anchor-for-social','#social-media');
});

Related

How can I have a function method in an if condition with JavaScript code?

I want to give condition method in my JavaScript code. This code does not work in Internet Explorer 10 version. When I paste this code in JavaScript validator, this message is shown:
Function declarations should not be placed in blocks. Use a function expression or move the statement to the top of the outer function.
How can I have a function here?
if(jQuery("header").attr("id") == "header-style-two")
{
function sticky_relocate() {
var window_top = jQuery(window).scrollTop();
var div_top = jQuery('#sticky-anchor').offset().top;
if (window_top > div_top) {
jQuery('.mainmenu-area').removeClass('light-menu');
//This is for when div in top
} else {
jQuery('.mainmenu-area').addClass('light-menu');
//This is for when div in not top
}
}
jQuery(function () {
jQuery(window).scroll(sticky_relocate);
sticky_relocate();
});
}
You can't have named function in an if block (it is not valid by the spec and hoisting would make it rather confusing anyway, but some JavaScript engines may try to compensate for bad code, which is why it may work in some browsers), but you can assign functions to variables in an if block.
Rather than:
function sticky_relocate() {
You can do this:
var sticky_relocate = function() {
So something like this will do the trick:
if(jQuery("header").attr("id") == "header-style-two")
{
var sticky_relocate = function() {
var window_top = jQuery(window).scrollTop();
var div_top = jQuery('#sticky-anchor').offset().top;
if (window_top > div_top) {
jQuery('.mainmenu-area').removeClass('light-menu');
//This is for when div in top
} else {
jQuery('.mainmenu-area').addClass('light-menu');
//This is for when div in not top
}
}
jQuery(function () {
jQuery(window).scroll(sticky_relocate);
sticky_relocate();
});
}
JSHint is giving you a warning, which means, "we think this is not the best idea, but we'll allow you to do it."
You can change your code in a couple of ways.
Change the function declaration to a function expression:
if(jQuery("header").attr("id") == "header-style-two") {
var sticky_relocate = function() {
var window_top = jQuery(window).scrollTop();
var div_top = jQuery('#sticky-anchor').offset().top;
if (window_top > div_top) {
jQuery('.mainmenu-area').removeClass('light-menu');
//This is for when div in top
} else {
jQuery('.mainmenu-area').addClass('light-menu');
//This is for when div in not top
}
}
jQuery(function () {
jQuery(window).scroll(sticky_relocate);
sticky_relocate();
});
}
OR move the function definition out of the if block.
if(jQuery("header").attr("id") == "header-style-two") {
jQuery(function () {
jQuery(window).scroll(sticky_relocate);
sticky_relocate();
});
}
function sticky_relocate() {
var window_top = jQuery(window).scrollTop();
var div_top = jQuery('#sticky-anchor').offset().top;
if (window_top > div_top) {
jQuery('.mainmenu-area').removeClass('light-menu');
//This is for when div in top
} else {
jQuery('.mainmenu-area').addClass('light-menu');
//This is for when div in not top
}
}
You can't have function declaration under if condition. You can put it outside and call it based on the condition.
var isHeaderStyleTwo = (jQuery("header").attr("id") == "header-style-two");
function sticky_relocate() {
var window_top = jQuery(window).scrollTop();
var div_top = jQuery('#sticky-anchor').offset().top;
if (window_top > div_top) {
jQuery('.mainmenu-area').removeClass('light-menu');
//This is for when div in top
} else {
jQuery('.mainmenu-area').addClass('light-menu');
//This is for when div in not top
}
}
jQuery(function () {
if (isHeaderStyleTwo) {
jQuery(window).scroll(sticky_relocate);
sticky_relocate();
}

launch function once if class is added on visible Element [duplicate]

This question already has an answer here:
jQuery trigger when 2/3s of div are in viewport
(1 answer)
Closed 6 years ago.
I would like to check if a class is added on an Element during the scroll and launch another function, just once, until the class is added to the next element.
here my first function :
function onScreen() {
$('article').each(function() {
var thisTop = $(this).offset().top - $(window).scrollTop();
var middleScreen = $(window).height() / 2;
if (thisTop < middleScreen && (thisTop + $(this).height()) > middleScreen) {
$(this).addClass('visible');
} else {
$(this).removeClass('visible');
}
});
}
// launch
$(window).on('load scroll', onScreen);
My seconde function : I would like to launch just once if the visible class is added to another article.
function textChange() {
var v = $('article.visible');
var el = $('.el', v);
var text = $(el).html();
$('.titre').html(text);
}
$(window).on('load scroll', textChange);
note : It's important to me to keep two separate function.
My issue is the scroll function get call textChange() each pixel I scroll on the page. Strangly, the onScreen() function add the visible class just once until the next article gonna be visible.
Thanks for yours suggestions.
Introduce a global variable that tells you if the function has been executed or not:
var textChanged = false;
In your textChange() function set it to true when the function was called the first time:
function textChange() {
if(!textChanged){
textChanged = true;
var v = $('article.visible');
var el = $('.el', v);
var text = $(el).html();
$('.titre').html(text);
}
}
EDIT: Alternatively you can do the check before the function gets called:
if (thisTop < middleScreen && (thisTop + $(this).height()) > middleScreen) {
$(this).addClass('visible');
if(!textChanged){
textChange();
}
} else {
$(this).removeClass('visible');
}

Hide Div on Scroll with JQuery

I'm sure this is a trivial problem but I cannot seem to figure it out. I'm trying to fade a side bar in and out, and because I have a few of them in my website, I need to give them individual IDs for Javascript.
This code works
$(window).on("scroll", function() {
var scrollPos = $(window).scrollTop() - 100 ;
if (scrollPos < 100) {
$("#menu").fadeOut();
} else {
$("#menu").fadeIn();
}
});
This doesn't
$(window).on("scroll", function() {
var menu = document.getElementById("menu");
var scrollPos = $(window).scrollTop() - 100 ;
if (scrollPos < 100) {
menu.fadeOut();
} else {
menu.fadeIn();
}
});
In the latter piece, all I'm trying to do is assign a variable.
Here's the fiddle: https://jsfiddle.net/gavinfriel/nhovvj6q/1/
Your help would be appreciated.
You have to wrap it in a jQuery call to make it a jQuery object. Otherwise it cannot find the fadeOut and fadeIn functions:
var menu = $("#menu");
or
var menu = $(document.getElementById("menu"));
You need to use jquery to convert menu to jQuery object.
So it will have the fade property
$(window).on("scroll", function() {
var menu = document.getElementById("menu");
var scrollPos = $(window).scrollTop() - 100 ;
if (scrollPos < 100) {
$(menu).fadeOut();
} else {
$(menu).fadeIn();
}
});
Because if you use menu.fadeOut() it will generate error because menudoesn't have fade property
Checkout this it will work.
$(window).on("scroll", function() {
var menu = $("#menu");
var scrollPos = $(window).scrollTop() - 100 ;
if (scrollPos < 100) {
menu.fadeOut();
} else {
menu.fadeIn();
}
});
As others have mentioned, you've declared a JavaScript variable but are trying to use it as a jQuery object.
I would personally go with PierreDuc's answer but if you refactor your code slightly you can carry on using the vanilla JS declared vaiable, but pass the variable slightly differently:
var test = document.getElementById("test");
$(test).hide();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="test">
TEST
</div>
In your 2nd code, this might look as follows:
$(window).on("scroll", function() {
var menu = document.getElementById("menu");
var scrollPos = $(window).scrollTop() - 100 ;
if (scrollPos < 100) {
$(menu).fadeOut();
} else {
$(menu).fadeIn();
}
});

Pop up text after scrolling certain distances is not working

I'm trying to get text to pop up at a fixed location at different y-scroll intervals however, I can't seem to chain the scripts correctly. It seems to skip the first action of displaying the first message.
Code: http://jsfiddle.net/k8bnd/
var startY = 1500;
var stopY = 2000;
$(window).scroll(function(){
checkY();
});
function checkY()
{
console.log($(window).scrollTop());
if($(window).scrollTop() > startY && $(window).scrollTop() <= stopY)
{
console.log("Show");
$('.titleTwo').show();
}
else
{
console.log("Hide");
$('.titleTwo').hide();
} }
checkY();
Your functions should have different names. Try
var startY1 = 900;
var stopY1 = 1800;
var startY2 = 1801;
var stopY2 = 2500;
$(window).scroll(function(){
checkY();
});
function checkY()
{
console.log($(window).scrollTop());
if($(window).scrollTop() > startY1 && $(window).scrollTop() <= stopY1)
{
console.log("Show");
$('.foxedDiv').show();
}
else
{
console.log("Hide");
$('.foxedDiv').hide();
}
if($(window).scrollTop() > startY2 && $(window).scrollTop() <= stopY2)
{
console.log("Show");
$('.foxedDivved').show();
}
else
{
console.log("Hide");
$('.foxedDivved').hide();
}
}
checkY();
Fixed Fiddle:
http://jsfiddle.net/k8bnd/1/
This is happening because you have overwritten the previous values/functions. To make this more dynamic you can add data-* attributes to each message element specifying which positions they are valid for. And then in the scroll event check each element's position data, if the window is within that range show it, otherwise hide it.
HTML
<!-- Changed the classes both elements had to foxedDiv
so that we can select them as a group and loop over them -->
<div class="foxedDiv" data-position="900,1800">
MESSAGE 1
</div>
<div class="foxedDiv" data-position="1801,2500">
MESSAGE 2
</div>
JS
//Note you do not need to make an anonymous
//function just to do the call for checkY
//just pass the function
$(window).scroll(checkY);
function checkY(){
//save this value so we dont have to call the function everytime
var top = $(window).scrollTop();
console.log(top);
$(".foxedDiv").each(function(){
var positionData = $(this).data("position").split(",");
if(top > positionData[0] && top <= positionData[1]){
console.log("Show");
$(this).show();
} else {
console.log("Hide");
$(this).hide();
}
});
}
checkY();
JSFiddle Demo

Get static value from variable (scroll function)

I have a "follow scroll" function, but I want it to turn off when it returns to a certain point. My code is as follows:
scrollSidebar: function(scroll) {
var elemPos = $('#bestvideos-2').offset().top,
scroll2 = scroll;
if(scroll2 >= elemPos) {
$('#bestvideos-2').animate({
'margin-top':(scroll - 315)+'px'
},0);
} else {
$('#bestvideos-2').css('margin-top','0');
}
}
$(window).scroll(function() {
var scrollHeight = $(window).scrollTop();
Scroll.scrollSidebar(scrollHeight);
})
The problem is - every time I get up, it goes way up, not following scroll. What I'm thinking is storing a variable elemPos somewhere and keep it static (now it's changing each time I scroll).
What can I do with this?
Pass the value to the scrollSidebar function - make sure that the var elemPos = $('#bestvideos-2').offset().top is executed on dom ready
scrollSidebar: function (elemPos, scroll) {
var scroll2 = scroll;
if (scroll2 >= elemPos) {
$('#bestvideos-2').animate({
'margin-top': (scroll - 315) + 'px'
}, 0);
} else {
$('#bestvideos-2').css('margin-top', '0');
}
}
var elemPos = $('#bestvideos-2').offset().top
$(window).scroll(function () {
var scrollHeight = $(window).scrollTop();
Scroll.scrollSidebar(elemPos, scrollHeight);
})

Categories