I am building a full page slider that keeps the native scrollbar and allows the user to either free scroll, use the mouse wheel or navigation dots (on the left) to switch to a slide.
Once the user is on the last slide and tries to scroll down further, the whole slider moves up to reveal a simple scrollable section. If the user scrolls down and then tries to go back up, then this new section moves out of the way again and returns the slider back into view.
Fiddle: http://jsfiddle.net/3odc8zmx/
The parts I'm struggling with:
Only the first two navigation dots work. The third one DOES WORK if you area looking at the first slide. But doesn't do anything, if you are on slide 2. Note: the purple one is a short-cut to the second section of the page and not related to the slider.
When moving to the last slide (via the dots, if you're on the first slide) it causes the code to make the whole slider move upwards as it sees this as the user has slid past the last slide as per the description above. I have tried to combat this using a variable called listen to stop the scroll event listening when using the showSlide method... but it seems to be true even though I set it to false, and only reset it to true again after the animation...
When scrolling down using the mouse wheel, I can get to the second section and back up, but not to the first third section. I'm wondering if I could use the showSlide method to better handle this instead of the current dirty next and prev functions I have implemented.
Note: If the user has free-scrolled, when they use the mouse-wheel, I want the slider to snap to the nearest slide to correct itself... Any suggestions for how I could do this?
Can anyone offer some help?
Here's the JS:
var listen = true;
function nextSlide()
{
$('#section1').stop(true,false).animate({
scrollTop: $('#section1').scrollTop() + $(window).height()
});
}
function prevSlide()
{
$('#section1').stop(true,false).animate({
scrollTop: -$('#section1').scrollTop() + $(window).height()
});
}
function showSlide(index)
{
var offset = $('#section1 div').eq(index).offset();
offset = offset.top;
if(offset){
listen = false;
$('.slide-dot').removeClass('active');
$('.slide-dot').eq(index).addClass('active');
$('#section1').stop(true,false).animate({
scrollTop: offset
}, 500, function(){
listen = true;
});
} else {
alert('error');
}
}
$(document).ready(function(){
var fullHeight = 0;
$('#section1 div').each(function(){
fullHeight = fullHeight + $(this).height();
});
var lastScrollTop1 = 0;
$('#section1').on('scroll', function(e){
var st = $(this).scrollTop();
if (st > lastScrollTop1){
if( $('#section1').scrollTop() + $(window).height() == fullHeight) {
if(listen){
$('body').addClass('shifted');
}
}
}
lastScrollTop1 = st;
});
$('#section1').on('mousewheel', function(e){
e.preventDefault();
var st = $(this).scrollTop();
if (st > lastScrollTop1){
nextSlide();
} else {
prevSlide();
}
});
var lastScrollTop2 = 0;
$('#section2').on('scroll', function(e){
var st = $(this).scrollTop();
if (st > lastScrollTop1){
} else {
if( st == 0 ){
$('body').removeClass('shifted');
}
}
lastScrollTop1 = st;
});
$('.slide-dots').css({'margin-top':-$('.slide-dots').height() / 2});
$('.slide-dot').first().addClass('active');
$(document).on('click', '.slide-dot', function(e){
e.preventDefault();
showSlide( $(this).index() );
});
$(document).on('click', '.slide-dot-fake', function(e){
e.preventDefault();
$('body').addClass('shifted');
});
});
And for those wondering why I'm not using something like fullPage.js, it's because it can't handle the way I want to transition between the two areas and have two scrollbars (one for each area).
You can use:
e.originalEvent.wheelDelta
instead of:
st > lastScrollTop1
in the mousewheel event for your third problem to check if the user has scrolled up or down. And also change the +/- in prevSlide. I used dm4web's fiddle for your first problem. And I used:
scrollTop: offset - 1
instead of:
scrollTop: offset
for your second problem, because when the scroll reaches to the last pixel of the third element, it automatically goes to the next section, so 1 pixel is enough for it not to.
Here's the fiddle: http://jsfiddle.net/3odc8zmx/3/
As suggested by #chdltest, you could do it by using fullPage.js.
Here's an example. Go to the last section.
Code used for the example:
Javascript
$('#fullpage').fullpage({
sectionsColor: ['yellow', 'orange', '#C0C0C0', '#ADD8E6'],
scrollOverflow: true,
scrollBar: true,
afterLoad: function (anchor, index) {
//hiding the main scroll bar
if (index == 4) {
$('body, html').css('overflow', 'hidden');
}
//showing the main scroll bar
if (index == 3) {
$('body, html').css('overflow', 'visible');
}
}
});
CSS (in case you prefer to use the normal style for it)
/* Normal style scroll bar
* --------------------------------------- */
.slimScrollBar {
display: none !important;
}
.fp-scrollable {
overflow: auto !important;
}
Advantages of using fullPage.js instead to your own code:
Strongly tested in different devices and browsers. (IE, Opera, Safari, Chrome, Firefox..)
Prevent problems with trackpads, Apple laptops trackpads or Apple Magic Mouse.
Old browser's compatibility, such as IE 8, Opera 12...
Touch devices compatibility (IE Windows Phone, Android, Apple iOS, touch desktops...)
It provides many other useful options and callbacks.
I've been trying to fade out a splash when scrolling down, and fading it in when scrolling back to the top of the page. It seems to work ok when scrolling down, but when I go back, it doesn't fades in. I tryed using fadeIn and FadeOut instead of fadeTo but didn't get a proper behavior
The code is actually pretty simple:
var splashTop = $('.splash-container').offset().top;
$(window).scroll(function () {
if ((splashTop - $(window).scrollTop()) < 50) {
$('.splash-container').stop().fadeTo("slow", 0);
} else {
$('.splash-container').stop().fadeTo("fast", 1);
}
});
And here is the jsFiddle example:
jsFiddle
If you just need to check if the scroll is at the top or not then you don't need to check the position of the Splash, Try:
$(window).scroll(function () {
if ($(window).scrollTop() > 0) {
$('.splash-container').stop().fadeTo("slow", 0);
console.log('p')
} else {
$('.splash-container').stop().fadeTo("fast", 1);
console.log(box1Top)
}
});
Check the Demo Fiddle
Edit
Now why your code doesn't work? ... Because you are always getting a value less than 50:
splashTop = 8 always
-
$(window).scrollTop() = more than 0
Then the result is always negative or 8 as max, you can never have a number more than 8 and your else condition is useless.
I try to use jQuery visible plugin to detect if an element is or isn't visible in the viewport. I use a code like this:
animateFrontPage: function(){
var apps = 0;
if($('#apps-shelf').visible(true)) {
apps = 1;
if(apps == 1) {
$('#apps-shelf li').velocity("transition.bounceUpIn", { stagger: 150 });
apps = 0
}
}
}
and I run it with scroll function:
$(window).scroll(function() {
Functions.animateFrontPage();
});
The problem is - animation repeats itself with every scroll. What can I do to prevent it?
If you only want the animation to show once, what you could do is add a class to the element to flag that it is finished - then each time you only carry out the animation if the element does not have this class. Perhaps something along these lines :
animateFrontPage: function(){
var $el = $('#apps-shelf');
if($el.visible(true) && !$el.hasClass('finished')) {
$el.addClass('finished');
$el.find('li').velocity("transition.bounceUpIn", { stagger: 150 });
}
}
Update
This is the else statement you need if you want the other animation to run on these conditions : a) the animation of the first element $('#apps-shelf') has already happened and b) the element $('#apps-shelf') is no longer visible on the screen (you have scrolled past it for example)
animateFrontPage: function(){
var $el = $('#apps-shelf');
if($el.visible(true) && !$el.hasClass('finished')) {
$el.addClass('finished');
$el.find('li').velocity("transition.bounceUpIn", { stagger: 150 });
} else if (!$el.visible(true) && $el.hasClass('finished')){
//other animation here
}
}
i was working on a galery where when the user scrolls and reaches a thumb certain background action occurs.
Now did this coding and i am able to get the result but somehow i am confused as it only works one time and then when i again scroll to that position it does nothing.
I am using alert boxes to reach 5th and 7th thumb and it only shows message once.
I am using something like this
$(document).ready(function () {
// Thumb 1
var thumb4Target = $("#myImg1").offset().top;
var interval = setInterval(function () {
if ($(window).scrollTop() >= thumb4Target) {
alert('1nd Image Position Obtained');
clearInterval(interval);
}
}, 0);
//Thumb 2
var thumb4Target2 = $("#myImg2").offset().top;
var interval2 = setInterval(function () {
if ($(window).scrollTop() >= thumb4Target2) {
alert('2nd Image Position Obtained');
clearInterval(interval2);
}
}, 0);
});
check this Fiddle
LINK
Please tell me where i am doing wrong.Thanks.
Use scroll event instead of interval. LIVE DEMO 1 Or LIVE DEMO 2
$(window).scroll(function()
{
var thumb4Target = $("#myImg1").offset().top;
var thumb4Target2 = $("#myImg2").offset().top;
if ($(window).scrollTop() >= thumb4Target) {
alert('1nd Image Position Obtained');
}
if ($(window).scrollTop() >= thumb4Target2) {
alert('2nd Image Position Obtained');
}
});
I am trying to make build my own carousel from scratch since I cant find a plugin that does what I want. Which is having a vertical and horizontal plugin that work at the same time both ways.
Anyway I decided to give it a shot and try to build my own. But right now I am stuck at trying to understand why my "next" button doesn't disappear when it has reached the end of the carousel.
here is the code:
$(document).ready(function() {
var sliderWidth = 300; // Give the size of the window
var sliderV = $('#slide-wrap-vertical'); // Assigns the container that has all the sectiosn that will be scrolled vertically
var sliderCount = $(sliderV).children().size(); // Gets the size of the verticla slider
//test();
$('a.nav-top-prev').on('click',function () {
$('#slide-wrap-vertical > div').animate({
top: '+=' + sliderWidth
}, 500);
showHideDirection();
});
$('a.nav-top-next').on('click', function () {
$('#slide-wrap-vertical > div').animate({
top: '-=' + sliderWidth
}, 500);
showHideDirection();
});
function showHideDirection() {
$(sliderV).children().each(function(){ // Checks all the children of the vertical carousel
if ($(this).position().top == 0) { // Finds the index of the children that is currently on view
if ($(this).index() == 0) { // If its the first one can't scroll back and hides the prev button
$('a.nav-top-prev').hide();
}
else if ($(this).index() >= sliderCount) { // If its the last one can't scroll forward and hides the next button
$('a.nav-top-next').hide();
}
else {
$('a.nav-top-prev').show();
$('a.nav-top-next').show();
}
}
});
}
});
http://jsfiddle.net/Dethdoll/WkFVs/8/
because sliderCount is 1 based and index() is zero based, it is impossible for index to be equal or greater than sliderCount. You need to subtract one.
else if ($(this).index() === sliderCount-1)
You can simplify those if/else checks with toggle
if ($(this).position().top == 0) {
var index = $(this).index();
$('a.nav-top-prev').toggle(index!==0);
$('a.nav-top-next').toggle(index!==sliderCount-1);
}