if/else and setInterval - javascript

<script>
//when user clicks start button this function ensures all fields //are set to 0 and it
//sets the timer for the game (90seconds) and the second timer to //call showWord() every four seconds to display a new word
function startGame() {
numBadWordsField.innerHTML = '';
numGoodWordsField.innerHTML = '';
numWordsRight = 0;
numWordsWrong = 0;
correctWords = [];
showWord();
gameTimer = setInterval(gameTime, 1000);
timedWordDisplay = setInterval(showWord, 4000);
}
//this function is set to repeat every four seconds unless the user //types the word
//correctly in which case code in the checkWord() function resets setInterval then and a new word appears
function showWord() {
let randomNum = Math.floor(Math.random()*wordsLevelOne.length);
currentWord = wordsLevelOne[randomNum];
//i put all correctly typed words in an array to avoid them being repeated
//if the random word has been typed correctly and is in the array then i tell the
//program to repeat the function until a new word is found.
if (correctWords.includes(currentWord)) {
showWord();
} else {
wordDisplayBox.innerHTML = currentWord;
setInterval(changeBar, 500);
answerBox.focus();
}
}
//this function is called oninput as user types in the word. it works perfectly (i think it does anyways)
//however i cannot figure out how to give instructions in the event the user does not type the
//word correctly before the four seconds are up and the setInterval repeats. I would like to
//in that case increment the words wrong score and reset the fields to be ready for the next
//word to be displayed
function checkWord() {
let currentWordLen = answerBox.value.length;
if (wordDisplayBox.innerHTML === answerBox.value) {
clearInterval(timedWordDisplay);
numWordsRight++;
correctWords.push(currentWord);
numGoodWordsField.innerHTML = numWordsRight;
answerBox.value = '';
answerBox.focus();
wordDisplayBox.innerHTML = '';
showWord();
timedWordDisplay = setInterval(showWord, 4000);
} else if (answerBox.value === currentWord.substring(0, currentWordLen)) {
answerBox.style.borderColor = 'green';
} else {
answerBox.style.borderColor = 'red';
}
}
//different topic than above but i also researched how to make my progress bar fill slowly over the course
//of the four seconds. i have written the following function identically to that on
//w3schools and other code yet it does not work.
//Any ideas?
function changeBar() {
let proBar = document.querySelector('#progressBar');
var width = 1;
var id = setInterval(frame, 10);
function frame() {
if (width >= 100) {
clearInterval(id);
} else {
width++;
proBar.style.width = width + '%';
}
}
}
</script>
This project Im working on is a beginner level speed typing game that displays a different word for the user to type in less than four seconds.I have a setInterval that displays a different word every four seconds unless the user types the word correctly at which point the timer starts over then. What I am stumped at is how can I make it so that if the correct answer is not typed in before the interval resets (at the end of four seconds) the program knows to increment the 'wrong answer' score and to reset the input boxes for the next word just like when it is typed correctly. i have attached the parts of my code i think may be relevant. If anyone has any suggestions let me know. I am eager to learn. **I am not familiar yet with JQuery. Please describe any suggestions using vanilla JS

This feature should be implemented in the showWord function.
showWord is executed after 4 seconds have passed, which is when the time is up. Executing this function means the user has failed to type the word in time.
I would do something like this :
function showWord() {
// At this point, the user has lost. We perform the according operations
numWordsWrong++;
answerBox.value = '';
// etc.
// What follows is the rest of the function you've already implemented
let randomNum = Math.floor(Math.random()*wordsLevelOne.length);
// etc.
}

To answer your question about the progress bar, you are setting an interval to run changeBar every 500 milliseconds, which would cause the progress bar to reset every half second. If you want a delay before starting the progress bar use setTimeout.
In addition, you are running your progress bar to move 1% every 10 milliseconds which would result in the bar completing in 1 second. If you want the bar to complete in 4 seconds, set the id interval to run every 40 milliseconds.
Without seeing your css and html, I have to assume you're using the correct id names in your code but if nothing is happening at all, that could also be the cause.
I have looked at the W3Shools code you reference and I tried to replicate what you were trying to do and got this to work:
<html>
<head>
<style>
#myProgress {
width: 100%;
background-color: #ddd;
}
#myBar {
width: 1%;
height: 30px;
background-color: #4CAF50;
}
</style>
</head>
<body>
<div id="myProgress">
<div id="myBar"></div>
</div>
</body>
<script>
function changeBar() {
let proBar = document.querySelector('#myBar');
var width = 1;
var id = setInterval(frame, 40);
function frame() {
if (width >= 100) {
clearInterval(id);
} else {
width++;
proBar.style.width = width + '%';
}
}
}
setTimeout(changeBar, 100);
</script>
</html>

One solution can be to create a new function (ex : showWordBecauseTimeout) and call it in your setInterval instead of showWord. And call that function in showWord fct instead of in startGame fct.
So the new code would be something like :
function showWord() {
clearInterval(timedWordDisplay);
timedWordDisplay = setInterval(showWordBecauseTimeout, 4000);
// you also need to move the cleaning of the input in the showWord fct
// ...
}
function showWordBecauseTimeout() {
numWordsWrong++;
showWord()
}
Hope that it helps you :).

Related

Rotating several images with different timings

I have three images side by side, left, middle and right. I want the first image on the left to change after 2 seconds, then the one in the middle to change 2 seconds later and then the one on the right to change 2 seconds after that. Then after another 2 seconds I want the first one on the left to change again and for the sequence to start all over again.
I've put together the javascript code for each image to have a certain start time and then a 6 second interval before changing again, this gives the effect I'm looking for.
The sequence works the first time round but when the first image is due to run through the sequence the second time round the whole thing seems to stick a bit and then all the images start changing together, as if they are all affecting one another. I don't know why this is since the code refers to each separately. Any help would be appreciated. Here's the code:
HTML Code:
<div>
<img id="mainImage" src="firstimage.jpg">
<img id="mainImage1" src="secondimage.jpg">
<img id="mainImage2" src="thirdimage.jpg">
</div>
Javascript Code:
<script>
var myImage = document.getElementById("mainImage");
var imageArray = ["image1.jpg","image2.jpg","image3.jpg"];
var imageIndex = 0;
function changeImage() {
myImage.setAttribute("src",imageArray[imageIndex]);
imageIndex++;
if (imageIndex >= imageArray.length) {
imageIndex = 0;
}
}
setTimeout(changeImage, 0000);
setInterval(changeImage,6000);
</script>
<script>
var myImage1 = document.getElementById("mainImage1");
var imageArray1 = ["image4.jpg","image5.jpg","image6.jpg"];
var imageIndex1 = 0;
function changeImage1() {
myImage1.setAttribute("src",imageArray1[imageIndex1]);
imageIndex1++;
if (imageIndex1 >= imageArray1.length) {
imageIndex1 = 0;
}
}
setTimeout(changeImage1, 2000);
setInterval(changeImage1,6000);
</script>
<script>
var myImage2 = document.getElementById("mainImage2");
var imageArray2 = ["image7.jpg","image8.jpg","image9.jpg"];
var imageIndex2 = 0;
function changeImage2() {
myImage2.setAttribute("src",imageArray2[imageIndex2]);
imageIndex2++;
if (imageIndex2 >= imageArray2.length) {
imageIndex2 = 0;
}
}
setTimeout(changeImage2, 4000);
setInterval(changeImage2,6000);
</script>
Solution:
For each
setTimeout(changeImage2, x);
setInterval(changeImage2,6000);
change to
setTimeout(function() {
setInterval(changeImage2,6000);
}, x);
Check here: https://jsfiddle.net/bstd3fqu/4/
Explanation:
setTimeout() doesn't make runtime to sleep for certain time. It simply set a timer to execute the mentioned function after certain time. So all setInterval() calls are executing at almost same time in your implementation. I am just setting the interval in the setTimeout function so that these setInterval() calls are executing at different times.

Simple loop for images

I'm trying to build a simple image slider (but using a fade effect). Every two seconds, the image should change to another image. At the end, it should call repeat_sponsor() again, to start over, so it becomes a loop.
I've written this (highly ineffective) code for 5 images. Turns out I'm going to need it for around 50 images. My editor just freezes when I add too much code.
I've tried using while-loops, but I just can't figure it out how to do this the right way.
Anyone who can help me with this?
function repeat_sponsor()
{
$("#sponsor2").hide();
$("#sponsor3").hide();
$("#sponsor4").hide();
$("#sponsor5").fadeOut("slow");
$("#sponsor1").fadeIn("slow", function() {
setTimeout(function(){$("#sponsor2").fadeIn("slow", function() {
setTimeout(function(){$("#sponsor3").fadeIn("slow", function() {
setTimeout(function(){$("#sponsor4").fadeIn("slow", function() {
setTimeout(function(){$("#sponsor5").fadeIn("slow", ...
(function (){
var cnt = 50; //set to the last one...
var max=50;
function show() {
$("#sponsor" + cnt).fadeOut("slow"); //if you want the fadeout to be done before showing next, put the following code in the complete callback
cnt++;
if(cnt>max) {
cnt=1;
}
$("#sponsor" + cnt).fadeIn("slow");
window.setTimeout(show, 2000);
}
show();
})();
But the real issue is the fact you are loading tons of images from the start. You will be better off changing it so you only have a small subset of images and change the source.
You should use some sort of for loop and a class for hiding the images. and add a max value that if checks out resets c & i
var i=0;
var c=1;
function repeat_sponsor()
{
$("#sponsor"+i).fadeOut("slow");
$(".sponsers").hide()
$("#sponsor"+c).fadeIn("slow", function() {
window.setTimeout(repeat_sponsor(), 3000);
}
i++;
c++;
}
Just run a function every two seconds with setInterval and appropriately target your different sponsor divs:
var i = 1;
var max = 50;
setInterval(function() {
// Could target all other sponsor images with a class "sponsor"
$('.sponsor').fadeOut();
// Execute code on the target
$("#sponsor" + i).fadeIn();
if (i === max) {
i = 0;
}
i++;
}, 2000);

Javascript fade in doesn't visibly animate

So I've created the following function to fade elements in and passed in a div that I want to fade in which in this case is an image gallery popup that I want to show when a user clicks an image thumbnail on my site. I'm also passing in a speed value (iSpeed) which the timeout uses for it's time value. In this case I'm using 25 (25ms).
I've stepped through this function whilst doing so it appears to be functioning as expected. If the current opacity is less than 1, then it is incremented and it will recall itself after the timeout until the opacity reaches 1. When it reaches one it stops fading and returns.
So after stepping through it, I take off my breakpoints and try to see it in action but for some reason my gallery instantly appears without any sense of fading.
var Effects = new function () {
this.Fading = false;
this.FadeIn = function (oElement, iSpeed) {
//set opacity to zero if we haven't started fading yet.
if (this.Fading == false) {
oElement.style.opacity = 0;
}
//if we've reached or passed max opacity, stop fading
if (oElement.style.opacity >= 1) {
oElement.style.opacity = 1;
this.Fading = false;
return;
}
//otherwise, fade
else {
this.Fading = true;
var iCurrentOpacity = parseFloat(oElement.style.opacity);
oElement.style.opacity = iCurrentOpacity + 0.1;
setTimeout(Effects.FadeIn(oElement, iSpeed), iSpeed);
}
}
}
Here's where I'm setting up the gallery.
this.Show = function (sPage, iImagesToDisplay, oSelectedImage) {
//create and show overlay
var oOverlay = document.createElement('div');
oOverlay.id = 'divOverlay';
document.body.appendChild(oOverlay);
//create and show gallery box
var oGallery = document.createElement('div');
oGallery.id = 'divGallery';
oGallery.style.opacity = 0;
document.body.appendChild(oGallery);
//set position of gallery box
oGallery.style.top = (window.innerHeight / 2) - (oGallery.clientHeight / 2) + 'px';
oGallery.style.left = (window.innerWidth / 2) - (oGallery.clientWidth / 2) + 'px';
//call content function
ImageGallery.CreateContent(oGallery, sPage, iImagesToDisplay, oSelectedImage);
//fade in gallery
Effects.FadeIn(oGallery, 25);
}
Could anyone help me out?
Also, I'm using IE10 and I've also tried Chrome, same result.
Thanks,
Andy
This line:
setTimeout(Effects.FadeIn(oElement, iSpeed), iSpeed);
calls Effects.FadeIn with the given arguments, and feeds its return value into setTimeout. This is exactly like foo(bar()), which calls bar immediately, and then feeds its return value into foo.
Since your FadeIn function doesn't return a function, that would be the problem.
Perhaps you meant:
setTimeout(function() {
Effects.FadeIn(oElement, iSpeed);
}, iSpeed);
...although you'd be better off creating that function once and reusing it.
For instance, I think this does what you're looking for, but without recreating functions on each loop:
var Effects = new function () {
this.FadeIn = function (oElement, iSpeed) {
var fading = false;
var timer = setInterval(function() {
//set opacity to zero if we haven't started fading yet.
if (fading == false) { // Consider `if (!this.Fading)`
oElement.style.opacity = 0;
}
//if we've reached or passed max opacity, stop fading
if (oElement.style.opacity >= 1) {
oElement.style.opacity = 1;
clearInterval(timer);
}
//otherwise, fade
else {
fading = true;
var iCurrentOpacity = parseFloat(oElement.style.opacity);
oElement.style.opacity = iCurrentOpacity + 0.1;
}
}, iSpeed);
};
};
Your code has a lot of problems. The one culpable for the element appearing immediately is that you call setTimeout not with a function but with the result of a function, because Effects.FadeIn will be executed immediately.
setTimeout(function(){Effects.FadeIn(oElement, iSpeed)}, iSpeed);
will probably act as you intend.
But seriously, you probably should not re-invent this wheel. jQuery will allow you to fade elements in and out easily and CSS transitions allow you to achieve element fading with as much as adding or removing a CSS class.
T.J. and MoMolog are both right about the bug: you're invoking the Effects.FadeIn function immediately before passing the result to setTimeout—which means that Effects.FadeIn calls itself synchronously again and again until the condition oElement.style.opacity >= 1 is reached.
As you may or may not know, many UI updates that all take place within one turn of the event loop will be batched together on the next repaint (or something like that) so you won't see any sort of transition.
This jsFiddle includes the suggested JS solution, as well as an alternate approach that I think you may find to be better: simply adding a CSS class with the transition property. This will result in a smoother animation. Note that if you go this route, though, you may need to also include some vendor prefixes.

How to make an icon flash/blink, which is present in a web page

I started working on advanced java few days before(too late to start on that, I know). I am stuck with a specific task of making an icon (which is present on the task bar) blink. This blinking should happen based on a specific condition, which means that it can be achieved using javascript.
I have been searching for a while now but is there a way to make an icon appear and disappear every 1 second or so to bring in the blinking effect ?
HTML
<img src='image/source' alt='blinking!' id='blinking_image' />
Javascript
var img = document.getElementById('blinking_image');
var interval = window.setInterval(function(){
if(img.style.visibility == 'hidden'){
img.style.visibility = 'visible';
}else{
img.style.visibility = 'hidden';
}
}, 1000); //the 1000 here is milliseconds and determines how often the interval should be run.
This creates an anonymous function inside the setInterval that runs every 1 second (1sec == 1000milisec). To see more about setInterval checkout the mdn here on it.
Each time it runs it checks to see if the img is hidden or visible if it's hidden then it shows it if it's visible then it hides it. It does this by checking the style.visiblity property. Which you can learn more about here on the mdn.
Small fix
instead
if(img.display == 'hidden')
use
if(img.style.visibility == 'hidden')
You might find opacity works better because the image is still there, which means it is still clickable if necessary. Also you can add a clear interval to stop the flashing.
var mycounter = 0
interval = window.setInterval(function () {
if (img.style.opacity == '0.1') {
img.style.opacity = '1';
mycounter = mycounter + 1
if (mycounter == 7) {
clearInterval(interval);
}
} else {
img.style.opacity = '0.1';
}
}, 500); //the 1000 here is milliseconds and determines how often the interval

Initializing a repetitive action with Javascript with getTime()

I'm a newb to development, so this may come off as a stupid question, but I figured I'd ask anyway. After all, me looking bad just makes you look better. :)
I want to change the css style on an element based on time. I've tried a few different methods and can get the time to display inside of html, but I can't use the time to trigger other events. I've put this little page together to make things simpler for me.
<html>
<head>
<title>timerTest</title>
<style type="text/css">
#box {
height:200px;
width: 200px;
background-color: red;
}
</style>
</head>
<body onload="maFucktion()">
<div id="box">T</div>
<script type="text/javascript">
var box = document.getElementById('box');
function maFucktion()
{
var d = new Date();
for(i=0; i > 100; ++i)
{
if((d.getTime() % 1000) < 499)
{
box.style.backgroundColor = "blue";
box.innerHTML = d.getTime() % 1000;
}
else
{
box.style.backgroundColor = "red";
box.innerHTML = d.getTime() % 1000;
}
}
}
</script>
</body>
</html>
So, what my little brain tells me this should do is, on page load, execute maFucktion() which should initiate a for loop which:
(1)sets a new Date()
(2)gets the time since january 1 1970 in milliseconds with the getTime() method
(3)breaks it down to the half second with the modulus operator
(4)and delivers a new background color and the division remainder of the condition based on whether the value is between 0-499 or else
I want it to change box.style.backgroundColor every half second which should end up looking like one of those silly banner ads from 1998, but I can't get it to automatically change.
I know a for loop probably isn't the best, but it should at least display a new innerHTML value for #box, right?
You need to use setTimeout() or setInterval() to trigger an action at some time in the future. See here and here for doc.
Looping and checking the time is very, very bad in javascript because it locks up the browser from processing user events.
So to change the background color every half second, you could do this:
var isBlue = false;
var box = document.getElementById('box');
setInterval(function() {
box.style.backgroundColor = isBlue ? "red" : "blue";
isBlue = !isBlue;
}, 500);
You can see a working demo here: http://jsfiddle.net/jfriend00/n5Mhz/.
What you really want to do here is use a timer. Have the timer call the function every 1/2 second:
<script type="text/javascript">
var box = document.getElementById('box');
var clrs = "#ff0000,#0000ff".split(",")
var cPos = 0;
function flipC() {
box.style.backgroundColor = clrs[cPos];
cPos = 1-cPos;
window.setTimeout(flipC,500)
}
flipC()
</script>

Categories

Resources