I've been searching everywhere for this and can't seem to find an anwser that works. What i have is a slider with arrows and buttons, when an arrow or button is clicked the function grabs the data-cs attribute which it uses to to determine the next slide.
the html
<div id="arrowleft" class="sliderbtns flip" data-sc="prev"></div>
<div id="arrowright" class="sliderbtns" data-sc="next"></div>
<div id="buttons" class="sliderbtns">
<div class="selectedbtn sliderbtns" id="button1" data-sc="1"></div>
<div class="button sliderbtns" data-sc="2"></div>
</div>
the javascript
$( ".sliderbtns" ).click(function() {
var button_data = $(this).attr('data-sc');
myslider(button_data);
});
the function in js
function myslider(position) {
if (position == "next" && (currentslide == slidecount)) {
position = 1;
} else if (position == "next") {
position = currentslide + 1;
} else if ((position == "prev") && (currentslide == 1)){
position = slidecount;
} else if ((position == "prev")) {
position = position - 1;
} else {
// position must then eqauls some integer from the data-sc attribute
position = parseInt(position);
alert (position); // alerts properly the first time
var out_slide = "Slide" + currentslide + "Out";
var next_slide = "Slide" + position;
alert(out_slide); //these work fine the first time
alert(next_slide);
window[next_slide]();
window[out_slide]();
// later on in the slide currentslide becomes position after this it returns value of Nan
setTimeout( function() {
currentslide = position;
alert("this is the current slide position" + currentslide);
}, 2000);
/* ommited code */
}
}
The arrows work fine if I just click on the arrows but when I click on a button it proprly goes to the next slide but none of the buttons no longer work and display current position as NaN, I have tried making the position variable an int in a bunch of different ways with Number(position), ToInt and ParseInt, but still after currentslide = position it returns it as Nan and the slider can no longer find the proper slides and functions etc... If any one has any idea what I could be doing wrong, how to properly make sure it's an actuall integer if that's posssible from a data attribute, or maybe some other way around I can throw that data around as and int that could be gotten by clicking the arrows or buttons. Greatly appreciate any help!
To get data use .data():
$(this).data('sc')
Seems nobody reading the question.
NaN should appear due to this:
position = currentslide + 1;
From code, I cannot see currentslide being intialized. If you do undefined + 1, you get NaN.
Globally, set currentSlide = 0 to have it work properly. Unless you're hiding code.
ps. title does not match the question posed in the description.
Related
The general idea to the site i am designing is to scroll through a set of menu items horizontally and incrementally underneath a static div that will magnify(increase dimensions and pt size) the contents of a menu items. I don't really need help with the magnify portion because i think it's as simple as adding a mag class to any of the menuItem divs that go underneath the static div. I have been messing with this for a few weeks and the code I have for incrementally scrolling, so far, is this:
$(document).ready(function () {
currentScrollPos = $('#scrollableDiv').scrollTop(120); //sets default scroll pos
/*The incrementScroll function is passed arguments currentScrollPos and UserScroll which are variables that i have initiated earlier in the program, and then initiates a for loop.
-The first statement sets up the variables: nextScrollPos as equal to the currentScrollPos(which by default is 120px) plus 240px(the distance to next menuItem), prevScrollPos as equal to the currentScrollPos(which by default is 120px) minus 240px(the distance to next menuItem).
-The second Statement checks to see if the user has scrolled using var userScroll
-The third statement sets: var CurrentScroll equal to the new scroll position and var userScroll to false*/
function incrementScroll(currentScrollPos, userScroll) {
for (var nextScrollPos = parseInt(currentScrollPos + 240, 10),
prevScrollPos = parseInt(currentScrollPos - 240, 10); //end first statement
userScroll == 'true'; console.log('dude'), //end second statement and begining of third
currentScrollPos = scrollTop(), userScroll = 'false') {
if (scrollTop() < currentScrollPos) {
$('#scrollableDiv').animate({
scrollTop: (parseInt(prevScrollPos, 10))
}, 200);
console.log('scrolln up')
} else if (scrollTop() > currentScrollPos) {
$('#scrollableDiv').animate({
scrollTop: (parseInt(nextScrollPos, 10))
}, 200);
console.log('scrolln down')//fire when
}
}
}
$('#scrollableDiv').scroll(function () {
userScroll = 'true';
_.debounce(incrementScroll, 200); //controls the amount of times the incrementScroll function is called
console.log('straight scrolln')
});
});
I have found a variety of solutions that are nigh close: such as a plugin that snaps to the next or previous div horizontally demo, another solution that also snaps and is based on setTimeout demo, but nothing that nails incrementally scrolling through divs. I also found a way to control the rate at which a user may scroll through the menuItems using debounce which is included in the above code.
The console.logs inside the loop do not fire when I demo the code in jsfiddle which leads me to believe the problem lies within the loop. I'm a noob though so it could be in syntax or anywhere else in the code for that matter. Also in the second demo, i have provided the css for the horizontal static div, but the moment I put it in my html it keeps the js from working.
I would like to write the code instead of using a plugin and any help would be appreciated! Also, thank you ahead of time!
Try this fiddle. Menu container height is 960px to show 4 menu items. "Zoom" div is positioned absolutely at top. When you scroll mouse over this div, menu items shifts to top/bottom. I had to add additional div to bottom to be able to scroll to last 3 menu items. JS code:
jQuery(document).ready(function($){
var current = 0;
var menu = $('.menu-container').scrollTop(0);
var items = menu.find('.menu-item');
var zoom = $('.zoom');
function isVerticalScroll(event){
var e = event.originalEvent;
if (e.axis && e.axis === e.HORIZONTAL_AXIS)
return false;
if (e.wheelDeltaX)
return false;
return true;
}
function handleMouseScroll(event){
if(isVerticalScroll(event)){
var delta = event.originalEvent.wheelDelta * -1 || event.originalEvent.detail;
current += (delta > 0 ? 1 : -1);
if(current < 0)
current = 0;
if(current >= items.length){
current = items.length - 1;
}
menu.stop().animate({
"scrollTop": current * 240
}, 300);
items.removeClass('current').eq(current).addClass('current');
event && event.preventDefault();
return false;
}
}
zoom.on({
"MozMousePixelScroll": handleMouseScroll,
"mousewheel": handleMouseScroll
});
});
Hope it will help.
My carousel has been built so that it slides to the next frame automatically every 5 seconds, for which I have written:
var carousel = $('.carousel ul:first');
var pagination = $('.carousel ul:last');
function slide01() {
carousel.delay(5000).animate({'margin-left':'-100%'}, function() {
pagination.find('li').removeClass('on');
pagination.find(':nth-child(2)').addClass('on');
});
slide02();
};
function slide02() {
carousel.delay(5000).animate({'margin-left':'-200%'}, function() {
pagination.find('li').removeClass('on');
pagination.find(':nth-child(3)').addClass('on');
});
slide03();
};
function slide03() {
carousel.delay(5000).animate({'margin-left':'-300%'}, function() {
pagination.find('li').removeClass('on');
pagination.find(':nth-child(4)').addClass('on');
});
slide04();
};
function slide04() {
carousel.delay(5000).animate({'margin-left':'0%'}, function() {
pagination.find('li').removeClass('on');
pagination.find(':nth-child(1)').addClass('on');
});
slide01();
};
slide01();
While this is working, I'm having difficulties with the pagination buttons. They respond but instead of going to its appropriate page, it's going to the next page, which you can view in my FIDDLE.
This is the code I have written for each button:
pagination.find('li:nth-child(1)').click(function(){
carousel.stop().animate({'margin-left':'0%'});
});
pagination.find('li:nth-child(2)').click(function(){
carousel.stop().animate({'margin-left':'100%'});
});
pagination.find('li:nth-child(3)').click(function(){
carousel.stop().animate({'margin-left':'200%'});
});
pagination.find('li:nth-child(4)').click(function(){
carousel.stop().animate({'margin-left':'300%'});
});
What can I do to fix this?
I have updated your Javascript code to provide your desired functionality and made it more extendable. Please let me know if you have any questions.
var carousel = $('.carousel ul:first');
var pagination = $('.carousel ul:last');
var slideWidth = 200;
var autoSlideTiming = 5000;
var timeout = null;
// Buttons
$.each(pagination.children(), function(i){
$(this).click(function(){
pagination.find('li.on').removeClass('on');
//if you wanted to find the width dynamically
//var slideWidth = $(this).parent().parent().find('ul:eq(0) li:eq('+i+')').width();
carousel.stop().animate({'margin-left': -(i * slideWidth)});
$(this).addClass('on');
});
});
// Slider
function advanceSlide(){
var currIndex = $(".pagination li.on").index();
var nextIndex = ((pagination.children().length - 1) == currIndex) ? 0 : (currIndex + 1);
carousel.animate({'margin-left': -(nextIndex * slideWidth)}, function() {
pagination.find('li.on').removeClass('on');
pagination.find(':nth-child('+(nextIndex + 1)+')').addClass('on');
timeout = setTimeout(function(){advanceSlide()}, autoSlideTiming);
});
}
$('.carousel').hover(function(){
clearTimeout(timeout);
}, function(){
timeout = setTimeout(function(){advanceSlide()}, autoSlideTiming);
});
//init auto slide
timeout = setTimeout(function(){advanceSlide()}, autoSlideTiming);
Also here is an updated Fiddle
Explanation
The $.each is a jQuery utility function that works like a normal for loop (I would actually recommend a vanilla JavaScript for loop if you know how). This $.each accepts 2 arguments: a collection (pagination.children() in our case, which is an array of the li's), and a callback function. This callback function passes in i which is our zero-based index of the collection. So, it's not 1, 2, 3, 4 but 0, 1, 2, 3. In this loop this is each li, which it is attaching a click event that handles removing and applying your on class and also the animation. The -(i * slideWidth) is taking the current zero-based index and multiplying it times the slideWidth and then getting the negative value of that result. So, the first slide -(0 * 200) would animate the margin-left to -0 or 0, and the second slide -(1 * 200) would animate the margin-left to -200, which pulls it 200 pixels in the left direction making it slide. This will allow you to had new li's to your pagination and this code will still work!
The trick to making the advanceSlide() function dynamic, is finding what the index of the next slide is. To find out where we need to go we first must find where we are. That is what currIndex is for, which we find with the jQuery index() function, which returns the zero-based index of the li with the on class. Now the magic. The nextIndex variable is being set using a ternary operator to find the value. A ternary is just programmer shorthand for a basic if then else statement. So if the ternary in this code was written out the normal way it would look like this:
var nextIndex;
if( (pagination.children().length - 1) == currIndex ){
nextIndex = 0;
}else{
nextIndex = currIndex + 1;
}
Remeber our currIndex is zero-based, but our collection (pagination.children()) length (number of items in the total collection) is not zero-based so we must minus 1 from it. Then we are checking if that value is equal to our currIndex because if this is the last item in our collection we need to set our nextIndex back to 0 so the slideshow loops back around. If it's not the last index we just add 1 to advance to the next slide. After we find that nextIndex we do our animation and apply our class.
I know this is a little long winded, but it's important that you fully understand the code you implement! Please let me know if you have nay further questions!
You have a "Maximum call stack size exceeded." error. Yours slide0X function calls another slide0Y function and so on. You should invoke slide0Y only once the slide0X animation ended (inside the complete callback).
Moreover in your click callbacks, margin-left should be negative since you want to slide to the left.
BTW, I would implement a function slideTo(slideId) so that it will work for n slides, instead of writing a function for each slide.
I am working on a circular image carousel in Javascript.
It needs to be circular in the sense that, if the 0 position slide is currently selected and "Previous" is pressed, it will jump to the last position slide. If the last position slide is currently selected and "Next" is pressed, it will jump to the 0 position slide.
Another program handles the overall slide, but I can:
Detect current position after shift with slide.current - the first position is 0
Detect the total number of slides (does not change until page reload) with slide.items.length
Fire my own nextSlide and previousSlide functions after the slide program completes its own complementary functions
Manually change the currently selected slide and pointer position using slideTo() in the slide API
Know automatically that the first visible slide, after page load, is the total number of items (3 to n) divided by 2, rounded up
Here's what I have:
var currentSlide = slide.current;
var lastSlide = 'undefined';
function nextSlide(){
currentSlide = slide.current;
if(lastSlide == 'undefined'){
lastSlide = currentSlide - 1;
} else if (lastSlide == 0) {
lastSlide = currentSlide;
} else{
lastSlide = lastSlide + 1;
}
if (lastSlide == currentSlide) {
slide.activate(0);
}
}
function previousSlide(){
currentSlide = slide.current;
if(lastSlide == 'undefined'){
lastSlide = currentSlide + 1;
} else if (lastSlide == slide.items.length - 1) {
lastSlide = currentSlide;
} else{
lastSlide = lastSlide - 1;
}
if (lastSlide == currentSlide) {
slide.activate(sly.items.length - 1);
}
}
This fails when you mix previousSlide calls and nextSlide calls. The lastSlide variable becomes incorrect.
There's no need to declare lastSlide's value to be "undefined". If you declare a variable without assigning any value, it becomes undefined by default.
Given that slide acts as an object, it would make more sense for nextSlide and previousSlide acting as methods instead of stand alone functions.
lastSlide value should depend on the value of currentSlide.
Strict comparison operators should be used to avoid type jumbling in the future. (=== instead of ==)
I'm testing out a layout on a website using 3 pictures here:
Schechterbusiness.info
the left button works, making it go through the pictures. But I can't figure out how to get the right button to work, which is supposed to scroll through the other way. I know there's probably a way to do it with arrays but I can't wrap my brain around it. Halp!
Code to scroll through pictures:
$('#fryLink').click(function() {
$('#hide').hide();
$('#img').hide();
count++;
if(count == 1) {
$('#img').attr("src","images/fry.png");
}
else if(count == 2) {
$('#img').attr("src","images/bender.png");
}
else if(count == 3) {
$('#img').attr("src","images/zoidberg.png");
}
$('#img').show("fade");
if(count > 2) {
count = 0;
}
normally it should be enough to just use use the same function the other way around with
count--;
following the first answere
Bind event to right mouse click
reverse the counter ;)
You have count cycling through four states: 0, 1, 2, and 3. But you only set the image for states 1 - 3.
This leads to duplicating one image--whichever was the last one--when your count variable is on 0.
As to helping you get exactly what you want, unfortunately that is not really clear. Are the three buttons supposed to be a sort of "forward / something / reverse"? What do you want to happen when the center button is clicked on?
Also, making the buttons display the proper pointer/hand icon is important. Right now they show the text selection bar instead, and that makes it confusing since it conveys to the user that the items are not clickable.
Try this
var count = 0;
var imgLength = 3;
$('#leftLink , #rightLink').click(function() {
$('#hide').hide();
$('#img').hide();
if (this.id === 'leftLink') {
count--;
if (count < 0) {
count = imgLength-1;
}
}
else {
count++;
if (count > imgLength-1) {
count = 0;
}
}
var src = "images/fry.png";
if (count == 1) {
src = "images/bender.png";
}
else if (count == 2) {
src = "images/zoidberg.png";
}
$('#img').attr('src',src).show("fade");
});
Script: jQuery Cycle slider: http://jquery.malsup.com/cycle/
I'm using the following code to move my slider thumbnails container to the left by "130px" just before the next slide comes into view. The margin is then reset to "0px" when the last slide is reached. This works well, however the container does not shift until the third slide.
This is the code I'm using:
function onBefore(currElement, nextElement, opts, isFoward) {
var currentslide = opts.currSlide + 1;
if(currentslide == opts.slideCount) {
jQuery(".slider-nav").animate({marginLeft: '0'});
} else if(currentslide > 1 && currentslide != opts.slideCount) {
jQuery(".slider-nav").animate({marginLeft: '-=133'});
}
}
How can I have it shift once the second slide comes into view. Note: Replacing "> 1" in the code above with "> 0" shifts the container as soon as the page loads.
I'm not sure of the context in which this function is called. But I think you want the following code:
function onBefore(currElement, nextElement, opts, isFoward) {
if(opts.currSlide == opts.slideCount) {
jQuery(".slider-nav").animate({marginLeft: '0'});
} else {
jQuery(".slider-nav").animate({marginLeft: '-=133'});
}
}
If that doesn't work it may be because your first slide is (slideCount = 0) instead of (slideCount = 1). If so change the IF test to:
if(opts.currSlide == (opts.slideCount - 1)) {
Regards
Neil