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);
}
Related
I came accross the following fiddle which let elements fade out of the document 1 by 1 as they reach the top.
By executing javascript:
$(window).scroll(function () {
$('[id^="box"]').each(function () {
if (($(this).offset().top - $(window).scrollTop()) < 20) {
$(this).stop().fadeTo(100, 0);
} else {
$(this).stop().fadeTo('fast', 1);
}
});
});
http://jsfiddle.net/JdbhV/6/
Only this is working on the full window, I want it to work on a div tag. So I modified the fiddle to add the div test and all other divs inside there, then modify the javascript to grab the div instead of the window:
$("#test").scroll(function () {
$('[id^="box"]').each(function () {
if (($(this).offset().top - $("#test").scrollTop()) < 20) {
$(this).stop().fadeTo(100, 0);
} else {
$(this).stop().fadeTo('fast', 1);
}
});
});
http://jsfiddle.net/JdbhV/1692/
But now they fade too fast and not when they reach the top of the div.
Does someone have a pointer what is going wrong here?
The .offset() method allows us to retrieve the current position of an element relative to the document.
Scrolling the window doesn't change the position of elements in the document however scrolling elements inside another element does. This causes the offset position to change which throws off the check to see if box is at the top of the scroll view.
Try using the .position() method which gets the position relative to the parent.
$("#test").scroll(function () {
$('[id^="box"]').each(function () {
//When the top of the square goes above the top of the scroll element, fade it out
if ($(this).position().top < 0) {
$(this).stop().fadeTo(100, 0);
} else {
$(this).stop().fadeTo('fast', 1);
}
});
});
http://jsfiddle.net/ys0m6axL/
The reason is that jQuery turns the divs transparent. However the divs are still there, which means their height still counts.
So, in particular for this case, the only thing you need is the subtraction. Using 20 minus the height of divs (which is 100px) and spaces between divs (which is 100px as well), you have 200px in total for each div (and the space around it).
Try the code below, and see if it works.
$("#test").scroll(function () {
$('[id^="box"]').each(function () {
if (($(this).offset().top - $("#test").scrollTop()) < 20 - $(this).index() * 200) {
$(this).stop().fadeTo(100, 0);
} else {
$(this).stop().fadeTo('fast', 1);
}
});
});
Good luck.
Try with using div top instead scrollTop in the calculation.
I have changed the calculation in this line :
if (($(this).offset().top - $("#test").offset().top) < 20) {
JSFIDDLE : http://jsfiddle.net/JdbhV/1697/
$("#test").scroll(function () {
$('[id^="box"]').each(function () {
if (($(this).offset().top - $("#test").offset().top) < 20) {
$(this).stop().fadeTo(100, 0);
} else {
$(this).stop().fadeTo('fast', 1);
}
});
});
Here are the jsfiddle example.
You just need to change the condition
from
$(this).offset().top - $("#test").scrollTop()) < 20
To
$(this).offset().top < $("#test").offset().top
$("#test").offset().top
is the height that determine when to do the fade action.
For now that is the top of the container #test.
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');
}
});
This is a follow-up post to a previous question: jQuery - scroll down every x seconds, then scroll to the top
I have refined the scrip a little further, but am having a little trouble with the last step.
I have a div that automatically 50px at a time until it reaches the bottom, at which point it scrolls to the top and starts again. I have this working perfectly thanks to the above question and with a little add work.
I need to make all scrolling stop when the div is hovered. I have done part of this already (there is no incremental scrolling down on hover) but I cannot get the full picture. The div will still scroll to the top even when hovered.
Here is my jQuery and a fiddle to go along with it: http://jsfiddle.net/wR5FY/1/
var scrollingUp = 0;
var dontScroll = 0;
window.setInterval(scrollit, 3000);
function scrollit() {
if(scrollingUp == 0 && dontScroll == 0) {
$('#scroller').animate({ scrollTop: $("#scroller").scrollTop() + 50 }, 'slow');
}
}
$('#scroller').bind('scroll', function () {
if (dontScroll == 0) {
if ($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
scrollingUp = 1;
$('#scroller').delay(2000).animate({ scrollTop: 0 }, 1000, function() {
scrollingUp = 0;
});
}
}
});
$('#scroller').bind('mouseenter', function() {
dontScroll = 1;
});
$('#scroller').bind('mouseleave', function() {
dontScroll = 0;
});
In the fiddle, try hovering the scroller div when the yellow square is visible. You will see that it scrolls to the top.
A couple of notes:
You will notice I have used mouseenter and mouseleave rather than hover and mouseout. This was the best way I could find to ensure all child elements within the div didn't have an adverse affect.
A potential problem area is the fact that I have binded to the scroll event for my function that scrolls to the top. I think this might cause some additional problems when a user is manually scrolling through the items, with my jQuery trying to scroll against the user.
I did a little experimenting with killing setInterval, but I didn't find this to be very helpful as the function that triggers isn't the problem area.
My overall goal here is to lock down all automatic scrolling when a user is hovering or manually scrolling through the list. This is 90% there. If they happen to scroll to the bottom, NOTHING should happen until they move the mouse elsewhere - this is the problem.
Keep it easier ;)
The problem was that you first evaluate wheter dontScroll is zero, then start the timer.
When the timer has ended, it doesnt evaluate anymore, whether dontScroll STILL is zero.
Just pulled that into your scrollIt function:
var scrollingUp = 0;
var dontScroll = 0;
window.setInterval(scrollit, 2000);
function scrollit() {
if(dontScroll == 0){
if ($('#scroller').scrollTop() + $('#scroller').innerHeight() >= $('#scroller')[0].scrollHeight) {
scrollingUp = 1;
$('#scroller').animate({ scrollTop: 0 }, 1000, function() {
scrollingUp = 0;
});
} else if(scrollingUp == 0) {
$('#scroller').animate({ scrollTop: $("#scroller").scrollTop() + 50 }, 'slow');
}
}
}
$('#scroller').bind('mouseenter', function() {
dontScroll = 1;
});
$('#scroller').bind('mouseleave', function() {
dontScroll = 0;
});
You can view my custom slider here: http://www.awaismuzaffar.com/examples/index.html
And below is the JQuery code for it:
$(document).ready(function() {
// Slider Function
var slideWidth = $('div.slide').width();
// Set the left position of each div element
$('div.slide').each(function(index){
$(this).css('left', index * slideWidth ); // Multiply each div element by the index(0, 1 etc) so each div is placed inline
});
// Next step is to animate the div elements
var clickCount = 1;
var slideCount = $('div.slide').length;
// Set the previous button to hide when loading with the first slide
if(clickCount == 1){
$('a#previous-button').css('background-color', '#cccccc');
}
$('a#next-button').click(function() {
if(clickCount < slideCount) {
$('div.slide').animate({"left":"-=" + slideWidth}, 'slow');
$('a#previous-button').css('background-color', '#ffffff');
clickCount++;
}
if(clickCount == slideCount) {
$('a#next-button').css('background-color', '#cccccc'); // Hide or grey out button
}
});
$('a#previous-button').click(function() {
if(clickCount > 1){
$('div.slide').animate({"left":"+=" + slideWidth}, 'slow');
$('a#next-button').css('background-color', '#ffffff');
clickCount--;
}
if(clickCount == 1){
$('a#previous-button').css('background-color', '#cccccc'); // Hide or grey out button
}
});
});
I am trying to modify this slider to allow continous scrolling.
I am not sure exactly how to achieve this, I am assuming I need to use append, but I am not sure how to make use of it.
Thanks.
You're doing things a little manually, I'm thinking someone else might've solved the problem. But in any case, in your click next button, you'd need to load in additional content when you hit the end. So if I were you, I'd do something like this:
$('a#next-button').click(function() {
...
if(clickCount == slideCount) {
$('a#next-button').css('background-color', '#cccccc');
$.get(moreContentUrl, objectRepresentingCurrentScrollPosition, loadContent);
spinner.show(); // show some kind of spinner here (you can also hook up a default spinner on all ajax events with a global ajax handler
}
});
function loadContent(response) {
// append your content (your controller should return just the <div class="slide" /> elements, and give them a class="slide newSlide" so you can distinguish them below
// you can also do client side templating here. would be more efficient, then just return the items as objects instead of html
$('#slide-container').append(response.itemsHtml);
// slide all new divs right
$('div.newSlide').animate({"left":"+=" + slideWidth}, 'fast');
$('div.newSlide').removeClass('newSlide');
// update variables and un-grey the next button
$('a#previous-button').css('background-color', '#ffffff');
slideCount += response.itemCount;
// hide the spinner shown when starting the load
spinner.hide();
}
Give it a shot, hope it works. Now, to clean up that code a little bit, I'd suggest using css classes instead of inline background colors, etc.
Here's a solution (somewhat like Shaz's), just less code :):
$(document).ready(function(){
$('#previous-button').click(function(){slidePanel(-1)});
$('#next-button').click(function(){slidePanel(1)});
var n = 0;
var animating = false;
$('#slide-'+n).css('display', 'block');
function slidePanel(delta)
{
if(!animating)
{
animating = true;
var d = (delta > 0 ? $('#slide-'+n).width()*-1 : $('#slide-'+n).width());
$('#slide-'+n).animate({
left: "+="+d
}, 'slow', function() { $(this).css('display', 'none'); animating = false; });
n = (n + delta) % $('div.slide').length;
n = n < 0 ? $('div.slide').length + n : n;
$('#slide-'+n).css('left', $('#slide-container').offset().left +(d*-1));
$('#slide-'+n).css('display', 'block');
$('#slide-'+n).animate({
left: 0
}, 'slow');
}
}
});
Check out the sample here.
(I know there's a way to figure out the "current slide" with a one liner equation, but I think I'm brain dead atm :P)
(Edited to account for repeatedly clicking)
Try something like this: http://fiddle.jshell.net/Shaz/dsBkf/
I've made a slide-show with 'li' tags and jquery.
The whole 'ul' moves to the left or right respective to the Next/Prev buttons and has a width equal to the total width of all the slides put together, i.e. 700px each. And only 1 slide is allowed to show in the viewport of width equal to 700px. But when I click next the show goes on even though there's no more slides.
The solution is to hide the Next button when the last slide shows up in the viewport. How do I do that?
Or maybe another solution is welcome...
This is my simplified code:
var slideList = $('#slideWindow ul')
$('#next').click(function(e){
slideList.animate({ 'left': '-=700px' });
if( $('li:last').next() === 0 ){
$(this).hide();
} else {
$(this).show();
}
return false;
});
If there is a particular class classBeingViewed applied to li that is being viewed at the moment, you can just do:
if($('li').last() == $('li.classBeingViewed')){
$(this).hide();
else {
$(this).show();
}
Or you can keep track of the index. This is preferable since it allows animations in both directions.
var slideList = $('#slideWindow ul');
var listIndex = 0;
var numLiElements = $('li').length;
$('#next').click(function(e){
slideList.animate({ 'left': '-=700px' });
if( listIndex == numLiElements ){
$(this).hide();
} else {
listIndex += 1;
$(this).show();
}
return false;
});
Then, you can decrement listIndex in a click handler to $('#previous') when you want to reverse the animation.