Setting a jScrollPane to autoscroll left and right, but pause on click? - javascript

Fiddle: http://jsfiddle.net/RJShm/
I have a jScrollPane that currently scroll from left, to right, then back left, and stops. What I'd like is for this to continually scroll from left to right, the right to left, then repeat. I have this fairly close to working by using pane.bind('jsp-scroll-x'..., but I can't seem to get it to scroll back to the right after one cycle. Current code for that:
pane.bind('jsp-scroll-x', function (event, pos_x, at_left, at_right) {
if (at_right)
{
api.scrollToX(0);
$(this).unbind(event);
}
});
I would also like for this to stop autoscrolling when anything in the pane is clicked (scroll bar, arrows, content, anything), and it would preferably restart after a few seconds of no clicks.
So, in short, how do I:
Make the jScrollPane scroll left/right automatically
Stop autoscrolling when clicked
Restart autoscrolling after a few seconds of no clicks inside the pane
Thanks
EDIT: jScrollPane Settings, and api for your convenience.

I have updated the handler for toggling the infinite scroll and also implemented click handler to pause the scroll and resume after a timeout (5 seconds). See draft code below and check the DEMO: http://jsfiddle.net/p6jLt/
var defaultSettings = {
showArrows: true,
animateScroll: true,
animateDuration: 5000
},
pauseSettings = {
showArrows: true,
animateScroll: false
};
var pane = $('.scroll-pane').jScrollPane(defaultSettings);
var api = pane.data('jsp');
var isFirst = true,
posX = 0,
isLeft = false,
timer;
pane.bind('jsp-scroll-x', scrollFx)
.mousedown(function () {
//lets make sure the below is
//executed only once after automatic croll
if (posX != -1) {
$(this).unbind('jsp-scroll-x');
api.scrollToX(posX);
api.reinitialise(pauseSettings); //no animation
posX = -1;
}
}).mouseup(function () {
clearTimeout(timer); //clear any previous timer
timer = setTimeout(function () {
isFirst = true;
posX = 0; //reset the killer switch
api.reinitialise(defaultSettings); //animateed scroll
pane.bind('jsp-scroll-x', scrollFx); //rebind
api.scrollToX(isLeft ? 0 : api.getContentWidth()); //resume scroll
}, 5000);
});
var scroll = api.scrollToX(api.getContentWidth());
function scrollFx(event, pos_x, at_left, at_right) {
if (posX == -1) { //kill scroll
$(this).unbind(event);
return false;
}
if (at_right) {
api.scrollToX(0);
isLeft = true; //used for restart
} else if (at_left && !isFirst) {
api.scrollToX(api.getContentWidth());
isLeft = false; //used for restart
}
isFirst = false;
posX = pos_x;
}
Issues: The plugin is little buggy with scroll sometimes, but it doesn't break the infinite scroll. You may find the little hicks on scroll, but it works for the most part. Test it out thoroughly and see how it goes.

Related

how to change carousel slide on mousewheel

I'm working on a project and I need to create a vertical carousel that works on scroll (mousewheel) I just need to know how can I handle the sliding on scroll.
I have a function called nextSlide when I call then it get the next slide.
I did something like this (I checked the direction and other stuff but I'm adding the simplest code snippet here)
Note: I did Debounce on my function but it didn't work
el.addEventListener('wheel', (event) => {
event.preventDefault();
nextSlide();
});
The problem here is the event firing on each mouse scroll I just need to handle it on one scroll here is an example from swiper
https://codepen.io/Seamni69/pen/vYgmqVd
What I meant by one scroll is calling the function just one time when scrolling, no matter how much scrolling is.
Created this. if wheelDeltaY is positive, you are scrolling down. If it's negative you are scrolling up.
window.addEventListener('wheel', throttle(scrollDirection, 500));
function scrollDirection(e) {
e.preventDefault();
e.wheelDeltaY > 0
? console.log("DOWN")
: console.log("UP")
e.stopImmediatePropagation();
};
function throttle(func, interval) {
let lastCall = 0;
return function() {
const now = Date.now();
if (lastCall + interval < now) {
lastCall = now;
return func.apply(this, arguments);
}
};
}

jQuery "Snap To" Effect

I have a specific effect I want for a website I'm building. As you can see in this website, I want the screen to "snap to" the next section after the user scrolls, but only after (not the instant) the scroll event has fired. The reason I don't want to use a plugin like panelSnap is because I
1: Want smaller code and
2. Want the website, when viewed on mobile, to have more of the "instant snap" effect (try reducing the browser size in the website mentioned above). I know I theoretically could try combining two plugins, like panelsnap and scrollify, and activate them appropriately when the browser is a certain width, but I don't know if I want to do that... :(
So all of that said, here's the code:
var scrollTimeout = null;
var currentElem = 0;
var options = {
scrollSpeed: 1100,
selector: 'div.panels',
scrollDelay: 500,
};
$(document).ready(function() {
var $snapElems = $(options.selector);
console.log($($snapElems[currentElem]).offset().top);
function snap() {
if ($('html, body').scrollTop() >= $($snapElems[currentElem]).offset().top) {
if (currentElem < $snapElems.length-1) {
currentElem++;
}
}else{
if (currentElem > 0) {
currentElem = currentElem - 1;
}
}
$('html, body').animate({
scrollTop: $($snapElems[currentElem]).offset().top
}, options.scrollSpeed);
}
$(window).scroll(function() {
if ($(window).innerWidth() > 766) {
if (scrollTimeout) {clearTimeout(scrollTimeout);}
scrollTimeout = setTimeout(function(){snap()}, options.scrollDelay);
}else{
//I'll deal with this later
}
});
});
My problem is that every time the snap function is called, it triggers the scroll event, which throws it into a loop where the window won't stop scrolling between the first and second elements. Here's the poor, dysfunctional site: https://tcfchurch.herokuapp.com/index.html Thank for the help.
You can use a boolean to record when the scroll animation in snap is in progress and prevent your $(window).scroll() event handler from taking any action.
Here's a working example:
var scrollTimeout = null;
var currentElem = 0;
var options = {
scrollSpeed: 1100,
selector: 'div.panels',
scrollDelay: 500,
};
$(document).ready(function() {
var scrollInProgress = false;
var $snapElems = $(options.selector);
console.log($($snapElems[currentElem]).offset().top);
function snap() {
if ($('html, body').scrollTop() >= $($snapElems[currentElem]).offset().top) {
if (currentElem < $snapElems.length-1) {
currentElem++;
}
}else{
if (currentElem > 0) {
currentElem = currentElem - 1;
}
}
scrollInProgress = true;
$('html, body').animate({
scrollTop: $($snapElems[currentElem]).offset().top
}, options.scrollSpeed, 'swing', function() {
// this function is invoked when the scroll animate is complete
scrollInProgress = false;
});
}
$(window).scroll(function() {
if (scrollInProgress == false) {
if ($(window).innerWidth() > 766) {
if (scrollTimeout) {clearTimeout(scrollTimeout);}
scrollTimeout = setTimeout(function(){snap()}, options.scrollDelay);
}else{
//I'll deal with this later
}
}
});
});
The variable scrollInProgress is set to false by default. It is then set to true when the scroll animate starts. When the animate finishes, scrollInProgress is set back to false. A simple if statement at the top of your $(window).scroll() event handler prevents the handler from taking any action while the animate scroll is in progress.
Have you considered using the well known fullPage.js library for that? Check out this normal scroll example. The snap timeout is configurable through the option fitToSectionDelay.
And nothing to worry about the size... it is 7Kb Gzipped!
I know I theoretically could try combining two plugins, like panelsnap and scrollify, and activate them appropriately when the browser is a certain width, but I don't know if I want to do that
fullPage.js also provides responsiveWidth and responsiveHeight options to turn it off under certain dimensions.

Too many scroll events for smooth scrolling

Hello there I've been trying to find a fix for the many scroll events firing on one scroll. This is the only thing close to working for me so far. I want to smoothscroll between two divs (#boxes and #header) I want to use the scroll bar to trigger this smooth scroll and not a button. Any suggestions on how to only take one scroll event? I also used solutions based from prev stackoverflow questions. I used my own locator instead of offsets because thats also unreliable
$(window).scroll(function () {
if (timer) {
window.clearTimeout(timer);
}
timer = window.setTimeout(function () {
if (locator == 0) {
id = $("#boxes");
locator = 1;
} else if (locator = 1) {
id = $("#header");
locator = 0;
}
// target element
var $id = $(id);
if ($id.length === 0) {
return;
}
// top position relative to the document
var pos = $id.offset().top;
// animated top scrolling
$('html, body').animate({scrollTop: pos}, 1500, function () {
$('html, body').clearQueue();
$('html, body').stop();
});
}, 2);
});
So, to be clear, you want any minor scroll event to scroll between one item and the other? Note that when a user scrolls, there is a "momentum" that the browser implements, and you'll be battling with that.
Regardless: You don't need to wrap this in a setTimeout. Right now, your javascript is creating a new setTimeout function that is being fired every 2ms. Scroll events occur with every pixel of movement in the scroll, so if you scroll 100px, you're going to be firing 100 times every 2ms. (That's 50,000 times).
Instead, have a a variable (isScrolling) track the state, so, if you're in the middle of scrolling, the function won't fire.
var isScrolling = false;
var locator = 0;
$(window).scroll(function () {
if (isScrolling) return false;
if (locator == 0) {
id = $("#boxes");
locator = 1;
} else if (locator = 1) {
id = $("#header");
locator = 0;
}
// target element
var $id = $(id);
if ($id.length === 0) {
return;
}
// top position relative to the document
var pos = $id.offset().top;
// animated top scrolling
isScrolling = true;
$('html, body').animate({scrollTop: pos}, 1500, function () {
$('html, body').clearQueue();
$('html, body').stop();
isScrolling = false;
});
});
Here's a JSbin: http://jsbin.com/jugefup/edit?html,css,js,output

swipe gesture that reply action

I have this code:
var controller = new Leap.Controller({enableGestures: true});
controller.on('gesture', function (gesture){
console.log(gesture);
if(gesture.type === 'swipe'){
handleSwipe(gesture);
}
});
function handleSwipe (swipe){
var startFrameID;
if(swipe.state === 'stop'){
if (swipe.direction[0] > 0){
//this means that the swipe is to the right direction
slideTimer = setTimeout(function(){
slidePict("sx");
},500);
}else{
//this means that the swipe is to the left direction
slideTimer = setTimeout(function(){
slidePict("dx");
},500);
}
}
}
controller.connect();
It works fine, due recognize swipe gesture, but when the gesture is performed, both to the left and towards the right, the slide seems to receive two successive input, and then taking two / three slide following...
How can I avoid this?
Swipe gestures are generated by the finger tips -- not the hand-- so you could get up to 5 swipe events per hand per frame. Then, the next frame, you will get swipe events updating the properties of each gesture.
You could modify your code as follows, so that it waits for the current swipe action to finish before allowing another action to start:
var isSwiping = false;
var controller = new Leap.Controller({enableGestures: true});
controller.on('gesture', function (gesture){
console.log(gesture);
if(gesture.type === 'swipe' && !isSwiping){
isSwiping = true;
handleSwipe(gesture);
}
});
function handleSwipe (swipe){
var startFrameID;
if (swipe.direction[0] > 0){
//this means that the swipe is to the right direction
slideTimer = setTimeout(function(){
slidePict("sx");
isSwiping = false;
},500);
}else{
//this means that the swipe is to the left direction
slideTimer = setTimeout(function(){
slidePict("dx");
isSwiping = false;
},500);
}
}
controller.connect();
[edit] removed if(swipe.state == "stop"){} clause from handleSwipe() function.

jQuery Scroll Timeout

I'm trying to put a delay on page scroll so if I put some animation, it will not ruin. Here is my code:
var lastScrollY = 0,
delayFlag = true,
delayTime = 1000;
$(window).on('scroll', function(e) {
if(delayFlag == true) {
delayFlag = false;
var posY = $(this).scrollTop(),
sectionH = $('.page').height(),
multiplier = (Math.round(lastScrollY / sectionH));
if(lastScrollY > posY) {
$(window).scrollTop((multiplier - 1) * sectionH);
}
else {
$(window).scrollTop((multiplier + 1) * sectionH);
}
lastScrollY = posY;
setTimeout(function() { delayFlag = true }, delayTime);
}
else {
e.preventDefault();
}
});
jQuery preventDefault() is not working. Is there any way I can put some delay on scroll event?
e.preventDefault(); is for preventing the default action of an event. For example, clicking on an anchor will cause the page to navigate to the address stored on the anchor's href, and calling e.preventDefault(); in an anchor's click event will cause this navigation to not happen.
e.preventDefault(); does not, however, cancel the event that just occurred. Calling it in the onchange event of a form input will not revert its value back to what it just was, and calling it in the scroll event will not cancel the scroll.
While I wouldn't recommend this, from a UX perspective (personally, I hate pages that stop me from going someplace in the site, just so I have to watch their ad or whathaveyou, and I'm fairly sure I'm not the only one...), what you might be able to do, rather than capture the scroll event, is turn off scrolling for the area to start with.
So, have something along these lines (example jsFiddle: http://jsfiddle.net/mori57/cmLun/):
In CSS:
.noscroll {
overflow:hidden;
}
And in your JS:
var lastScrollY = 0,
delayFlag = true,
delayTime = 1000;
$(function(){
$("body").addClass("noscroll");
window.setTimeout(function(){
$("body").removeClass("noscroll");
}, delayTime );
});

Categories

Resources