How to delay two functions inside a loop? - javascript

I've been searching all day and I can't figure out how to fix it.
All I wanna do is iterate through a bunch of elements and do the following things to each of it:
Add a class
Wait 3s
Remove the class added
Go to the next element
I've tried many things and now I have this:
/* Avatars is an array of elements */
var i = 0
function testimonialCarousel(avatars){
const avatarsLen = avatars.length
avatars[i].classList.add("focused-avatar");
i++;
if (i > 0){
avatars[i-1].classList.remove("focused-avatar");
};
if (i < avatarsLen) {
setTimeout(testimonialCarousel.bind({}, avatars), 3000);
} else{
i = 0;
};
};
I know that there are many questions here already covering the delay of a single function, for example: How do I add a delay in a JavaScript loop?
This is not my case. I can achieve it, adding the class for each element with a 3s interval. What I'm not able to achieve is the "remove class" step.
Does anybody may help me?

Ok, I've found out how to handle it:
for (let i = 0; i <= avatarsLen; i++){
setTimeout(function(){
if (i > 0){
avatars[i-1].classList.remove("focused-avatar");
};
if (i == avatarsLen) {
return testimonialCarousel();
};
avatars[i].classList.add("focused-avatar");
balloonMessage.style.opacity = 0;
balloonName.style.opacity = 0;
setTimeout(function(){
balloonMessage.innerHTML = balloonContent[i].message;
balloonName.innerHTML = "— " + balloonContent[i].name;
balloonMessage.style.opacity = 1;
balloonName.style.opacity = 1;
}, 650)
}, i*3000); /* <--- The solution lays here. */

Related

When combining 2 strings, Dom element is not showing same results as static entered query

I'm sure I'm overlooking the most obvious, but I need to loop through a few links on the page, but some reason when I try to introduce the iterated number, and change to a string, it doesn't work. By not working, I mean when I run the function, it gives me error ' Uncaught TypeError: Cannot read property 'click' of null'. The first is an example showing it works without the loop. The 2nd is the string combo that doesn't work.
This works!
function myFunction() {
var grids = document.getElementsByClassName('gridRow')
setInterval(function(){
for(i=1;i<grids.length;i++) {
var test = '_resultsGrid__Button_1'
document.getElementById(test).click()
}
}, 2000);
}
This doesn't!
function myFunction() {
var grids = document.getElementsByClassName('gridRow')
setInterval(function() {
for(i=1;i<grids.length;i++) {
var test = '_resultsGrid__Button_' + String(i)
document.getElementById(String(test)).click()
}
}, 2000);
}
Instead of doing
for (i = 1;i < grids.length;i++) { ... }
You should be doing
for (i = 1;i <= grids.length;i++) { ... }
In your first example you were looping only while i was less than (<) the elements length, so you would loop one less time than the length; you'll want to use the less than or equal to (<=) operator instead to include that last iteration
function myFunction() {
var grids = document.getElementsByClassName('gridRow')
setInterval(function() {
for(i = 1; i <= grids.length; i++) {
var test = '_resultsGrid__Button_'+String(i)
document.getElementById(String(test)).click()
}
}, 2000);
}

Javascript Performance improvement

I am Using Jquery plugin to show a dropdown which looks like this
Now in the edit page, this drop-down opens with checked checkboxes, I do this with the help of Javascript which is as below
var setValues = $("#SelectedFrameworks").val().split(",");
for (var i = 0; i < setValues.length; i++) {
var selectedElement = $("#frameworksDropDown").find('*[data-id="' + setValues[i] + '"]');
selectedElement.find("i").addClass("fa-check-square-o").removeClass("fa-square-o");
SelectParent(selectedElement);
}
function SelectParent(_element) {
var count = 0;
for (var i = 0; i < $(_element).parent().children().length; i++) {
if ($(_element).parent().children().eq(i).find("i").attr("class") == "fa select-box fa-check-square-o") {
count++;
}
}
if (count == $(_element).parent().children().length) {
$(_element).closest("ul").siblings("i").click();
}
}
I store this value first in the hidden field then use it to Check the checkboxes. (as shown in the code)
Now the problem is, it takes too much time when data is a lot. this causes the page to hang.
I found that operation
selectedElement.find("i").addClass("fa-check-square-o").removeClass("fa-square-o");
takes too much time. how can I optimize this code to have a better result
EDIT
Here is the HTML for this dropdown.
Note: this HTML is autogenarated.
Thanks.
So one of the big issues with this code is the amount of times you're calling the DOM. Everytime you do $(el) you're calling document.getElementByClassName or id etc. Which is gonna be slow and is unnecessary to make that many calls.
So you can change
function SelectParent(_element) {
var count = 0;
for (var i = 0; i < $(_element).parent().children().length; i++) {
if ($(_element).parent().children().eq(i).find("i").attr("class") == "fa select-box fa-check-square-o") {
count++;
}
}
if (count == $(_element).parent().children().length) {
$(_element).closest("ul").siblings("i").click();
}
}
To this, which accesses the DOM once, stores a reference to the element. This will cut down on the amount of DOM calls you make. The biggest advantage to this is of course, speed. I always make a point of naming jquery variables beginning with $ so that it's much easier and quicker to tell what that variable is in the future, or if someone else comes to work on your code.
function SelectParent(_element) {
var count = 0;
var $element = $(_element);
var $children = $element.parent().children();
for (var i = 0, length = $children.length; i < length; i++) {
if ($children.eq(i).find("i").attr("class") == "fa select-box fa-check-square-o") {
count++;
}
}
if (count == $children.length) {
$element.closest("ul").siblings("i").click();
}
}
Now of course you can refactor the rest to speed it up ;)

Why first image in Array doesn't loop the first time around?

I am making a simple animation using javascript. Of course I could use the CSS keyframes, but that would not work for what I need this for, so no CSS solution please. I threw in a status div just so you see what I mean without actually having to see the images. JSfiddle below.
Anyway here is the HTML.
<div id="zero-walking"><img src="#" id="zeroImage"></div>
<div id="statusDiv"></div>
Here is the javascript
var index = 0;
var zero = document.getElementById("zeroImage");
var zeroArray = ["images/1.png", "images/2.png", "images/3.png", "images/4.png", "images/5.png", "images/6.png", "images/7.png", "images/8.png", "images/9.png", "images/10.png", "images/11.png"];
zeroAnimate();
function zeroAnimate() {
zero.setAttribute('src', zeroArray[index]);
index += 1;
if (index == zeroArray.length) {
index = 0;
}
var statusDiv = document.getElementById('statusDiv');
statusDiv.innerHTML = zeroArray[index];
}
setInterval(zeroAnimate, 700);
http://jsfiddle.net/r9zfg3jp/
This block:
index += 1;
if (index == zeroArray.length) {
index = 0;
}
Should be at the very end of the function.
Your problem is index += 1 is happening before you ever do statusDiv.innerHTML = zeroArray[index]; so it's 1 (not 0) the first time you get there...
Try moving the index assignment operator to the end of your method here. As it is, you are FIRST increment the index, then doing work, meaning you are skipping the 0 frame...
Sometimes I ask myself why I help. If you just want to loop over those images it's like:
function loopImages(elem, imgs, interval, loop){
var i = 0, loopy = setInterval(function(){
elem.src = imgs[i++];
if(i === imgs.length){
loop ? i = 0 : clearInterval(loopy);
}
}, interval);
}
loopImages(document.getElementById('zeroImage'), zeroArray, 700, true); // loops forever

Adding increased count to the DOM for every pass

what I'm hoping to achieve is to increase a count and then append that to the DOM on every pass through using each(). What I have at the moment is the final count added at the end. For example.
Say I have 100 divs, for every pass through it should add the new count as it counts it, like so 1,2,3,4,5,6,7... and so on. But at the moment it counts all the objects and just appends 100 at the end. Please can someone point me in the direction to where I'm going wrong?
I've added a very basic version of what I'm hoping to achieve below... also here is a JSbin (I tried jsfiddle but it seems to be down for me) .
$(".toCount").each(function(i){
$("#count").text(i + 1);
});
$('input').on('click',function () {
var len = $(".toCount").length;
var arr = [];
for (var i = 0; i < len; i++ ) {
arr.push(i+1);
}
$('#count').text(arr.join());
});
I don't know what you mean by 1, 2, 3 ... in case that you want to count the elements step by step you can use setInterval function:
$('input').on('click',function () {
var l = $(".toCount").length,
$c = $('#count'),
i = 0;
var t = setInterval(function() {
i++;
$c.text(i);
if (i === l) clearInterval(t);
}, 10);
});
http://jsbin.com/eronel/17/edit
use append();
Insert content, specified by the parameter, to the end of each element in the set of matched elements.
in your case text() is replacing your div's text so u get 100 at the end ..
$("#count").append(i + 1);
Use append
$("#count").append(i + 1);

Javascript pause in WinRT for animation

I want to pause execution in javascript so that I can animate the appearance of text on the screen. My code is currently this:
function AnimateWord(word) {
for (var i = 0; i <= word.length; i++) {
myTest.textContent += word.charAt(i);
// need to pause here and then continue
}
}
I've done some research and the preferred method to do this in javascript seems to be setTimeout, although I can't really see how that would work in this case without creating a recursive loop (which just doesn't seem like the right solution to me).
Is there a way around this, or am I stuck with setTimeout and a recursive loop?
EDIT:
Based on some additional tests, I've tried using the Promise.timeout:
for (var i = 0; i <= word.length; i++) {
WinJS.Promise.timeout(1000).then(TypeLetter(word.charAt(i)));
}
function TypeLetter(letter) {
myTest.textContent += letter;
}
But this doesn't seem to actually pause. In fact, it seems to completely ignore the timeout. I've also tried:
setTimeout(TypeLetter(word.charAt(i)), 1000);
With basically the same results. this page seems to imply that it should wait and then execute the task. I'm quite new to WinJS, but am equating a promise to an await keyword in C#.
setTimeout/setIngerval/requestAnimationFrame are pretty much your only choices. I wouldn't call them recursive perse - while you do call your same function over & over. The calls tack is completely independent.
What kind of animation are you really trying to create? It may be better to create a span for each character, have them hidden, and then fade/translate the, in using CSS animations.
var i = 0;
var str = "plz send teh codez";
var intervalId = setInterval(function(){
myTest.textContent += str.charAt(i);
if (++i >= str.length)
clearInterval(intervalId);
}, 1000);
demo http://jsfiddle.net/qxfVu/1/
Does this do what you are looking for:
var array1 = [];
function AnimateWord(word) {
var test = $('#test');
for (var i = 0; i <= word.length; i++) {
array1.push(word.charAt(i));
test.delay(100).queue(function() {
this.innerHTML += array1[0];
array1.splice(0, 1);
$(this).dequeue();
});
}
}
please see fiddle link as well: http://jsfiddle.net/7Ea9u/

Categories

Resources