jQuery sticky div misbehaving - javascript

I'm using a bit of code to keep a sidebar element in view (and within the bounds of its parent) while scrolling and am having a bit of a problem. I have multiple articles on a page (approximately 10), each with it's own sidebar. The markup looks like this:
<article>
<section class="project-details entry-content">
<header>
...
</header>
</section>
<section class="offset-by-four twelve columns">
...
</section>
</article>
And the CSS:
article {
padding-top: 2em;
position: relative; }
article .project-details {
margin: 0 10px;
position: absolute;
width: 220px; }
... and finally, the Javascript:
$.fn.persistent = function(options) {
var opts = $.extend({
duration: 0,
lockBottom: true
},
options),
elements = [];
this.each(function() {
var parentPaddingTop = parseInt($(this).parent().css('paddingTop'));
$(this).data({
'parentPaddingTop': parentPaddingTop,
'startOffset': $(this).parent().offset().top
}).css({
position: 'absolute'
});
if (opts.lockBottom) {
var bottomPos = $(this).parent().height() - $(this).height() + parentPaddingTop;
if (bottomPos < 0) {
bottomPos = 0;
}
$(this).data('bottomPos', bottomPos);
}
elements.push($(this));
});
$(window).scroll(function() {
var pastStartOffset = $(document).scrollTop() > opts.startOffset;
$.each(elements,
function() {
var parentPaddingTop = $(this).data('parentPaddingTop'),
startOffset = $(this).data('startOffset'),
bottomPos = $(this).data('bottomPos');
$(this).stop();
var objFartherThanTopPos = $(this).offset().top > startOffset,
objBiggerThanWindow = $(this).outerHeight() < $(window).height();
if ((pastStartOffset || objFartherThanTopPos) && objBiggerThanWindow) {
var newpos = ($(document).scrollTop() - startOffset + parentPaddingTop);
if (newpos > bottomPos) {
newpos = bottomPos;
}
if ($(document).scrollTop() < startOffset) {
newpos = parentPaddingTop;
}
$(this).animate({
top: newpos
}, opts.duration);
}
}
);
});
};
It's the .project-details DIV that should remain sticky, but for some reason only the first one on the page works and the rest do nothing. Occasionally the second will start to work while scrolling down the page and then will fail about halfway through.
Can anyone see any glaring flaws with this code that might cause such behavior?

check the following code and make sure you understand that n is each element, using this instead a each function does not refer to the current element if that makes sense.
this.each(function(i,n) {
var parentPaddingTop = parseInt($(n).parent().css('paddingTop'));
$(n).data({
'parentPaddingTop': parentPaddingTop,
'startOffset': $(n).parent().offset().top
}).css({
position: 'absolute'
});
if (opts.lockBottom) {
var bottomPos = $(n).parent().height() - $(n).height() + parentPaddingTop;
if (bottomPos < 0) {
bottomPos = 0;
}
$(n).data('bottomPos', bottomPos);
}
elements.push($(n));
});

Related

Scroll to reveal elements one by one

I'd like to have elements in an array be consecutively revealed as the user scrolls. I found some code from here which sort of does what I want, and modified it like this:
var unit = document.querySelectorAll("span");
var i = 0;
var currentID = 0;
var slideCount = unit.length;
document.addEventListener("scroll", (e) => {
let scrolled =
document.documentElement.scrollTop /
(document.documentElement.scrollHeight -
document.documentElement.clientHeight);
unit.forEach(function (l, i) {
if (i / unit.length < scrolled) {
l.style.setProperty("--percentage", 1);
} else {
l.style.setProperty("--percentage", 0);
}
});
});
:root {
--percentage: 0;
}
#reveal span {
opacity: var(--percentage);
}
body {
height: 2000px;
}
#reveal {
position: fixed;
top: 0;
left: 0;
}
<div id="reveal">
<span>Scrolling</span>
<span>should</span>
<span>reveal</span>
<span>elements</span>
<span>one</span>
<span>by</span>
<span>one</span>
</div>
I'm wondering how I can rework this code so it doesn't rely on the height of the body in order to operate. I'd like to eliminate all scrollbars (which is proving difficult on iOS).

How to exclude multiple scrolls events for section scroll using jQuery

I'm facing problem is that even when I scroll one time, it gets scrolled multiple times automatically.
Here's my JSFiddle.
So, what I want is that only one section should be scrolled when I scroll one time. When I scroll down 1 time, next section should be seen. Similarly, when I scroll up 1 time, previous section should be seen.
I tried getting help from similar based question but I didn't get one. Thanks for the help in advance.
$(function(){
var lastScrollTop = 0, timer;
$(window).scroll(function(event){
clearTimeout(timer);
var windowH, scrollTop, currentSec = 0, scrollRatio, secOffset, secOffsetTop;
scrollTop = $(this).scrollTop();
windowH = $(window).outerHeight();
if (scrollTop == 0) {
currentSec = 1;
} else {
scrollRatio = scrollTop/windowH;
scrollRatio = Math.round(scrollRatio);
currentSec = scrollRatio + 1;
}
secOffset = $("#sec-"+currentSec).offset();
secOffsetTop = secOffset.top;
console.log("currentSec: "+currentSec);
//Stackoverflow Code
timer = setTimeout(function() {
if (scrollTop > lastScrollTop){
// downscroll code
console.log("DOWN DOWN DOWN!");
//$("#sec-" + currentSec).next("section").animate({scrollTop: 0}, 500);
var targetOffset = $("#sec-" + currentSec).next("section").offset();
$('html,body').animate({scrollTop: targetOffset.top}, 1250);
} else {
// upscroll code
console.log("DOWN DOWN UP!");
//$("#sec-" + currentSec).prev("section").animate({scrollTop: 0}, 500);
var targetOffset = $("#sec-" + currentSec).prev("section").offset();
$('html,body').animate({scrollTop: targetOffset.top});
}
lastScrollTop = scrollTop;
//Stackoverflow Code ENDS
}, 1250);
});
});
* {
box-sizing: border-box;
}
body {
margin: 0;
}
section {
height: 100vh;
color: #fff;
font-size: 60px;
padding: 15px;
}
#sec-1 {
background-color: #0ebeff;
}
#sec-2 {
background-color: #47cf73;
}
#sec-3 {
background-color: #fcd000;
}
#sec-4 {
background-color: #b9f;
}
#sec-5 {
background-color: #ff3c41;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="sec-scroll" id="sec-1">Section 1 </section>
<section class="sec-scroll" id="sec-2">Section 2 </section>
<section class="sec-scroll" id="sec-3">Section 3 </section>
<section class="sec-scroll" id="sec-4">Section 4 </section>
<section class="sec-scroll" id="sec-5">Section 5 </section>

Resizable sticky footer overlaps content - fix

In my layout I have created the following jsfiddle-hosted resizable sticky footer. However, on the resize it overlaps the content. Is there anyway to make it responsive on all browsers?
http://jsfiddle.net/9aLc0mg2/
$(function () {
$('.footer').resizable({
handles: 'n, s'
}).bind('resize', function(){
$(this).css("top", "auto");
});
});
<div class="footer">
<p> footer content here </p>
</div>
CSS:
.footer {
color: #ffffff;
position: fixed !important;
bottom: 0;
width: 100%;
/* Set the fixed height of the footer here */
z-index: 1000;
height: 60px;
background-color: #333333;
}
Does it need to be resizable back down ? Triedd the disable method but it does not work for some reason. Got it to stop at the content above it though. Is this any good ?
JS FIDDLE
$(function () {
var topheight = $('#top').height();
var topoffset = $("#top").offset();
var topbottom = topoffset.top + topheight;
$('.footer').resizable({
handles: 'n, s'
}).bind('resize', function(){
$(this).css("top","auto");
var footeroffset = $(this).offset();
var footerheight = $(this).height();
var footerBottom= footeroffset.top + footerheight;
$("#res").html(topbottom+" "+footeroffset.top);
if(topbottom + 50 >= footeroffset.top){
$('#res').html("should disable");
$('.footer').resizable("destroy");
}
});
});
I was able after digging more in research to solve it by adding the following function
var bumpIt = function() {
$('body').css('margin-bottom', $('.footer').height());
},
didResize = false;
bumpIt();
$(window).resize(function() {
didResize = true;
});
setInterval(function() {
if(didResize) {
didResize = false;
bumpIt();
}
}, 250);
http://jsfiddle.net/v71tsx97/
Also could be done this way: http://jsfiddle.net/mnuxohoj/
But still any other methods with better performance are welcome.

Make script start at the top of a specific div

So I basically want the script to start at the top of "mini" div but can't get it to work right.
#mini {
width: 100%;
padding-top: 300px;}
var tTop = $("#mini").outerHeight(true);
Full script:
$(window).scroll(checkY);
function checkY() {
//save this value so we dont have to call the function everytime
var top = $(window).scrollTop();
$(".title").each(function () {
var target = $(this).closest(".content");
var tTop = $("#mini").outerHeight(true);
var tBottom = target.offset().top + target.outerHeight();
if (top >= tTop && top <= tBottom) {
console.log("Show");
$(this).show();
} else {
console.log("Hide");
$(this).hide();
}
});
}
checkY();
Why not setting the mini style to
position:relative;
and the inner div to
position: absolute;
top:0

Javascript Menu Jumping from bottom to top instead of Scrolling

I am trying to make a menu that sticks to the bottom of the page and then to the top after scrolling. The only problem is that instead of scrolling with the page, the menu stays in the same place and then jumps to the top right at the end.
I am running stellar.js on the site also and I wondered if this was conflicting but I removed the calling javascript and the problem persisted so I put it back.
The site URL is www.percolatedpropaganda.co.uk
I am stumped and any help would be much appreciated!
Javascript
$(document).ready(function() {
var windowH = $(window).height();
var stickToBot = windowH - $('#menu').outerHeight(true);
$('#menu').css({'top': stickToBot + 'px'});
$(window).scroll(function() {
var scrollVal = $(this).scrollTop();
if ( scrollVal > stickToBot ) {
$('#menu').css({'position':'fixed','top' :'0px'});
} else {
$('#menu').css({'position':'absolute','top': stickToBot +'px'});
}
});
});
CSS
#menu {
font-size: 85%;
position: relative;
float: left;
}
Why don't you try this:
Javascript:
$(document).ready(function() {
$(window).scroll(function() {
var scrollVal = $(this).scrollTop();
if ( scrollVal > 0 ) {
$('#menu').css({bottom: '', top :'0px'});
} else {
$('#menu').css({top: '', bottom: '0px'});
}
});
});
CSS:
#menu {
position: fixed;
bottom: 0;
}
Check it out: Example
UPDATE:
If you want the movement to be animated use this instead:
Javascript:
$(document).ready(function() {
var menu = $('#menu');
var windowH = $(window).height();
var stickToBot = windowH - menu.outerHeight(true);
menu.css('top', stickToBot + 'px');
$(window).scroll(function() {
var scrollVal = $(this).scrollTop();
if ( scrollVal > 0 ) {
menu.stop().animate({top :'0px'});
} else {
menu.stop().animate({top: stickToBot + 'px'});
}
});
});
CSS:
#menu {
position: fixed;
}
Have a look: Example
UPDATE 2:
If you want it like cwtchcamping.co.uk... have a look at this:
Javascript:
$(document).ready(function() {
var menu = $('#menu');
var windowH = $(window).height();
var stickToBot = windowH - menu.outerHeight(true);
menu.css('top', stickToBot + 'px');
$(window).scroll(function() {
var scrollVal = $(this).scrollTop();
if (scrollVal > stickToBot) {
menu.css({top: '0px', position: 'fixed'});
}
else {
menu.css({top: stickToBot + 'px', position: 'absolute'});
}
});
});
CSS:
#menu {
position: absolute;
}
Example: JSFiddle

Categories