Create jQuery infinite loop of items - javascript

I am trying to accomplish an infinite loop of items inside 1 main div.
The idea is to show part of the items, then slide the left one outside of the screen, whilst another is added from the right side of the screen.
The following function is working, but the animate method doesn't work, it just changing the css without animating it.
Am I doing it wrong?
Also any better approach would be welcome. I tried to search jQuery solutions but they didn't work well for me so i wanted to create another one.
jQuery(document).ready(function() {
var items = jQuery('.companies-logos div');
var temp;
var item_width = 0;
if(items.length > 9) {
items.slice(9).remove();
setInterval(function(){
jQuery('.companies-logos').append(items[9]);
items[9].style.marginLeft = '0';
item_width = items[0].offsetWidth + 12.5;
jQuery(items[0]).animate({marginLeft: '-' + item_width + 'px'}, 2000);
// items[0].style.marginLeft = '-' + item_width + 'px';
temp = items[0];
jQuery(items[0]).remove();
items.splice(0, 1);
items.push(temp);
// jQuery(items[items.length-1]).css('transition', 'all 2500ms');
}, 2500);
}
});

For those interested in achieving the wanted result from above:
$(function(){
setInterval(function(){
var item_width = $('.companies-logos ul li:first-child').width() + 25;
$(".companies-logos ul li:first-child").animate({"margin-left": -item_width}, 1500, function(){
$(this).css("margin-left",25).appendTo(".companies-logos ul");
});
}, 2000);
});

Related

function firing multiple times when scrolling fast

First of all, I'm not very advanced at code and tend to only do this part time so please excuse all terrible/ugly code! I appreciate there are already some solutions out there but I can't seem to make any of them work with my code so would really appreciate some help!
I'm using isotope grid and trying to setup an infinite scroll. I want to load 10 images at a time when the user scrolls to the bottom by taking these images from an array and appending them to a temp div.
This is working perfectly when scrolling slowly, but as soon as you scroll quickly the function seems to fire multiple times, it gets a little glitchy and loads lots of images at once.
$(window).scroll(function() {
var scrollTop = $(window).scrollTop();
var windowHeight = $(window).height();
var docuHeight = $(document).height();
if(scrollTop + windowHeight == docuHeight){
nextTenImages = imagesData.splice(0,10);
var content = ""
for (var i = 0; i < nextTenImages.length; i++) {
content +=
"<div class='box " + nextTenImages[i]["type"] + "'" + ">" +
"<div class='box-wrapper'>" +
"<img src='" + nextTenImages[i]["src"] + "' />" +
"</div>" +
"</div>"
};
$('body').append('<div id="temp-load"><div id="grid"></div></div>');
$('#temp-load > #grid').append(content)
$('#temp-load > #grid').children().css({
opacity: 0
});
var toAdd = $('#temp-load > #grid').html();
$container.isotope('insert', $(toAdd), function(){
$container.children().css({
opacity: 1
});
$('#temp-load').remove();
});
}
});
Make a single timeout to run the callback. This may avoid the function from executing multiple times.
var timer;
function scrollEvt() {
/* scroll actions */
}
$(window).scroll(function() {
/* clear the old timeout */
clearTimeout(timer);
/* wait until 400 ms for callback */
timer = setTimeout(scrollEvt, 400);
});
Using other ways may result in problems (like comparing (window.performance || Date).now())...
Unbind that specific scroll event till your delayed operation is completed to prevent accumulating more of the event triggers which create the duplication behaviour as in your case.
var winCached = $(window),
docCached = $(document)
var currLeng = 0;
function addContent() {
dettachScrollEvent();
setTimeout(function() { //this timeout simulates the delay from the ajax post
for (var i = currLeng; i < currLeng + 100; i++)
$('div').append(i + '<br />');
currLeng = i;
console.log("called loader!");
attachScrollEvent();
}, 500);
}
function infiNLoader() {
if (winCached.scrollTop() + winCached.height() > docCached.height() - 300) {
addContent();
//alert("near bottom! Adding more dummy content for infinite scrolling");
}
}
function attachScrollEvent() {
winCached.scroll(infiNLoader);
}
function dettachScrollEvent() {
winCached.unbind('scroll', infiNLoader);
}
addContent();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>

Javascript slider function - How to objectify the selectors?

I'm currently working on a project where a custom slider was needed and i quickly grabbed a neat looking tutorial of the web and went away and staticly it all works great.
Now i want to be able to put several sliders on my page and therefore need to add the controls dynamicly rather than just selecting a certain slider with jquery like I've done below.
This is my code with comments added to explain what im trying to achieve:
var Slider = function() { this.initialize.apply(this, arguments) };
Slider.prototype = {
initialize: function(slider) {
this.ul = slider.children[2];
this.li = this.ul.children;
this.nav = slider.children[3]; //Why cant i use .append on this element?
// make <ul> as large as all <li>’s
this.ul.style.width = (100 * this.li.length) + '%';
// set width of the li's
for(i = 0; i < this.li.length; i++) {
this.li[i].style.width = (100 / this.li.length) + '%';
$(".slider-nav").append( '<div class="slider-dot"></div>'); //Want to make it a this.nav or something similar instead of an external selector
//console.log(this.nav);
}
this.currentIndex = 0;
},
goTo: function(index) {
if (index < 0 || index > this.li.length - 1)
return;
// move <ul> left
this.ul.style.left = '-' + (100 * index) + '%';
this.currentIndex = index
},
goToPrev: function() {
this.goTo(this.currentIndex - 1)
},
goToNext: function() {
this.goTo(this.currentIndex + 1)
}}
var sliders = [];
$('.slider').each(function() {
sliders.push(new Slider(this));
});
//Find a way to implement theese 2 within the slider function, how to find out what position in the array a slider has?
$(".prev-btn").click(function() {
sliders[0].goToPrev();
});
$(".next-btn").click(function() {
sliders[0].goToNext();});
The marks up for the slider looks like this: http://puu.sh/hAUH1/a865792137.png
I managed to get it done by defining this as another var
var sliderEle = this;
I could then call it like this:
$(this.prev).click(function(e) {
e.preventDefault();
sliderEle.goToPrev();
});
with prev and next defined like this:
this.prev = slider.children[0];
this.next = slider.children[1];

Syntax or logical error in jquery/javascript

I have a variable number of promotional items (panels) that are in a sliding belt, that should be set to the width of a panel (300px) multiplied with the amount of panels.
It alerts the correct beltsize. With fixed numbers the slider works too. I suspect the error to be in the if/else if part. I am not even sure this is valid Javascript Syntax.
Any hint is appreciated.
$(window).ready(function(){
var whichpanel = 1;
var panels = $(".panel").length;
var beltsize = panels*300;
$('.belt').css({'width':beltsize});
});
$(window).ready(function promoslider(){
if (panels>whichpanel){
$('.belt').delay(7000).animate({'left':'-=300'}, 500);
whichpanel += 1;
}
else if (panels=whichpanel){
$('.belt').delay(7000).animate({'left':'0'}, 500);
whichpanel = 1;
}
setTimeout(promoslider, 0);
});
promoslider;
UPDATE! Here is the code that works for me now (http://jsfiddle.net/zr5Nd/10/):
$(window).ready(function () {
var whichpanel = 1;
var panels = $(".panel").length;
var beltsize = panels * 300;
$('.belt').css({
'width': beltsize
});
function movingdiv() {
if (panels > whichpanel) {
//alert('Panels:' + panels + '/whichpanel:' + whichpanel);
$('.belt').delay(1000).animate({
'margin-left': '-=300px'
}, 500);
whichpanel += 1;
} else if (panels == whichpanel) {
//alert('Panels:' + panels + '/whichpanel:' + whichpanel);
$('.belt').delay(1000).animate({
'margin-left': '0'
}, 500*panels);
whichpanel = 1;
} else {
alert('3');
}
setTimeout(movingdiv, 0);
}
setTimeout(movingdiv, 0);
});
You need to use the equality/identity operators (==/===) instead of the assignment operator = in your else if statement, e.g.
else if (panels == whichpanel){
$('.belt').delay(7000).animate({'left':'0'}, 500);
whichpanel = 1;
}
Also, I believe promoslider; is supposed to be promoslider();.
You should put the call of promoslider into $(window).ready as well, as the function does not yet exist otherwise. Plus you have to do the call this way promoslider(), promoslider alone will not result in a call.
And of course you have to use the equals-operator == instead of the assign-operator = in your if else-statement.
use panels === whichpanel instead of panels=whichpanel
variables whichpanel, panels have lost their scope in the if/else if part.

.next() not working as intended

So,
if($(this).hasClass('active')){
$(this).removeClass('active');
$(this).prev().addClass('active');
}
works fine, it adds the class "active" to this previous div of the same kind.
if($(this).hasClass('active')){
$(this).removeClass('active');
$(this).next().addClass('active');
}
However, adds the class to the next div (as i intend for it to do) for about 0.5 of a second BUT then removes it.
Here's ALL of the jQuery (as per your comments below) - Please do not comment on my horrible code organization
$(window).load(function () {
// Initial variables
var numberSlides = 0;
var currentSlide = 1;
var ready = true;
var pageWidthR = $(document).width() - 352;
var pageWidthL = $(document).width() - 352;
// Update number of slides by number of .slide elements
$('#features-slider .slide').each(function () {
numberSlides++;
});
// Go through each slide and move it to the left of the screen
var i = 0;
$($('#features-slider .slide').get().reverse()).each(function () {
if (i == 0) {
} else {
var newWidth = i * 115;
$(this).css('left', '-' + newWidth + '%');
}
i++;
});
// Animate the first slide in
$('#features-slider .slide:last-child').addClass('active').animate({
left: 0
}, 1500);
// Remove the loading message
$('#loading').fadeOut(1000, function () {
$('#loading').remove();
// Now that we're done - we can show it
$('#features-slider').show();
});
/***** Left and Right buttons *****/
/* Right */
$('#rightbutton').click(function () {
var numberSlides = 0;
$('#features-slider .slide').each(function () {
numberSlides++;
});
var index = $('.slide.active').index() + 1;
if (!$('.slide').is(':animated') && index != 1) {
$('#features-slider .slide').each(function () {
if ($(this).hasClass('active')) {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft) + 115;
} else {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft) + 115;
}
$(this).animate({
left: newLeft + '%'
}, 1500);
if ($(this).hasClass('active')) {
$(this).removeClass('active');
$(this).prev().addClass('active');
}
});
}
});
/* Left */
$('#leftbutton').click(function () {
var numberSlides = 0;
$('#features-slider .slide').each(function () {
numberSlides++;
});
var index = $('.slide.active').index() + 1;
if (!$('.slide').is(':animated') && index != numberSlides) {
$('#features-slider .slide').each(function () {
if ($(this).hasClass('active')) {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft) - 115;
} else {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft) - 115;
}
$(this).animate({
left: newLeft + '%'
}, 1500);
if ($(this).hasClass('active')) {
$(this).next().addClass('active');
$(this).removeClass('active').not($(this).next());
}
});
}
});
});
$(document).ready(function () {
// Hide the slider and show a loading message while we do stuff and the images / DOM loads - Also disable overflow on the body so no horizontal scrollbar is shown
$('body').css('overflow-x', 'hidden');
$('#features-slider').hide();
$('#loading').html('<center> <img id="loader" src="/wp-content/themes/responsive/library/images/ajax-loader.gif" /> Loading</center>');
});
RESOLVED
New left button function :
$('#leftbutton').click(function(){
var numberSlides = 0;
$('#features-slider .slide').each(function(){
numberSlides++;
});
var index = $('.slide.active').index()+1;
if( !$('.slide').is(':animated') && index != numberSlides ){
var done = false;
$('#features-slider .slide').each(function(){
if($(this).hasClass('active')){
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft)-115;
} else {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft)-115;
}
$(this).animate({left: newLeft+'%'}, 1500);
if($(this).hasClass('active') && done == false){
$(this).next().addClass('active');
$(this).removeClass('active');
done = true;
}
});
});
If you're iterating forward through the elements, then it should be clear what's going on - you add the "active" class to the next element, and then the next iteration takes it away.
This is just a guess however as you did not post enough code for me (or anybody else) to be sure.
edit — ok now that you've updated the question, it's clear that the guess was correct. The .each() function will iterate forward through the elements. When an element has the "active" class, and the code removes it and adds it to the next element, then on the next iteration the work is undone.
Since you are referencing this and by the behavior you're describing, you are likely iterating a loop for a list of elements. As a result, you are completing the action you want but the next iteration is removing the previous changes due to your usage of removing a class and then adding the class back.
As it stands now, your code does not illustrate how this occurence can be happening.
Update:
As suspected, you seem to be looping as signified by: each(function(){. While iterating through your objects the class is being pushed forward and is not acting as desired. You are stating add the class to the next element, but remove it from the current element, and this behavior continues through your iteration.
On a side note, update your code to call removeClass() on the current object first, before adding it to the next object:
if ($(this).hasClass('active')) {
$(this).removeClass('active').next().addClass('active');
}

changing background image with a for loop

i have a table with 3 cells the middel 1 in a black image so it will look like there is a line in the middle of the screen.
now in the other cell i want to show pictures, so i tryed to do a loop that changing the images every second with by hiding the cells and then show them.
the script:
$(window).ready(function () {
//the images sits in a div with a hidden property.
var AlumniumPictures = $("#AlumnimPictureHolder").children();
var ShipozimPictures = $("#ShipozimPictureHolder").children();
//var timer = $.timer(yourfunction, 10000);
for (var i = 0; i < 10; i++) {
$(".almoniyomButtonTD").css({
"background-image": "url(" + $(AlumniumPictures[i]).attr('src') + ")"
});
$(".shipozimButtonTD").css({
"background-image": "url(" + $(ShipozimPictures[i]).attr('src') + ")"
});
$(".almoniyomButtonTD").hide();
$(".shipozimButtonTD").hide();
$(".almoniyomButtonTD").show(1100);
$(".shipozimButtonTD").show(1100);
//for some reson the code dosnt work if im not using the setInterval method.
document.setInterval(1000);
}
});
this is not working it only show me the first images and then stop.
is there a batter way to do this?
am im doing this right?
I think you might do this for the background:
$(window).ready(function () {
//the images sits in a div with a hidden property.
var AlumniumPictures = $("#AlumnimPictureHolder").children();
var ShipozimPictures = $("#ShipozimPictureHolder").children();
//var timer = $.timer(yourfunction, 10000);
time = 0;
step = 1000; // One secund
for (var i = 0; i < 10; i++) {
time+= step;
$(".almoniyomButtonTD").hide();
$(".shipozimButtonTD").hide();
$(".almoniyomButtonTD").show(1100);
$(".shipozimButtonTD").show(1100);
//for some reson the code dosnt work if im not using the setInterval method.
document.setInterval("changeBG('" + $(AlumniumPictures[i]).attr('src') + "', '.almoniyomButtonTD')", time);
document.setInterval("changeBG('" + $(AlumniumPictures[i]).attr('src') + "', '.shipozimButtonTD')", time);
}
});
function changeBG(image, obj) {
$(obj).css({
"background-image": "url(" + image + ")"
});
}
But I don't undestand what you want to do with this:
$(".almoniyomButtonTD").hide();
$(".shipozimButtonTD").hide();
$(".almoniyomButtonTD").show(1100);
$(".shipozimButtonTD").show(1100);
See the docs about setInterval. You need to tell it what code you are running.
window.setInterval(code, delay);
You aren't specifying any code for it to run! Try placing your for statement in a function and calling that.
Also, from Mozilla and MS docs setInterval seems to be on the window object, not on the document object. I don't think it will work the way you have it. I imagine if you looked in a debugger you would see an error thrown.
window.setInterval(myFunction, 1000);
function myFunction() {
for (var i = 0; i < 10; i++) {
$(".almoniyomButtonTD").css({
"background-image": "url(" + $(AlumniumPictures[i]).attr('src') + ")"
});
$(".shipozimButtonTD").css({
"background-image": "url(" + $(ShipozimPictures[i]).attr('src') + ")"
});
$(".almoniyomButtonTD").hide();
$(".shipozimButtonTD").hide();
$(".almoniyomButtonTD").show(1100);
$(".shipozimButtonTD").show(1100);
}
}

Categories