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.
Related
I'm trying to change one image at a time when I'm scrolling through the page.
This code actually changes all images classes when we get to that point of the scroll.
Is there any other way we can change images individually when scrolling?
Thank you.
jQuery(function($) {
var show = $(".show");
var hide = $(".hide");
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if($(window).scrollTop() >= 500){
show.removeClass('show').addClass("hide");
hide.removeClass('hide').addClass("show");
} else {
show.removeClass("hide").addClass('show');
hide.removeClass('show').addClass("hide");
}
});
});
Since you're checking the scroll position of window and hiding/showing, this will hide/show all elements with the specified class name.
To achieve your purpose, add css position: relative to all images (if no position is specified already),
Then, iterate through each image as follows...
jQuery(function($) {
//var show = $(".show");
//var hide = $(".hide");
$(window).scroll(function() {
/*var scroll = $(window).scrollTop();
if($(window).scrollTop() >= 500){
show.removeClass('show').addClass("hide");
hide.removeClass('hide').addClass("show");
} else {
show.removeClass("hide").addClass('show');
hide.removeClass('show').addClass("hide");
}*/
var images = $('img');//or any other selector
$.each(images, function () {
if($(this).offset().top <= -500) {
$(this).hide();
}
else {
$(this).show();
}
});
});
});
In the javascript below the following line should find the height of the dropdown-container element in it's slideDown() / visible state. However, it appears to be doing the opposite when the button is clicked and the dropdown expands the height returned is 1 (I have tested this by uncommenting the line at the end of the function). When the button is clicked again to collapse the dropdown the height is, for example, 681. Why is this the case and is there any way to assess the expanded height correctly within this function when the button is clicked to expand the dropdown container please?
$(this).next(".dropdown-container").css("height")
Here is the javascript in full:
$(document).ready(function () {
var dropdown = $(".dropdown-btn");
var i;
for (i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener("click", function () {
$(".dropdown-btn").not(this).removeClass("active");
$(".dropdown-container").slideUp();
$(this).toggleClass("active");
if ($(this).hasClass("active")) {
$(this).next(".dropdown-container").slideDown();
if (Modernizr.mq('(max-height: 750px)') || $(this).next(".dropdown-container").css("height").replace(/px/, "") > ($(document).height() - 132 - 176)) {
$(".dropdown-btn").not(this).slideUp();
}
}
else {
$(".dropdown-btn").not(this).slideDown();
}
//$('a').text($(this).next(".dropdown-container").css("height").replace(/px/, ""));
});
As per the comments above, the height needed to be assessed within the callback function, which is the second option in the slideDown method. As the code was moved the this logic also needed to be updated to be relative to the container instead of the button. Below is the code that was updated:
if ($(this).hasClass("active")) {
$(this).next(".dropdown-container").slideDown("slow", function() {
// Animation complete.
if (Modernizr.mq('(max-height: 750px)') || $(this).css("height").replace(/px/, "") > ($(document).height() - 132 - 176)) {
$(".dropdown-btn").not($(this).prev(".dropdown-btn")).slideUp();
}
});
}
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);
}
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/