I am having problems understanding how a loop works how can I make a 'for' loop infinite times.
I am developing a wordpress website and I am using an automatic slider, in which the first slider element gets a class of "current" and I want a looping function that keeps verifying which element is the first one for me to be able to display certain texts for each slide.
The code is not that important but this is the JS:
window.onload = function() {
console.log('test');
const frank = document.querySelectorAll('#franck');
const slide21 = document.getElementById('slick-slide21');
console.log(slide21);
if(slide21.classList.contains('slick-current')){
console.log('julien');
}
and the html for current slider elements looks like this:
<div class="premium-carousel-template item-wrapper slick-slide slick-current slick-active" data-slick-index="5" aria-hidden="false" style="width: 374px;" tabindex="0" role="tabpanel" id="slick-slide25" aria-describedby="slick-slide-control25">
I am checking if the element contains the Slide-current element but it checks only once. I have a for but can I make it check for every slide that moves at every 2 seconds?
Looping to 9999 or anything like it but i want an infinite loop.
infinite for loop:
for(;;) {
/*things to do infinitely*/
}
in while loop:
while(1) {
/*things to do*/
}
and if you want to stop the loop, you can just add
if(/*condition to stop*/) {
break;
}
Related
I want to animate an image input when the user click the image, I'm using animate.css with Bootstrap and Angular, I've seen some examples to add the animate class when the image is click but nothing happens, when I console.log the element in the function I can see that the animate class is added but didnt work, also I got an error message in the console.
html code
<input type="image" src="../../../assets/img/as-logo-150dpi-05.png" class="d-block animate__animated animate__slideInLeft" id="offMenu" (click)="animateLogo()">
TS code
animateLogo(){
const element = document.querySelector('#offMenu');
if(element) {
element.classList.add('animate__animated', 'animate__bounceOutRight');
console.log(element)
}
}
As you can see in the input class, the aniimate class "animate__bounceOutRight" is added but nothing happens in my project, any advice on this?
So after the answer I found out the error message is because of bootstrap, nothing to do with the animation, and the problem was because the input already have an animation, when the function added another this overlaps and didint make it work so I need to disable the first one to make the second works but now the input disappear because of the second animation
HTML
<input type="image" src="../../../assets/img/as-logo-150dpi-05.png" class="d-block animate__animated animate__slideInLeft" id="offMenu" [ngClass]="{'animate__slideInLeft ': firstAnimation , 'animate__bounceOutRight': secondAnimation }" (click)="animateLogo()">
TS
firstAnimation: boolean; //This is true
secondAnimation: boolean; //This is false
animateLogo(){
this.firstAnimation = false
this.secondAnimation = true
}
Did you add the animate.css styles in your
angular.json
"styles": [
"node_modules/animate.css/animate.css"
],
OR
styles.css:
#import '~animate.css/animate.min'
Also just for a better approach let's try to do tackle your problem the Angular way
In your .ts create a boolean field named activateAnimation and we'll set it as true when the user clicks the image so your .ts code will look something like this:
activateAnimation: boolean;
animateLogo(): void {
this.activateAnimation = true
}
and then in your HTML we can conditionally add the animate.css classes that you want to add using the [ngClass] directive of Angular.
<input type="image" src="../../../assets/img/as-logo-150dpi-05.png"
class="d-block animate__animated animate__slideInLeft"
[ngClass]="{'animate__animated ': activateAnimation , 'animate__bounceOutRight': activateAnimation }" id="offMenu"
(click)="animateLogo()">```
Ok so after a little research I found a video that explains how to use Animate.css using jQuery and using the function that he explains with the click event I managed to take out the first animation class, add the second one and once the animations ends, take out the second animation class and add again the first animation class, all of this in the TS file, have some problems coding the jQuery in the TS file but the framework helps me out with the correct form of the code
So first in my <input> I added the class offMenu to identify my input, also I leave the animate__animated so I dont have to add it every time I take out or add an animation class and also I leave the animate__slideInLeft because I want to animate the input the first time ther page loads.
<input type="image" src="../../../assets/img/as-logo-150dpi-05.png" class="d-block animate__animated animate__slideInLeft offMenu" id="offMenu">
Next in my TS file in the constructor part I code the jQuery function, I create 3 variables:
The first one is effects this variable saves the second effect that
is animate__bounceOutRight.
The second variable is effectsEnd that saves the different classes
that Animate.css have to detect when the animation ends for the
different browsers.
And the third one is to save the element I want to add or remove
classes, in this case is my input with the class offMenu.
If you want to add one more variable to save the animate class you currently have, you can do it.
Next I select the element I want to add and remove classes and call the event on click once again in the function I select the element and remove the firts animate class 'animate__slideInLeft' as this animation already end theres no need to add the effectsEnd variable, next I add the second animation class that is saved in my variable effects, then with one we indicate this is going to happen one time and check fot the animation to end with the variable effectsEnd once the animation ends, we remove the animation class effects and add the firt animation class.
constructor() {
$(() =>{
var effects = 'animate__bounceOutRight';
var effectsEnd = 'animationend oAnimationEnd mozAnimationEnd webkitAnimationEnd';
var element = $('input.offMenu');
$(element).on("click", () => {
$(element).removeClass('animate__slideInLeft').addClass(effects).one(effectsEnd, () =>{
$(element).removeClass(effects).addClass('animate__slideInLeft')
});
});
})
}
Whit this code you can put one animation to show when the page is load and then add another animation when you click in the element and take back the element once the out animation is done, hope this helps someone else.
I am trying to make a simple slot machine game as the first one here.
The one in the example above is a bit complex, but I only need mine to add a few classes here and there at simple click events.
Long story short, I have a play button which initiates the slot machine (shows it - this is done), and when the slot machine is shown, a SPIN button appears, and when I click that button, I can only make it add one class for the first combination (e.g. "bonus") which adds the CSS class and its respective transitions to the desired effect.
And now comes the tricky part for me, I need to click the same SPIN button again, but add a different class this time. This has to work 3 times, while when I am pressing it for the 4-th time, I need it to add another class to the id='ad-cont' div.
How can I achieve this with vanilla JS? I know there must be some sort of a loop here, but I can't figure it out.
<div id="ad-cont">
<div id="slot-frame"><img class="frame" src="../frame.png">
<div class="frame-item"></div>
<div class="frame-item"></div>
<div class="frame-item"></div>
<div class="frame-item"></div>
<div class="frame-item"></div>
</div><a id="play" href="#">PLAY</a><a id="spin" href="#">SPIN</a>
</div>
And here is what I've got so far:
var adContainer = document.getElementById('ad-cont');
var playBtn = document.getElementById('play');
var spinBtn = document.getElementById('spin');
var slotMachine = document.getElementById('slot-frame');
playBtn.addEventListener('click', function(){
adContainer.classList.add('playing');
});
spinBtn.addEventListener('click', function(){
slotMachine.classList.add('bonus');
});
Thank You all!
Have you tried using a switch and a count that resets itself?
var count = 0;
spinBtn.addEventListener('click', function(){
count++;
switch(count) {
case 1:
slotMachine.classList.add('bonus');
break;
case 2:
slotMachine.classList.add('bonus2');
break;
case 3:
slotMachine.classList.add('bonus3');
break;
case 4:
otherIdElement.classList.add('finished!');
count = 0;
break;
default:
alert("error!");
}
});
There's not enough code to really give a complete answer, but if I understand you right, I think the easiest thing to do would be to add a counter and an array of classes.
var counter = 0;
var classes = ['playing', 'playing_again', 'another_class', 'bonus']
Then you can add classes as you play:
playBtn.addEventListener('click', function(){
adContainer.classList.add(classes[counter]);
// if you need to do other things here you
// can check the counter value and proceed accordingly
counter++
});
You just need to check that counter never gets higher than the last index of classes
function clearObjects() {
var co = document.getElementsByClassName("clearable");
var i;
alert("function runs");
for (i = 0; i < co.length; i++) {
alert("for loop runs 1/3");
alert("for loop runs 2/3, time to erase");
co[i].style.backgroundColor = "#FFFFFF";
alert("for loop runs 1, erased 1");
};
};
clearObjects();
This function that I has here is suppose to change the color of all divs with the class of clearable to a background color of white, where they are "Erased." The function runs inside of my other code, but my issue is that the for loop stops running when it gets to:
co[i].style.backgroundColor = "#FFFFFF";
I put alerts in there to see what parts of the function run, and the final alert "for loop runs 1, erased 1" does not alert, and the for loop does not run again. I have looked and could not find a problem similar to mine. Does anyone know what I am doing wrong? I will post all of my code if neccessary. Thanks!
I fixed my problem by setting the visibility to hidden instead of background to white, and by setting the class of the new divs with jquery's attr() function instead of what I had. It works perfectly now, thanks for all the input!
The issue you were running into is that you were attempting to set the class of each drawn object in CSS. The change to fix that is changing this:
var div = $('<div>').css({
'class': 'clearable'
});
To this:
var div = $('<div>').css({
...
}).addClass('clearable');
You can also remove the element easily by using co[i].parentNode.removeChild(co[i]) instead of changing the background color (frees up memory). I've reversed the direction of the loop in my example because you're dealing with removing elements (and that shifts the array one element backwards causing you to skip an item each time if going forwards).
See my code pen: http://codepen.io/anon/pen/BNYRWE
i am doing a site with 2 navigations (navs) including links, each of them in another div.
When a link is clicked it should change its background image in the css (change class).
And only one link of its class can change the background.
In the second nav there is one link which is also included in nav 1.
Also are in the second nav two different background images to "toggle".
I already have accomplished the first nav, but I do not know how to include the second one.
In the second one is the problem that two links should not change their background at the same time.
The site: http://enlifer.de/test25/zp-kazachkova.html
The second nav is at the height of the logo.
If "Leistungen" is clicked in the second nav, the first one should also change its default background and vice versa.
Following code is relevant.
First nav
<navigation>
<ul id="nav">
<li class="link" onclick="mark(this)"> Kontakt </li>
<li class="link" onclick="mark(this)"> Anfahrt </li>
<li class="link" onclick="mark(this)"> Leistungen </li>
<li class="link" onclick="mark(this)"> Praxisteam </li>
</ul>
</navigation>
Second nav
<up>
<ul id="up">
<li class="uplink-l" onclick="l_mark(this)"> Leistungen </li>
<li class="uplink-i" onclick="i_mark(this)"> Impressum </li>
</ul>
</up>
JavaScript
<script type="text/javascript">
function mark(cell)
{
for(i=0; i <
document.getElementById("nav").getElementsByTagName("li").length; i++)
{
document.getElementById("nav").getElementsByTagName("li")[i].className="link";
}
cell.className="linkactive";
}
function l_mark(cell)
{
for(i=0; i <
document.getElementById("up").getElementsByTagName("li")[0].length; i++)
{
document.getElementById("up").getElementsByTagName("li")[0][i].className="uplink-l";
}
cell.className="uplink-l-active";
}
function i_mark(cell)
{
for(i=0; i <
document.getElementById("up").getElementsByTagName("li")[1].length; i++)
{
document.getElementById("up").getElementsByTagName("li")[1][i].className="uplink-i";
}
cell.className="uplink-i-active";
}
window.onload = setActive;
</script>
Thanks!
"Leistungen" has the class lmark, while "Impressum" has imark. Your Javascript function for lmark-classed elements resets the background for all other lmark-classed elements, but not for the imark-classed ones. Same for the function that concerns imark.
If you need to have only one non-default background for all lmark and imark elements, a correct (probably correct, though not tested) code is:
function li_mark(cell) {
var elts=document.getElementById("up").getElementsByTagName("li"); //store the elements we need in a local variable so we don't have to rewrite all that line (and the browser won't have to do the fetching job again), we don't care if they're L-type or I-type
for(var i in elts)
if(elts[i].className && elts[i].className.length>=8) //check if there is a className and it is at least as long as "uplink-X", otherwise we don't process the element and skip to the next
elts[i].className="uplink-"+elts[i].className.charAt(7); //we retrieve the letter for the type of class (L or I), and we append it to "upload-" to redefine the class of the current element
cell.className+="-active"; //after the loop, all elements have their default class, so we just need to append "-active" to the one we want to be active
}
Then, all your calls to l_mark(this) and i_mark(this) should simply be replaced by calls to li_mark(this).
P.S.: not related, but my current browser (Firefox) doesn't seem to like the window.onload=setActive;, saying that "setActive is not defined"...
Edit according to comments, having seen your JS file (scripttests.js):
You still need 2 functions, mark() and li_mark(), because for mark() your active class is of the form <className>active instead of <className>-X-active (not the same pattern in naming the classes, and no need to retrieve the character Lor I).
Another part of the problem is that you call cell.className+="-active" twice on the same cell in the one function you have.
The last part of the problem is that you forgot the instruction within the if of the second loop: as there are no block brackets, the instruction that is executed when this if is true is cell.className+="-active"... executed as many times as the loop runs and the if is true.
A (probably) working version would be:
function li_mark(cell) {
var elts=document.getElementById("up").getElementsByTagName("li"); //store the elements we need in a local variable so we don't have to rewrite all that line (and the browser won't have to do the fetching job again), we don't care if they're L-type or I-type
for(var i in elts)
if(elts[i].className && elts[i].className.length>=8) //check if there is a className and it is at least as long as "uplink-X", otherwise we don't process the element and skip to the next
elts[i].className="uplink-"+elts[i].className.charAt(7); //we retrieve the letter for the type of class (L or I), and we append it to "upload-" to redefine the class of the current element
if(cell && cell.className && cell.className.length>=8) { //if we passed an argument, then it must be a cell to activate, with a basic check on its className
cell.className+="-active"; //after the loop, all elements have their default class, so we just need to append "-active" to the one we want to be active
mark(); //we call mark() with no argument to reset all the items managed by mark(), we call it in this if-block to avoid infinite recursion
}
}
function mark(cell) {
var elts=document.getElementById("nav").getElementsByTagName("li"); //store the elements we need in a local variable so we don't have to rewrite all that line (and the browser won't have to do the fetching job again), we don't care if they're L-type or I-type
for(var i in elts)
if(elts[i].className) //check if there is a className, otherwise we don't process the element and skip to the next
elts[i].className="link"; //we set back to the default class
if(cell && cell.className) { //if we passed an argument, then it must be a cell to activate
cell.className+="active"; //after the loop, all elements have their default class, so we just need to append "active" to the one we want to be active
li_mark(); //we call li_mark() with no argument to reset all the items managed by li_mark(), we call it in this if-block to avoid infinite recursion
}
}
I've never particularly used JS much, with the exception of basic animations,
The page I'm working on requires me to fade out the active div and fade the requested one in, I have around 25 different div's I'll be fading between. At the minute I can't think of how to only fade the active one out so I'm trying to fade every div but the one that's requested out.
Here's the code I'm attempting to get working
var active = 0;
for (i=0;i<array.length;i++) {
if (i != active){
document.write("$('."+array[i]+"').fadeOut(900);");
}
naturally i know the document.write shouldn't be there, but ideally that code has to be printed into the .js file I'm using, however. I don't have a clue how to print it to the .js.
any suggestions would be greatly appreciated, or a way to do this in php without a page reload!
When you find yourself generating code on the fly, it usually indicates that you want to take a step back and re-evaluate your approach. :-)
In this case, there's no need to create the JavaScript dynamically. It's just a matter of running the code.
I wasn't sure what your definition of "active" was, so here's something that fades divs in/out on the basis of what buttons you press:
The HTML:
<input type='button' value='1'>
<input type='button' value='2'>
<input type='button' value='3'>
<input type='button' value='4'>
<input type='button' value='5'>
<input type='button' value='6'>
<div id='container'>
<div class='c1'>This is c1</div>
<div class='c2'>This is c2</div>
<div class='c3'>This is c3</div>
<div class='c4'>This is c4</div>
<div class='c5'>This is c5</div>
<div class='c6'>This is c6</div>
</div>
The JavaScript (teaching version):
jQuery(function($) {
// Hook our buttons; this selector hooks all of them,
// so you probably want to narrow that down, but I
// have no idea what your definition of "active" is,
// so I made one up.
$(":button").click(function() {
// Get the value of the button, e.g., 1, 2
var val = this.value;
// Get all of the divs in the container
var divs = $("#container div");
// Fade out all of the ones that aren't our target;
// fade in the one that is
divs.not(".c" + val).fadeOut(900);
divs.filter(".c" + val).fadeIn(900);
});
});
Live copy
That does this:
Uses the jQuery ready function (the shortcut form where I just pass a function into the jQuery function) to run the code when the page is "ready" (the DOM has been built)
Looks up all divs we want to be dealing with. In my case, it's all the divs in a container, but you can use just about any CSS3 selector you want (and then some).
Uses not with a class selector to filter out the div that has the target class, then uses fadeOut to start fading the other ones out.
Uses filter to reduce the set to just our target div, and fadeIn to start fading it in.
That version is for clarity. Here's a more concise version (still perfectly clear to people who know jQuery well, but tricky for folks still finding their feet):
The JavaScript (chained version using end):
jQuery(function($) {
// Hook our buttons; this selector hooks all of them,
// so you probably want to narrow that down, but I
// have no idea what your definition of "active" is,
// so I made one up.
$(":button").click(function() {
// Get the value of the button, e.g., 1, 2
var val = this.value;
// Get all of the divs in the container
// Fade out all of the ones that aren't our target;
// fade in the one that is
$("#container div")
.not(".c" + val).fadeOut(900)
.end()
.filter(".c" + val).fadeIn(900);
});
});
Live copy
Not sure why you are using document.write instead of simply executing the javascript.
var active = 0;
for (i=0;i<array.length;i++) {
if (i != active) {
$("."+array[i]).fadeOut(900);
}
Additionally, try using a jQuery selector to select all the non-active divs by adding an additional class to each div:
var active = array[0];
var classname = "some_class";
$("div." + classname + ":not(." + active + ")").fadeOut(900);
You could even just select the visible divs that are not the active one and fade them out:
var active = array[0];
var classname = "some_class";
$("div." + classname + ":not(." + active + "):visible").fadeOut(900);