// .items direct child
var itemsContainer = $('.blog-ticker').children();
// each item in .items
var items = $('.blog-ticker').children().children();
setInterval(function(){
var i = 0;
itemsContainer.css({
'top': -(items[i].clientHeight)+'px'
});
if(i <= items.length) {
i++;
}
}, 2000);
it stops after the first round... confusion sets in. What Should I do?
No it probably doesn't stop after the first round.
The problem is that you are declaring i to 0 each time the function runs, so you are just setting the first item to the same position and it appears to be doing nothing.
You just need to declare i outside of the function and it should work fine:
// .items direct child
var itemsContainer = $('.blog-ticker').children();
// each item in .items
var items = $('.blog-ticker').children().children();
// counter
var i = 0;
setInterval(function(){
itemsContainer.css({
'top': -(items[i].clientHeight)+'px'
});
if(i <= items.length) {
i++;
}
}, 2000);
Related
Why am I required to click twice in order to change the classes after 'reseting'? How can I fix this issue?
The desired result is to bring the function back to the initial state and cycle through the arrays normally. Demo below.
$(function () {
var weights = ["jHairline", "jThin", "jLight", "jMedium"];
var currentIndex = 0;
$('#text').on('click', function (e) {
$("h1").removeClass().addClass(weights[currentIndex]);
$("h1").html(weights[currentIndex]);
if (currentIndex == weights.length - 1)
currentIndex = 0;
else
currentIndex++;
e.preventDefault();
});
$('#reset').click(function () {
currentIndex = 0;
$("h1").removeClass().addClass(weights[currentIndex]);
$("h1").html(weights[currentIndex]);
});
});
Demo
Because you reset it to 0 and don't increment it on the next update.
The quick fix would be
$('#reset').click(function() {
currentIndex = 0;
$("h1").removeClass().addClass(weights[currentIndex]);
$("h1").html(weights[currentIndex]);
currentIndex=1;
});
The proper way would be to do the incrementing at the beginning of the $('#text').on('click', function(e) { function
--Edit for clarification request--
This is how I would personally recommend writing it:
$(function () {
var weights = ["jHairline", "jThin", "jLight", "jMedium"];
var currentIndex = -1;
$('#text').on('click', function (e) {
currentIndex=(currentIndex+1)%weights.length;
$("h1").removeClass().addClass(weights[currentIndex]);
$("h1").html(weights[currentIndex]);
e.preventDefault();
});
$('#reset').click(function () {
currentIndex = 0;
$("h1").removeClass().addClass(weights[currentIndex]);
$("h1").html(weights[currentIndex]);
});
});
The 2 lines I added/modified were var currentIndex = -1; and currentIndex=(currentIndex+1)%weights.length; .
So essentially, you are incrementing the number by 1 when the text.click function starts. If you start it at -1 at the beginning, then when text.click enters, it will increment it to 0. And setting it to 0 in reset will make sure it increments to 1 next time text.click is ran.
Further,
if (currentIndex == weights.length - 1)
currentIndex = 0;
else
currentIndex++;
is a bit more concise and clear when written as currentIndex=(currentIndex+1)%weights.length; . It is adding 1 to the number, and then modding (taking the remainder when dividing) to loop it back around to 0 once weight.length is hit.
I don't know what's wrong with my code. I cannot pass a function in my javascript, [i don't want to put it inline]
My problem is my prev button and next button doesn't work, I also tried to put return false on prev and next to stop refreshing the page, but it still refreshing on click.
This is my code [please also see my comments] and my codepen:
$(document).ready(function slider() {
$('#img1').show('fade', 500);
$('#img1').delay(5000).hide("slide", { direction: 'left' }, 500);
});
var count = 2;
setInterval(function loop() {
var all = document.getElementsByTagName('li').length; // <-- i got the li elements so i did the same to prev and next
$('#img' + count).show('slide', { direction: 'right' }, 500);
$('#img' + count).delay(5500).hide('slide', { direction: 'left' }, 500);
if (count === all) {
count = 1;
} else {
count += 1;
}
}, 6500);
var sliderInt = 1;
var sliderNext = 2;
document.getElementsByClassName('prev').onclick = function prev() { // <-- not working
console.log('clicked prev');
var newSlide = sliderInt - 1;
showSlide(newSlide);
return false;
}
document.getElementsByClassName('next').onclick = function next() { // <-- not working
console.log('clicked next');
var newSlide = sliderInt + 1;
showSlide(newSlide);
return false;
}
function stopLoop() {
window.clearInterval(loop());
}
function showSlide(id) { // <-- this function doesn't work from prev and next
stopLoop(); // <-- I want to stop the loop() function when prev and next is clicked
if (id > count) {
id = 1;
} else if (id < 1) {
id = count;
}
$('li').hide('slide', { direction: 'left' }, 500);
$('#img' + id).show('slide', { direction: 'right' }, 500);
sliderInt = id;
sliderNext = id + 1;
window.slider(); // <-- I want to call the function slider here
}
a fix demo will be much appreciated :)
When you use the document.getElementsByClassName('prev').onclick you got an array. Use it like below
document.getElementsByClassName('prev')[0].onclick
document.getElementsByClassName('next')[0].onclick
getElementsByClassName returns a HTMLCollection. So you need to pass the relevant index to which you want to add the onclick function
document.getElementsByClassName('next')[0]
But this will attach the event only on the first element in the collection.
An more relevant example is
var list = document.getElementsByClassName('next or prev');
for (var i = 0, len = list.length; i < len; i++) {
(function(i){ // creating closure
list[i].addEventListener('click',function(){
// code you want to execute on click of next or prev
}
}(i))
}
As you are already using jquery you can avoid all this if you use class selector
$('.next or .prev').on('click',function(event){
// relevant code
})
function slideShow() {
var pageSplash = document.getElementById('splash');
var image = ["pic1.jpg", "pic2.jpg", "pic3.jpg", "pic4.jpg"];
var i = 0;
while (i <= image.length) {
if (i > image.length) {
i = 0;
}
i += 1;
pageSplash.innerHTML = '<img id ="splashImage" src="file:///C:/JonTFS/JonGrochCoding/Javascript%20Practical%20Test/' + image[i] + '">';
setTimeout('slideShow', 5000);
}
}
I'm unsure why my i variable is not being recognized as the i variable from the rest of the function, so when ever I try to run my while loop it get's an error message saying that it's undefined.
I think you want setInterval instead of setTimeout, and you want you be careful that you increment i after you you update innerHTML.
function slideShow() {
var pageSplash = document.getElementById('splash');
var image = ["pic1.jpg", "pic2.jpg", "pic3.jpg", "pic4.jpg"];
var i = 0;
setInterval(function () {
if (i === image.length) {
i = 0;
}
pageSplash.innerHTML = '<img id ="splashImage" src="file:///C:/JonTFS/JonGrochCoding/Javascript%20Practical%20Test/' + image[i] + '">';
i++;
}, 5000)
}
slideShow();
You don't need a while loop. You don't need to reset i. You don't need to set innerHTML.
Click Run code snippet... to see how this works. More explanation below the code
function slideShow(elem, images, delay, i) {
elem.src = images[i % images.length];
setTimeout(function() {
slideShow(elem, images, delay, i+1);
}, delay);
}
// setup slideshow 1
slideShow(
document.querySelector('#slideshow1 img'), // target element
[ // array of images
'http://lorempixel.com/100/100/animals/1/',
'http://lorempixel.com/100/100/animals/2/',
'http://lorempixel.com/100/100/animals/3/',
'http://lorempixel.com/100/100/animals/4/',
'http://lorempixel.com/100/100/animals/5/',
'http://lorempixel.com/100/100/animals/6/'
],
1000, // 1000 ms delay (1 second)
1 // start on slide index 1
);
// setup slideshow 2
slideShow(
document.querySelector('#slideshow2 img'), // target element
[ // array of images
'http://lorempixel.com/100/100/nature/1/',
'http://lorempixel.com/100/100/nature/2/',
'http://lorempixel.com/100/100/nature/3/',
'http://lorempixel.com/100/100/nature/4/',
'http://lorempixel.com/100/100/nature/5/',
'http://lorempixel.com/100/100/nature/6/'
],
500, // 500 ms delay
1 // start on slide 1
);
#slideshow1, #slideshow2 {
width: 150px;
display: inline-block;
}
<div id="slideshow1">
<h2>Animals</h2>
<p>(1000 ms delay)</p>
<!-- initial image -->
<img src="http://lorempixel.com/100/100/animals/1/">
</div>
<div id="slideshow2">
<h2>Nature</h2>
<p>(500 ms delay)</p>
<!-- initial image -->
<img src="http://lorempixel.com/100/100/sports/1/">
</div>
This is a huge improvement because your slideshow function is reusable. It means you can use the same function for any slideshow you want. You can even run multiple slideshows on the same page, as I have demonstrated here.
As others have pointed out, the while loop is unnecessary and, as I pointed out, the setTimout was incorrectly written. The following simplifies your code significantly:
var i = 0;
function slideShow() {
var pageSplash = document.getElementById('splash');
var imageArray = ["pic1.jpg", "pic2.jpg", "pic3.jpg", "pic4.jpg"];
if(i < imageArray.length) {
pageSplash.innerHTML = '<img title='+ imageArray[i] + ' id ="splashImage" src="file:///C:/JonTFS/JonGrochCoding/Javascript%20Practical%20Test/' + imageArray[i] + '">';
}
i++;
}
setInterval(slideShow, 2000);
See: https://jsfiddle.net/dauvc4j6/8/ for a working version.
setTimeout calls the function again so you're re-initializing i to 0 every time you call it. Since you can use setTimeout to call the function recursively you don't need the while loop. Pull i out of the function altogether and make it a global variable.
//i should be global
var i = 0;
function slideShow() {
var pageSplash = document.getElementById('splash');
var image = ["pic1.jpg", "pic2.jpg", "pic3.jpg", "pic4.jpg"];
if (i >= image.length) {
i = 0;
}
i += 1;
pageSplash.innerHTML = '<img id ="splashImage" src="file:///C:/JonTFS/JonGrochCoding/Javascript%20Practical%20Test/' + image[i] + '">';
//set timeout is going to call slideShow again so if it's in the function it will call recursively, if you wanted to stop after a certain point you could nest setTimeout in an if
setTimeout(slideShow, 5000);
}
//you need to initially call the function
slideShow();
I have a full width slideshow. So I have a few problems with it.
One is that clearTimeout won't work. If I call the function by a click, it should clear the Timeout.
Does someone know why this won't work? Please explain and show where exactly the problem is.
Thank you and sorry for my bad English.
var index = 0;
var slideSpeed = 1000;
function mainSlider(menuLink){
clearTimeout(slide);
if(menuLink !== false){
alert('You call this function by a click event.');
clearTimeout(slide);
}
var sliderIndex = $('.main_slider_content').length - 1;
$('.main_slider_content').hide();
index++;
if(index > sliderIndex){
index = 0;
}
$('.main_slider_content:eq(' + index + ')').show();
var slide = setTimeout(function(){mainSlider(false)}, slideSpeed);
setTimeout(countContentImg(index), slideSpeed);
}
$(document).on('click', '.main_slider_menu_link',function(){
var linkIndex = $(this).index();
mainSlider(linkIndex);
});
function countContentImg(index){
$('#main_slider_selected_img').html('');
var sliderIndex = $('.main_slider_content').length;
for(var i = 0; i < sliderIndex; i++) {
if(i === index)
$('#main_slider_selected_img').append('<li class="main_slider_menu_link main_slider_menu_link_slected"></li>');
else
$('#main_slider_selected_img').append('<li class="main_slider_menu_link"></li>');
}
}
$(document).ready(function(){
countContentImg(index);
mainSlider(false);
});
This looks like a scope issue. You're trying to clear a timeout from a variable that doesn't contain a timeout reference yet. Each call to mainSlider creates a new, locally scoped timeout reference, long after you've tried to clear it.
function mainSlider(menuLink){
clearTimeout(slide); // Clearing a timeout that doesn't exist yet
if(menuLink !== false){
alert('You call this function by a click event.');
clearTimeout(slide); // Clearing a timeout that doesn't exist yet
}
var sliderIndex = $('.main_slider_content').length - 1;
$('.main_slider_content').hide();
index++;
if(index > sliderIndex){
index = 0;
}
$('.main_slider_content:eq(' + index + ')').show();
// Now the timeout exists, but only in the scope of this current call
var slide = setTimeout(function(){mainSlider(false)}, slideSpeed);
setTimeout(countContentImg(index), slideSpeed);
}
Change it to:
var slide;
function mainSlider(menuLink){
clearTimeout(slide);
if(menuLink !== false){
alert('You call this function by a click event.');
clearTimeout(slide);
}
var sliderIndex = $('.main_slider_content').length - 1;
$('.main_slider_content').hide();
index++;
if(index > sliderIndex){
index = 0;
}
$('.main_slider_content:eq(' + index + ')').show();
// Remove var
slide = setTimeout(function(){mainSlider(false)}, slideSpeed);
setTimeout(countContentImg(index), slideSpeed);
}
I have been trying to write a script that changes an image src every two seconds based on a list.
So, everything is inside a forloop that loops over that list:
$(document).ready(function() {
var lis = {{dias|safe}}; <----- a long list from django. This part of the code works fine.
for (i=0; i<lis.length; i++){
src_img = lis[i][1];
var timeout = setInterval(function(){
console.log(src_img)
$("#imagen").attr("src", src_img);
}, 2000)
}
});
It doesn't work, the console logs thousands of srcs that correspond to the last item on the list. Thanks a lot for your help.
you don't need to run cycle in this case, you just save "pointer" - curentImage and call next array item through function ever 2 sec
var curentImage = 0;
function getNextImg(){
var url = lis[curentImage];
if(lis[curentImage]){
curentImage++;
} else {
curentImage = 0;
}
return url;
}
var timeout = setInterval(function(){
$("#imagen").attr("src", getNextImg());
}, 2000)
var curentImage = 0;
var length = lis.length;
function NewImage(){
var url = lis[curentImage];
if(curentImage < length){
currentImage++;
}
else{
currentImage = 0;
}
return url;
}
var timeout = setInterval(function(){
$("#imagen").attr("src", getNextImg());
}, 2000)
PS: Better than the previous one, Checks for lis length and starts from first if you reach end.
You need something like this
$(document).ready(function() {
var index = 0;
setInterval(function(){
src_img = lis[index++ % lis.lenght][1]; // avoid arrayOutOfBounds
$("#imagen").attr("src", src_img);
}, 2000)
});