Return on scroll firefox - javascript

I've created a sticky sidebar function which works perfectly in chrome and safari but not in Firefox. From what I can tell it's not returning properly when it should be.
Consider a snippet of the code in question:
if (scrolling_down && bottom_offset <= bottom_padding) {
$item.css({
position: 'absolute',
top: 'auto',
bottom: bottom_padding
});
console.log(1);
return false;
console.log(2);
}
console.log(3);
The console in Chrome logs 3 until it hits the bottom of the page then logs 1 for the rest of the scroll.
In Firefox however, the console logs 3 until it hits the bottom then alternates between 3 and 1.
I'm pretty sure it should be ignoring 3 (because of the return false) once it's hit the bottom, like Chrome.
Full Javascript:
// Sticky Sidebars
stickyAsides: function() {
var $item = $('.js-sticky'),
$parent = $item.parent(),
last_scroll = 0,
scrolling_down = false;
function setStyles() {
$item.css({
width: $item.outerWidth()
});
}
function stick() {
var parent_rect = $parent.get(0).getBoundingClientRect(),
parent_top = parent_rect.top,
parent_bottom = parent_rect.bottom,
item_rect = $item.get(0).getBoundingClientRect(),
item_top = item_rect.top,
item_bottom = item_rect.bottom,
bottom_offset = parent_bottom - item_bottom,
bottom_padding = parseInt($parent.css('padding-bottom'));
scrolling_down = (last_scroll < w.scroll) ? true : false;
setStyles();
if (scrolling_down && bottom_offset <= bottom_padding) {
$item.css({
position: 'absolute',
top: 'auto',
bottom: bottom_padding
});
console.log(1);
return false;
console.log(2);
}
console.log(3);
if (item_top <= -10 || parent_top <= 0) {
$item.css({
position: 'fixed',
top: '0',
bottom: 'auto'
});
}
if (!scrolling_down && parent_top > 0) {
$item.css({
position: 'relative',
top: '0',
bottom: 'auto'
});
}
last_scroll = w.scroll;
}
$(window).on('scroll', function(){
w.scroll = $doc.scrollTop();
if (Modernizr.mq('(min-width: 1024px)') && Modernizr.flexbox) {
stick();
}
});
}, // End stickyAsides()
EDIT: Codepen Example: http://codepen.io/jhealey5/pen/JGLjPN - However this seems to work okay, so there is something else interfering on the page. I don't expect anyone to solve it but there might be some advice. I'm unable to link to the live page at this time I'm afraid.

Seems Firefox wasn't doing calculations correctly. Adding +20px to the bottom padding calculation seems to fix it.

Related

Div follow as you scroll on desktops screen and is fixe on mobile screen

I want a div follow as you scroll when you are on a screen wider than 991. On a screen size smaller i want the div fixe. And i want the javascript code refresh every time someone load or resize the page.
Here my code (it's not dry...).
My problem is when i resize the window (desktop screen -> mobile screen -> desktop screen...):
1 - on mobile screen i can't go at the bottom of the page
2 - on desktop screen i have a problem when i scroll the page
//when the page is load and the window resize detect if it's a smallscreen
var smallscreen = true;
$(window).on("resize load", function() {
if ($(window).width() > 991) {
smallscreen = false;
}
else {
smallscreen = true;
};
//if it's not a small screen activate the scrolling
if (smallscreen == false) {
$.fn.followTo = function ( pos ) {
var $this = this,
$window = $(window);
$window.scroll(function(e){
if ($window.scrollTop() > pos) {
$this.css({
position: 'absolute',
top: pos
});
}
else {
$this.css({
position: 'fixed',
top: 180
});
};
});
};
$('#checkout_validation').followTo(400);
}
else {
$.fn.followTo = function ( pos ) {
var $this = this,
$window = $(window);
$window.on("resize scroll load", function(e){
if ($window.scrollTop() > pos) {
$this.css({
position: 'initial',
width: '100%',
top: 0
});
}
else {
$this.css({
position: 'initial',
width: '100%',
top: 0
});
};
});
};
$('#checkout_validation').followTo(0);
};
});
Here's my working code. Thanks you #iMatoria for having dried it.
//when the page is load and the window resize detect if it's a smallscreen
var smallscreen = true;
$.fn.followTo = function(pos) {
var $this = this,
$window = $(window);
$window.on("resize scroll", function(e) {
function positionByScreen(positionForBiggerScreen, topOffsetForBiggerScreen) {
if (smallscreen == false) {
//alert('bigcreen scroll end');
$this.css({
position: positionForBiggerScreen,
top: topOffsetForBiggerScreen
});
} else {
//alert('smallscreen no scroll end ');
$this.css({
position: 'inherit',
top: 0
});
}
}
if ($window.scrollTop() > pos) {
positionByScreen("absolute", pos);
} else {
positionByScreen("fixed", 180);
};
});
};
$(window).on("resize load", function() {
smallscreen = !($(window).width() > 991);
//if it's not a small screen activate the scrolling
$('#checkout_validation').followTo(smallscreen ? 0 : 400);
//var d = document.getElementById("checkout_validation");
//d.className += " otherclass";
});

Offset Top Not Working In IOS

Here is the complete code http://jsfiddle.net/vinex08/uhm26em1/
jQuery(function ($) {
var distance = $('.c').offset().top,
$window = $(window);
$window.scroll(function () {
if ($window.scrollTop() >= distance) {
$(".b").css({
position: 'fixed',
top: '0'
});
} else {
$(".b").css({
position: 'inherit',
top: '10'
});
}
});
});`
It's working on Chrome and Firefox but when i checked it via iPad AIR and iPhone, the effect executes even before the 'class c' hits the top.
I hope this will help:
jQuery(function ($) {
var distance = $('.c').offset().top;
$(window).scroll(function () {
var wndwTop = $(this).scrollTop();
if (wndwTop >= distance) {
$(".b").css({
position: 'fixed',
top: '0'
});
} else {
$(".b").css({
position: 'inherit',
top: '10'
});
}
});
});
Here we have known fix for mobile Safari.
Firstly, detect browser; secondly, a little bit change behavior of the 'offset' function:
// mobile Safari reports wrong values on offset()
// http://dev.jquery.com/ticket/6446
if ( /webkit.*mobile/i.test(navigator.userAgent)) {
(function($) {
$.fn.offsetOld = $.fn.offset;
$.fn.offset = function() {
var result = this.offsetOld();
result.top -= window.scrollY;
result.left -= window.scrollX;
return result;
};
})(jQuery);
}
Place this code somewhere after jquery initialization, but before your offset computations.

make animation with scrollTop

animate = animate;
desanimate = undo animate;
Friends, I created a function that does an element animate or 'desanimate' depending on where the scroll of the body or a div is, it's working ok, how it works?
<li data-animation-time="[100, 800]" data-animation-position="right" class="list-item one"></li>
the first value of the data-animation-time array is the initial value, ie the animator function should be called when the scrollTop pass that value, the second value is the end, the 'desanimate' function should be called when the scrollTop pass that value.
Everything working as you can see here -> Codepen: http://codepen.io/celicoo/pen/ogKGEP (you need scroll to see the animation happens).
Now I want to determine which way the animation to happen and which way it should end, for that I changed this attr:
data-animation-position="right-to-left" instead of just right or left, and i add some ifs statements to the animation and 'desanimation' function:
Animate:
var animate = function(target, position) {
target.css('display', 'inline-block');
if (position === 'right-to-right') {
target.animate({
opacity: 1,
right: '0px'
}, 500);
}
else if (position === 'right-to-left') {
target.animate({
opacity: 1,
right: '0px'
}, 500);
}
else if (position === 'left-to-left') {
target.animate({
opacity: 1,
left: '0px'
}, 500);
}
else if (position === 'left-to-right') {
target.animate({
opacity: 1,
left: '0px'
}, 500);
}
};
'Desanimate':
var desanimate = function(target, position) {
if (position === 'right-to-right') {
target.animate({
opacity: 0,
right: '245px'
}, 500);
}
else if (position === 'right-to-left') {
target.animate({
opacity: 0,
left: '245px'
}, 500);
}
else if (position === 'left-to-left') {
target.animate({
opacity: 0,
left: '245px'
}, 500);
}
else if (position === 'left-to-right') {
target.animate({
opacity: 0,
right: '245px'
}, 500);
}
};
And is not working in the 'desanimate' way, something is not working good, and i really cant see what it is.
Could someone give me a hand here? What could be doing 'desanimate' not work when I inverted step values?
Example:
left-to-right
right-to-left
Codepen with old code working just with one side (ex: left or right);
Code pen with new code not working 100% with multiple sides (ex: left to left, left to right, right to right or right to left);
Updated the codepen link . Just have a look and let me know whether it matches the requirement.
+ function($) {
var animate = function(target, position) {
target.css('display', 'inline-block');
if (position === 'right-to-left' || position === 'right-to-right' ) {
target.css('right', '500px');
target.css('left','' );
target.animate({
opacity: 1,
right: '0px'
}, 500);
}
else if (position === 'left-to-right' || position=="left-to-left") {
target.css('left', '500px');
target.css('right', '');
target.animate({
opacity: 1,
left: '0px'
}, 500);
}
};
var disanimate = function(target, position) {
if (position === 'right-to-left' || position ==="left-to-left") {
target.css('left','' );
target.animate({
opacity: 0,
right: '245px'
}, 500);
}
else if (position === 'left-to-right' || position === "right-to-right") {
target.css('left','' );
target.animate({
opacity: 0,
left: '245px'
}, 500);
}
};
$(window).on('load', function() {
var target = $('[data-animation-time]');
var animationInitial = target.data('animation-time')[0];
var animationFinal = target.data('animation-time')[1];
var position = target.data('animation-position');
var shown = false;
$('.container').scroll(function() {
var scroll = $(this).scrollTop();
if (!shown && (animationInitial < scroll && animationFinal > scroll)) {
console.log("animate")
animate(target, position);
shown = true;
}
else if (shown && (animationFinal < scroll || animationInitial > scroll)) {
console.log("disanimate")
disanimate(target, position);
shown = false;
if (position.split("-")[0] == position.split("-")[2])
position = anti(position);
}
});
});
}(jQuery);
var anti = function (position){
if (position == "left-to-left")
return "right-to-right"
else
return "left-to-left"
}
Css :- it was right 500px. so intital position of card is fixed. i changed it to dynamic based on input and whenever you are adding right(css) you have to make sure left(css) is null because if you give both right and left it will get confused during animation
left-to-right & right-to-left both have their initial and final position same.. so no need of extra fittings.. so it will work even if you come from down
left-to-left & right-to-right don't have have their initial and final position same .. so left-to-left will become right-to-right in reverse loop. i did that using anti function

Script does not enter in else statement

I have a table on the right of my page( with id="efficacia"). I wrote this JS script in order to shift left/right clicking on it
JavaScript
$("#efficacia").click(function() {
var posizione = $("#efficacia").position();
if(posizione.right != 0) {
$(this).animate({
right: '0'
}, 1000);
} else {
$(this).animate({
right: '-202'
}, 1000);
}
});
CSS
#efficacia {
position: fixed;
right: -202px;
top: 200px;
cursor: pointer;
z-index: 100;
}
My script works well for the first "click", then when I click again it does not shitf on the right of 202px. It looks like that function does not enter in else statemet.
position().right does not exist. Only top and left.
http://api.jquery.com/position/
Base your condition on left attribute and it will work
position doesn't return a right property.
You can get the right css property so:
$("#efficacia").click(function() {
var right = parseInt($(this).css('right'));
if(right != 0) {
$(this).animate({
right: '0'
}, 1000);
} else {
$(this).animate({
right: '202'
}, 1000);
}
});
See the DEMO.
If you want get position of all corners then you can use getBoundingClientRect(). It will returns bottom, right, left, top, width and height of your div. But, of course, it will return values that starts from left corner.
var boundingBox = $(this).get(0).getBoundingClientRect();
console.log(boundingBox.right);
Read about getBoundingClientRect()
There's an error in your code at right: '-202'. You have to specify right: '-202px'.
Here's the updated code:
$("#efficacia").click(function() {
var right = $(this).css('right');
if(right != "0px") {
$(this).animate({
right: '0px'
}, 1000);
} else {
$(this).animate({
right: '-202px'
}, 1000);
}
});
That's it
jQuery.position() doesn't return value for style.right. It returns only
Object{top: somVal, left: somVal}
so if u want to get the value of right then get it from style attribute
Eg-
$("#efficacia").click(function() {
// var posizione = $("#efficacia").position();//here right is undefined
var right=this.style.right.replace("px", "") * 1;//fetch value of right from style
if(right != 0) {
$(this).animate({
right: '0'
}, 1000);
} else {
$(this).animate({
right: '202'
}, 1000);
}
});

jquery: animate down navigation, not sliding back up/working properly

Hey so i was trying to get my navigation to animate down after a certain div has passed but its not working properly. not sure why. it works when sliding down although a bit buggy(sometimes there seems to be a delay before it slides down and other times it slides down properly immediately). It also does not slide up it justs removes it self.
what am i doing wrong?
here is my code:
$(window).scroll(function () {
targetScroll = $('#scroll_verder').position().top,
currentScroll = $('html').scrollTop() || $('body').scrollTop();
if(currentScroll>=targetScroll){
$('.navbar').addClass('show-menu').animate({ top: '0px' });
}
else {
$('.navbar').stop();
$('.navbar').removeClass('show-menu');
$('.navbar').animate({ top: '-50px' });
}
});
Had a look at your code on the link you posted. This should do the trick:
var reachedTarget = false; // Prevent animation collisions with this
var targetScroll = $('#scroll_verder').position().top;
$(window).scroll(function () {
var currentScroll = $('html').scrollTop() || $('body').scrollTop();
if ( currentScroll >= targetScroll ) {
if ( !reachedTarget ) {
$('.navbar').stop();
$('.navbar').addClass('show-menu').animate({ top: '0px' });
}
reachedTarget = true;
} else{
if ( reachedTarget ) {
$('.navbar').stop();
$('.navbar').removeClass('show-menu').animate({ top: '-50px' });
}
reachedTarget = false;
}
});
EDIT: In CSS (to make sure initial position is correct):
.navbar.show-menu {
z-index: 999;
display: block;
top : -50px;
}

Categories