Scroll Javascript functions for different parent divs - javascript

I have a simple javascript scroll function that fixes my sidebar navigation and works fine on it's own, but I need to adjust it so different page types have different scroll events. Example: pages with banners need to have the fixed sidebar at a different scroll point that pages without a sidebar.
The indicator of a different page will be that the sidebar for a page without a banner will have a parent div that a page with a banner will not have. I am using a wordpress theme so my customization on this is limited.
Below is my example HTML and JS, but you can also see it at : http://jsfiddle.net/61L4ac2j/
HTML:
<div id="mk-page-id-1" class="theme-page-wrapper mk-main-wrapper">
<aside id="mk-sidebar" class="mk-builtin test">
<div class="sidebar-wrapper" style="min-height:600px;">
Page without banner example
</div>
</aside>
</div>
<div id="mk-page-id-2" class="theme-page-wrapper">
</div>
<div class="theme-page-wrapper">
<aside id="mk-sidebar" class="mk-builtin">
<div class="sidebar-wrapper" style="min-height:600px;">
Page with banner example
</div>
</aside>
</div>
JS:
$(function() {
var div = $(".sidebar-wrapper");
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (($("sidebar-wrapper").parent().parent("mk-main-wrapper")) & (scroll > 147)) {
div.css( "background", "yellow" );
} else if (scroll > 263) {
div.css( "background", "green" );
} else {
div.css( "background", "blue" );
}
});
});
For simplification purposes, I used background color, but my actual JS will use "addclass". See JS below:
$(function() {
var div = $(".sidebar-wrapper");
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if ($("sidebar-wrapper").parent().parent("mk-main-wrapper") & scroll > 147) {
div.addClass("fixed-product-nav");
} else if (scroll > 263) {
div.addClass("fixed-product-nav");
} else {
div.removeClass("fixed-product-nav");
}
});
});
The issue is I cannot get the first IF Statement true, which you can see at the JSFiddle. It looks like something with the parent elements.
I feel like I'm close and just missing something.
Thanks!

jQuery objects will always be truthy. You need to check the length to see if it is greater than zero.
You also do not have a class selector, it is missing the .
Also & is not correct, it needs to be &&
$("sidebar-wrapper").parent().parent("mk-main-wrapper") & scroll > 147
to
$(".sidebar-wrapper").closest(".mk-main-wrapper").length && scroll > 147

Related

Text effect not working properly if i add more div on page scroll

I have taken a reference of the below site and i want to add text effects ie opacity gets fade on page scroll. The above code is working properly if i use the below reference as it is but if i add many div then it gets faded early not reaching the required div
http://jsfiddle.net/HsRpT/134/
Here is what i have done and the text fade effects goes early without reaching the actual div. Is there any other way of solving this problem?
<div>
fsdfdfsdfffffffffff<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>><br><br><br>
</div>
<div class="block">
<h2>Fade this in / out as scroll down</h2>
</div>
<div class="content">
<div class="headerbar">
</div>
</div>
Try
$(window).scroll(function() {
var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
if (scrollTop > 200) {
$('.block').stop(true, true).fadeOut();
}
else {
$('.block').stop(true, true).fadeIn('fast');
}
});
Fiddle
current_div="div1";
$(window).scroll(function() {
current_div = scroll_content();
console.log(current_div);
if(current_div=="last"){
don't fade out
}
});
function scroll_content(){
var winTop = $(this).scrollTop();
var $divs = $('section');
var top = $.grep($divs, function(item) {
return $(item).position().top <= winTop;
});
var cur=top[top.length - 1];
return $(cur).attr('id');
}
You can get the the id of the div which is going out of screen while scrolling. So you can do what ever you want to do with the divs after getting the id .
It worked for me.
Let me know if you any other query.

jQuery - on window scroll run a function without any delay

I have an issue with a jquery function. You can see a working demo here - http://dev.sreejesh.in/menuissue/ . As you can see when the user scrolls down to the page, I have written a jQuery function(which will triger on scroll) to check scroll pixel. When the browser scrolls to a certain pixel(height of the sidemenu block), the Menu block will stay fixed & rest of the content scrolls as normal.
The functionality is working now, however the problem is menublocks makes a jumps when this function runs. I think this is because of the delay in running the function. Hope you guys have any nice trick to fix this.
I used an if/else function to check the scroll pixel, so when the scrolled pixel is greater than menublock height it will add a class "fixed" .
I use the following code.
HTML
<div id="globalwrapper">
<div id="menubar">
---- Menu List items-----
</div>
<div id="mainblock">
----Main content area----
</div>
</div>
jQuery
$(document).ready(function(){
$(window).scroll(function() {
adjustScroll();
});
});
function adjustScroll(){
var windowHeight = $(window).height();
var menublockHeight = $('#menubar').height();
var scrollValue = $(document).scrollTop();
var posValue = menublockHeight - windowHeight;
var menuStatus = $('#menubar').css('left');
$('#menubar').css('minHeight', windowHeight);
$('#menubar').css('height', menublockHeight);
console.log(menuStatus);
$(document).scroll(function() {
if(menuStatus == '0px') {
if(scrollValue > posValue){
$('#menubar').addClass('fixed');
$('#menubar').css('marginTop', -posValue);
}else {
$('#menubar').removeClass('fixed');
$('#menubar').css('marginTop', '0px');
}
}
});
}
I think only CSS can solve this issue, add this style:
#menubar{
position: fixed;
}
just test on Google Chrome,you can have a try.

How do I make a div shift above or below another div based on the scroll bar?

Here's my situation:
I have a bunch of rows. In each row is a button that when clicked displays a set of options. Depending on where the row is in the page, the settings need to open above or below the button. If the button is at the top of the page, the settings would display beneath the button. If the button is at the bottom of the page, it should open above.
If the user picks something at the bottom of the page, but then scrolls so it's towards the top, I need the settings to shift under the button as opposed to on top. What's the best way to do this? I'm not actually sure of ANY way to do this, so any advice would be appreciated.
http://jsfiddle.net/573zJ/
Test the position of the element relative to the viewport midpoint, and move it to the first or last position relative to its container, like so:
<div class="container">
<div class="element-set">
<div class="normal">content</div>
<div class="flipper">flipper</div>
</div>
... random number of .element-set
<div class="element-set">
<div class="normal">content</div>
<div class="flipper">flipper</div>
</div>
</div>
and
$(window).scroll(function () {
flippers();
});
function flippers() {
var midpoint = $(window).height() / 2;
$('.flipper').each( function () {
var $flipper = $(this);
var $parent = $flipper.parent();
var top = $parent.position().top - $(window).scrollTop();
if ( top > midpoint ) {
$flipper.prependTo( $parent );
} else {
$flipper.appendTo( $parent );
}
});
}

Javascript - Efficiency for scroll event, run code only once

These if statements are always making me dizzy. If have a page with a header, and a hidden header above that in the markup.
<div id="headerfloat" style="display:none;">
<p>Floated header</p>
</div>
<div id="header">
<p>Header</p>
</div>
The idea is that whenever the page is scrolled down more than 225px, the #headerfloat should appear, and dissapear when topScroll is less than 225px. And I managed to get this working with javascript and jQuery, but when I test it on iPhone, it's very sluggish. And I'm pretty sure it's because the code is run at each scroll event. And even if #headerfloat is visible, the code still executes. Even though it doesn't have to at that point.
So, I need to make sure the code only run once, when it's needed. My first thought was to add and remove classes like .open and .closed to #headerfloat. And run if statements on those during the scroll event. But is that the most efficient way of doing it?
My so far, ugly snippet:
jQuery(window).scroll(function () {
var headerfloat = $("#header_float");
var top = jQuery(window).scrollTop();
if (top > 225) // height of float header
{
if (!$(headerfloat).hasClass("closed")) {
$(headerfloat).addClass("boxshadow", "", 100, "easeInOutQuad").slideDown().addClass("open").removeClass("closed");
}
} else {
$(headerfloat).removeClass("boxshadow", "", 100, "easeInOutQuad").removeClass("closed").slideUp();
}
});
Edit: So after laconbass's awesome response, this is the code I ended up with:
var mainHeader = $('#header')
, top_limit = mainHeader.outerHeight()
, $window = $(window)
;
var header_float = $('#header_float')
bindEvent();
function bindEvent() {
$window.scroll( scrollEvent );
}
function scrollEvent() {
var top = $window.scrollTop();
// avoid any logic if nothing must be done
if ( top < top_limit && !header_float.is(':visible')
|| top > top_limit && header_float.is(':visible')
) return;
// unbind the scroll event to avoid its execution
// until slide animation is complete
$window.unbind( 'scroll' );
// show/hide the header
if ( top > top_limit ) {
header_float.slideDown( 400, bindEvent );
} else {
header_float.slideUp( 400, bindEvent );
}
};
The snippet you started from seems a bit ugly.
I've made one on jsfiddle for your pleasure and reference
I've assumed the following:
you want a fixed positioned header when the page scrolls down (aka fixed header).
fixed headed is a clone of the page main header, with the class fixed.
fixed header is shown when the page scrolls down more than the header height.
fixed header is hidden when the page scrolls up enough to show the main page header.
Performance tips:
cache the jQuery objects to avoid making a new query each time the event handler is executed.
unbind the event handler before the show/hide animations, rebind it after.
on the event handler, return as soon as posible to avoid unnecesary logic. Remember while JavaScript is executed the browser render process is blocked.
var mainHeader = $('header')
, header = mainHeader.clone().addClass('fixed').appendTo('body')
, top_limit = header.outerHeight()
;
bindEvents();
function bindEvents() {
$(window).scroll( scrollEvent );
}
function scrollEvent() {
var top = $(window).scrollTop();
// avoid any logic if nothing must be done
if ( top < top_limit && !header.is(':visible')
|| top > top_limit && header.is(':visible')
) return;
// unbind the scroll event to avoid its execution
// until slide animation is complete
$(window).unbind( 'scroll' );
// show/hide the header
if ( top > top_limit ) {
header.slideDown( 400, bindEvents );
} else {
header.slideUp( 400, bindEvents );
}
};
<header>
<h1>Awesome header</h1>
</header>
<div>
<!-- the page content -->
</div>
/* the real code needed */
header.fixed {
display: none;
position: fixed;
top: 0;
}
two way:
1,on scroll,and if you have done your want, remove the scroll event.
2,var a variable,default is false, on scroll, if the variable is false,to do you want,and set the variable to true; if the variable is true already, do nothing(or others you want)

Push footer to bottom when page is not full

I'm developing a mobile web app. This is the main structure from top to bottom: header div, menu div, content div, footer div. The header, menu and footer are constant and pages are loaded into the content div using ajax.
Some of the pages have lots of content and they fill out the page so scroll is needed. Some of the pages have only one or two lines of content so they leave a big empty part (Not necessarily different pages - one page for example shows a list of orders, you can have no orders and you can have hundreds...).
This is what i want to achieve: If the page is not full with content, the footer will be in the bottom of the page. If the page is full and scroll is needed, the footer will be immediately after the content (so you scroll down the page and in the end you reach the footer).
The sticky footer solutions are not good for me because i don't want the footer to stick to the bottom always, only when the page is not full of content.
Is there anyway to achieve that? Thanks.
Then you have to use javascript for that - calculate the height of the content - substract it from the window height and set the margin-top of the footer from that distance:
jsfiddle
jsfiddle show
HTML
<div id="header" class="header">Header</div>
<div id="content" class="content">Content</div>
<div id="footer" class="footer">Footer</div>
JS (This example uses jQuery, it should be included before this script.)
$('#footer').css('margin-top',
$(document).height()
- ( $('#header').height() + $('#content').height() )
- $('#footer').height()
);
You can put an onresize window that call this function on any resize of the window.
[edit blag :]
Here is the onResize method (but with a min-height and not a margin-top)
Check the JSFiddle
// function to set the height on fly
function autoHeight() {
$('#content').css('min-height', 0);
$('#content').css('min-height', (
$(document).height()
- $('#header').height()
- $('#footer').height()
));
}
// onDocumentReady function bind
$(document).ready(function() {
autoHeight();
});
// onResize bind of the function
$(window).resize(function() {
autoHeight();
});
Borders, padding and margin
If you want to have borders and padding included in the calculation you can use outerHeight() instead of height(). Alternatively outerHeight(true) also includes margins.
A CSS Sticky footer should solve your problem.
Here's an example
That is super easy to setup and use. It will force the footer down the page with the content, and if the content isn't big enough to fill the page it will stick to the bottom.
function autoHeight() {
var h = $(document).height() - $('body').height();
if (h > 0) {
$('#footer').css({
marginTop: h
});
}
}
$(window).on('load', autoHeight);
The following solution works for me, based on the answer from Александр Михайлов. It finds the bottom of the footer and determines if it is less than the document height and uses top margin on the footer to make up the shortfall. This solution might give issues if your content is being resized on the go.
$(function () {
updateFooterPosition();
});
$(window).resize(function () {
updateFooterPosition();
});
function updateFooterPosition() {
var bottomOfFooter = $('footer').offset().top + $('footer').outerHeight(true);
var heightShortage = $(document).height() - bottomOfFooter;
if (heightShortage < 0) heightShortage = 0;
$('footer').css('margin-top', heightShortage);
}
Here's the solution i came to on my project
function autoHeight() {
if ( document.body.clientHeight < window.innerHeight ) {
document.querySelector('#footer').style.position = 'absolute';
document.querySelector('#footer').style.bottom = '0';
}
}
document.addEventListener("DOMContentLoaded", function() {
autoHeight();
});
This solution worked for me. I think this is perfect if you have more than only a #header and #footer. It just push the content down with a padding-bottom if body is smaller than the viewport.
function autoHeight() {
var bodyHeight = $("body").height();
var vwptHeight = $(window).height();
var gap = vwptHeight - bodyHeight;
if (vwptHeight > bodyHeight) {
$("#content").css( "padding-bottom" , gap );
} else {
$("#content").css( "padding-bottom" , "0" );
}
}
$(document).ready(function() {
autoHeight();
});
$(window).resize(function() {
autoHeight();
});

Categories

Resources