I have a button that's fixed on the bottom right side of the page;
.btn-this{
width: 313px;
height: 61px;
background-color: #ebb762;
position: fixed;
bottom: 0;
right: 0;
z-index: 99;
}
And so i wanted to change the position of the button from 'fixed' to 'relative' after scrolling at a certain point of the page;
Now at first i had this work out for me:
JQuery(function ($) {
var masinfo = $(".btn-this");
$(window).scroll(function () {
var scroll = $(window).scrollTop();
if (scroll >= 457) {
masinfo.css('position', 'relative');
} else {
masinfo.css({
position: 'fixed',
bottom: '0'
});
}
});
});
But then i did see that this was not a quality solution , since i would have to paste and change the code for each page, and it would never be smooth.
So i did check this two posts:
Check if a user has scrolled to the bottom
How could I add a class of "bottom" to "#sidebar" once it reaches the bottom of its parent container?
But then again , i couldn't make it work smoothly, the code works, but it executes a lot of time,
when using:
if ($(window).scrollTop() + $(window).height() > $(document).height() - 78) {
console.log('bottom');
}
the console logs "bottom" 11 times;
I tried using a debouncer, but i just didn't understand the concept or just didn't do it the right way;
Has anyone been able to do something like this?
I see 3 possible bottlenecks:
global event listener($(window).scroll()) may be attached for several times(it can be if you have SPA where navigation does not reload page and each new page set up one more handler)
scroll event handler occurs on each scroll event
... and handler freeze page until its ended - that's where passive event listeners come to rescue.
As for #2 you addressed this with debouncing but it's better to see your code(about exact debouncing logic). You may make it in wrong way so not only last event dispatch handler is called but every time(with some delay)
As for #3 jQuery does not support it yet so you need to use low-level addEventListener instead.
A debounce function limits the rate at which a function can fire. Read more about debounce function
There is one more way you can improve the performance of animations/scroll that is requestAnimationFrame
so your function can be written as
JQuery(function ($) {
var masinfo = $(".btn-this");
$(window).scroll(function () {
// If there's a timer, cancel it
if (timeout) {
window.cancelAnimationFrame(timeout);
}
// Setup the new requestAnimationFrame()
timeout = window.requestAnimationFrame(function () {
if ($(window).scrollTop() + $(window).height() > $(document).height() - 78) {
console.log('bottom');
}
});
});
});
Related
I've created this script:
jQuery(".resultlist").mousewheel(function(event, delta) {
this.scrollLeft -= (delta);
event.preventDefault();
});
which fires a horizontal scroll function over the .resultlist container and this is working as expected. I need to disable this on screen widths underneath 545px so I've wrapped it in a resize function.
/* Trigger Resize Script */
jQuery(document).ready(function(){
function resizeForm(){
var width = (window.innerWidth > 0) ? window.innerWidth : document.documentElement.clientWidth;
if(width > 545){
jQuery(".resultlist").mousewheel(function(event, delta) {
this.scrollLeft -= (delta);
event.preventDefault();
});
} else {
// invert
}
}
window.onresize = resizeForm;
resizeForm();
});
/* End Trigger Resize Script */
The problem I have is that the script still runs if else is true, I did start working on a function that would include and then delete a separate script based on screenwidth but this became very cumbersome and is surely not the right way to achieve this.
I need to convert the mousewheel function so that it behaves like a normal vertical scroll instead, so that I can switch between my current horizontal scroll and a normal vertical scroll inside the resize function.
How do I amend the below function to scroll vertically?
jQuery(".resultlist").mousewheel(function(event, delta) {
this.scrollLeft -= (delta);
event.preventDefault();
});
There's a lot of going on in your code. One of the misconcepts is, that it creates a ton of mousewheel listeners on the elements when resizing the window. Here's how you can achieve what you need:
'use strict';
// Allows an event handler to run only when the event has stopped to fire
function debounce(callback, delay = 200) {
let timeout;
return function() {
const context = this,
args = arguments;
window.clearTimeout(timeout);
timeout = window.setTimeout(function() {
callback.apply(context, args);
}, delay);
};
}
jQuery(document).ready(function() {
let width, dirProp;
function resizeForm() {
width = jQuery(window).width();
dirProp = (width > 545) ? 'scrollLeft' : 'scrollTop';
}
function scroll(event) {
event.preventDefault();
// Use the original event object to access WheelEvent properties
this[dirProp] += (event.originalEvent.deltaY);
}
jQuery(".resultlist").on('wheel', scroll);
jQuery(window).on('resize', debounce(resizeForm));
resizeForm();
});
.resultlist {
position: relative;
width: 200px;
height: 200px;
overflow: auto;
}
.list-content {
position: relative;
height: 500px;
width: 500px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="resultlist">
<div class="list-content">Text</div>
</div>
The code uses standard WheelEvent and a debouncer to prevent the resize event to be handled continuously (resize event fires tens of times per second during resizing). The resize handler updates width and dirProp variables, which then are used in the WheelEvent handler to determine which way to scroll the element (with the bracket notation you can use a variable as a property name).
It's notable, that the strict mode is a must with this code, otherwise the debouncer might actually consume more time than it was purposed to save.
You might want to add some kind of "scroll home" function to reset the scrollable element when the window size is changed. You can test the code at jsFiddle.
I want to implement scrolling event function that forwards me to certain position on page like it's done in FullPage.js.
Example: https://alvarotrigo.com/fullPage
I tried adding onscroll event listener, which distinguishes scrolling direction and then executes scrollTo() , but it seems like a bad idea.
How do i implement this properly? Thanks in advance.
What i tried so far:
function throttle(fn, delay) {
let last;
let timer;
return () => {
const now = +new Date;
if (last && now < last + delay) {
clearTimeout(timer);
timer = setTimeout(() => {
last = now;
fn();
}, delay);
} else {
last = now;
fn();
}
};
}
var scrollPos = 0;
function smooth_scroll(){
// detects new state and compares it with the new one
if ((document.body.getBoundingClientRect()).top > scrollPos)
{
window.scrollTo({ top: 0, behavior: 'smooth' })
}
else
{
window.scrollTo({ top: 1000, behavior: 'smooth' })//as an example
}
// saves the new position for iteration.
scrollPos = (document.body.getBoundingClientRect()).top;
}
window.addEventListener('scroll', throttle(smooth_scroll, 1000));
I expect it to work like this: whenever i scroll down it forwards me to bottom (1000, 0), and when i scroll up it gets me to the top. All smoothly.
If you look onto your example website you can see that they are not scrolling a list. They are animating a wrapper and its children:
class: fullpage-wrapper
attribute they change: transform:translate3d(0px, -937px, 0px);
What happens ist that all elements are inside one wrapper which is then moved upwards the height of the box. The smooth effect of this page is provided by a specific easing which can be attached to the CSS animation.
So if you want to get the same "scrolling" effect you need to think about an animation solution. Therefore you can stick to blank CSS-Animations or Framework/Library specific ones.
For further informations about animation, I can try to help you as far as it's not getting a full Animation course :)
i was working on woocommerce site.My Site . The single product page has a control generator with a number of drop down options.So when a user selects each options he cannot see the changes happening at the top.So i position the image div as fixed.As follows.
.single-product .images{position:fixed;}
this made the image fixed but it is floating till down the page.I only need it just before the description/review tabs starts.Is there any other css or any js/jquery solutions to solve this .Please help.Thanks!!
Based on your website environment, you need something like this:
var images = jQuery('.images');
jQuery.fn.followTo = function (pos) {
var $this = this,
$window = jQuery(window);
$window.scroll(function (e) {
if ($window.scrollTop() > pos) {
$this.css({
position: 'absolute',
top: pos - $this.height()
});
} else {
$this.css({
position: 'fixed',
top: 'auto' //earlier it was 0
});
}
});
};
images.followTo(jQuery('#myTab').offset().top - images.height());
You may need to re-position the elements a bit, but the script will work on your website, as I tested with firebug.
I have note written this script, the script attributed to: Stopping fixed position scrolling at a certain point?
Let me know if you can take it forward from here :)
I had this working with no problems for the entire build of the site. Then, the day I was supposed to launch, the sticky menu stopped working right. The menu is supposed to start at the bottom, scroll to the top, then stick (position: fixed).
Now, it scrolls about 10px and then jumps to the top. Why is the scrollTop distance not calculating correctly?
Live site at [site no longer exists]
Here's the code for the sticky menu. I'm also using JS to set min-height of divs to window height, but haven't included that code here.
$(function(){
var stickyRibbonTop = $('#wrapper-wcf53badf7ebadf7').offset().top;
$(window).scroll(function(){
if( $(window).scrollTop() > stickyRibbonTop ) {
$('#wrapper-wcf53badf7ebadf7').css({position: 'fixed', top: '0px', 'background-image':'url(http://amarshall.360zen.com/wp-content/uploads/2014/07/menu-fade-background2.png)'});
$('#block-bcf53bf14093931c').css({display: 'block'});
} else {
$('#wrapper-wcf53badf7ebadf7').css({position: 'static', top: '0px','background-image':'none'});
$('#block-bcf53bf14093931c').css({display: 'none'});
}
});
});
Thanks in advance for any help! I'm not a JS or jQuery expert yet, so any suggestions for cleaning things up would be appreciated.
NOTE: The site is built on WordPress, so no-conflict mode is in effect.
I think you are initialising the sticky menu function before you set the min-height of $('big-div').
On page load, the menu starts at 54px from the top, and so when you store the offset().top value as stickyRibbonTop, it is stored at 54px. Then on your scroll event you are comparing against this.
Try setting the min-height of the divs first in your code, then run this same script afterwards. The value of stickyRibbonTop should then be correct.
Bear in mind that you will need to reset stickyRibbonTop every time the window.height() is updated, so you should probably make this sticky menu function a named function and call it at the end of the wrapper_height function. something like this:
function stickyNav() {
var stickyRibbonTop = $('#wrapper-wcf53badf7ebadf7').offset().top;
$(window).unbind('scroll', scrollEvent);
$(window).on('scroll', stickyRibbonTop, scrollEvent);
};
function scrollEvent(event) {
var stickyRibbonTop = event.data;
if ($(window).scrollTop() > stickyRibbonTop) {
$('#wrapper-wcf53badf7ebadf7').css({ position: 'fixed', top: '0px', 'background-image': 'url(http://www.adammarshalltherapy.com/wp-content/uploads/2014/07/menu-fade-background2.png)' });
$('#block-bcf53bf14093931c').css({ display: 'block' });
}
else {
$('#wrapper-wcf53badf7ebadf7').css({ position: 'static', top: '0px', 'background-image': 'none' });
$('#block-bcf53bf14093931c').css({ display: 'none' });
}
};
function wrapper_height() {
var height = $(window).height();
var wrapperheight = height - 75;
wrapperheight = parseInt(wrapperheight) + 'px';
$(".bigDiv").css('min-height', wrapperheight);
$("#wrapper-wcf53bad125d7d9a").css('height', wrapperheight);
stickyNav();
}
$(function () {
wrapper_height();
$(window).bind('resize', wrapper_height);
});
I'm trying to create a popup box on a list of items that goes very much to the bottom of the browser.
I want the POPUP to be in the center of the page where the user is at regardless of how low they scrolled
i have to use POSITION ABSOLUTE not FIXED
but when i use POSITION ABSOLUTE the popup always appears on top and i know its due to my top: 0
.lightbox-container{
border: solid red 1px;
width: 100px;
height: 40px;
background: yellow;
position: absolute;
top: 0;
}
I want to use something like scrollTop or one of those to get the popup to always stay in the users viewpoint regardless of how low they scrolled
$('a').on('click', function(e){
var lightBox = $('<div class="lightbox-container"> <p>click to remove</p>');
lightBox.appendTo('body');
$('.lightbox-container').on('click', function(e){
$(this).remove();
});
});
here is the fiddle im working on http://jsfiddle.net/2RNAN/1/
I know there are other posts about this but im very new to jquery and cant seem to get it working.
This works working fiddle here
$('a').on('click', function (e) {
e.preventDefault();
var lightBox = $('<div class="lightbox-container"> <p>click to remove</p>');
lightBox.appendTo('body');
$('.lightbox-container').css('top', $(document).scrollTop() + 'px');
$('.lightbox-container').on('click', function (e) {
$(this).remove();
});
});
$(document).on('scroll', function () {
$('.lightbox-container').css('top', $(document).scrollTop() + 'px');
});
Edit: I think its a bit unclean and also unnecessary to center the pop-up box via jQuery. You can easily do this with CSS. Check out my updated JsFiddle: http://jsfiddle.net/kCC8p/9/ Edit End
I set the overflow to hidden on the body and included the pop-up outside the scrollable element. This way the scroll position of the user doesn't matter anymore.
JS
var lightbox = $('.lightbox-container');
$('a').click(function(e) {
e.preventDefault();
lightbox.show();
lightbox.addClass('open');
lightbox.append('<p>Click to remove</p>');
});
lightbox.click(function(e) {
lightbox.removeClass('open');
lightbox.find('p').remove();
$(this).hide();
});
See rest on jFiddle...
I may be a little late but I think this might be closer to what you were after:
Working Example
$(function () {
var lightbox = $('.lightbox-container'),
center = function () {
var T = $(window).height() / 2 - lightbox.height() / 2 + $(window).scrollTop(),
L = $(window).width() / 2 - lightbox.width() / 2;
lightbox.css({
top: T,
left: L
}).click(function () {
$(this).hide();
});
};
$('a').click(function (e) {
e.preventDefault();
lightbox.show().text('Click to remove');
center();
});
$(window).scroll(center);
$(window).resize(center);
});
Note that this method centers the popup and keeps it centered regardless of scrolling or re-sizing.
Are you avoiding the use of position fixed due to IE9 compatibility or some other reason? Using position fixed is probably the simplest answer and then address whatever compatibility issue you're having with specific browsers, such as with this answer for IE9 regarding quirks mode.