how to refresh two functions without reloading the page in html - javascript

i need to refresh the blockrandompos and animblock without refreshing the page
var player = document.getElementById("player");
var block = document.getElementById("block");
function goleft(argument) {
player.classList.add("animatel");
setTimeout(function() {
player.classList.remove("animatel");
}, 1);
console.log("left");
}
function goright(argument) {
player.classList.add("animater");
console.log("right");
}
function blockrandompos(argument) {
var block3 = document.getElementById("block");
var posleftblock = Math.floor(Math.random() * 370) + 1; //random numbers from 200 to 300 pos
var info = block3.setAttribute("style", "width:30px; height:30px; position: relative; left:" + posleftblock + "px;"); //block settings
console.log(posleftblock);
}
function animblock(argument) {
block.classList.add("animationblock");
console.log(block.classList);
}
blockrandompos()
animblock()

You are probably looking for an event and subsequently an event-listener that can call a function when the event takes place. Beyond onLoad and onClick, there are a crazy amount of events that you can use.
https://developer.mozilla.org/en-US/docs/Web/Events
So the question is, when do you want to run your functions exactly? Maybe we can help tell you which event to use.

Related

if/else and setInterval

<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 :).

Vanilla JS + VueJS: Scroll to top of div on button click

I have an app created using VueJS. It is a multistep form with a next button.
You can view the app working here:
https://staging.evbox.com/configurator.html
The issue I am trying to solve, is once the user clicks the next button, the top of the following question is visible. Can someone help me with a vanilla JS solution or some advice?
The button html:
<button class="button-container__next" type="button" #click="goToNextStep()">Next</button>
And the function is:
goToNextStep: function () {
this.currentStep++
}
It seems that the scrollbar is for body. So you can do this:
goToNextStep: function () {
this.currentStep++;
window.scrollTo(0, 0);
}
If the main scrollbar is not attached to the body, try two following lines:
document.body.scrollTop = 0; // For safari
document.documentElement.scrollTop = 0;
I solved it by doing the following. I found this script but I have to be honest im not really sure how it works. Can someone explain it to me?
goToNextStep: function () {
this.currentStep++
let myDiv = document.getElementById('wrapper');
scrollTo(document.body, myDiv.offsetTop, 100);
function scrollTo(element, to, duration) {
if (duration < 0) return;
var difference = to - element.scrollTop;
var perTick = difference / duration * 2;
setTimeout(function() {
element.scrollTop = element.scrollTop + perTick;
scrollTo(element, to, duration - 2);
}, 10);
}
}
I also added this to the CSS:
html { height: 100%; overflow:auto!important; }
body { height: 100%!important; }

Make EventListener only fire once, without removing it - No jQuery

Okay so I have the following line of code...
window.addEventListener("scroll", sHeader);
function sHeader(){
var yPosition = window.pageYOffset;
if ( yPosition = > 5 ){
header.className += ' shorter';
}
}
...which enables me to change the styles of my header after scrolling. However, it continues to fire unnecessarily as I scroll further down the page, consequently adding more "shorter" to the class attribute for "header" in HTML; like this:
<header class=" shorter shorter shorter shorter shorter shorter shorter...">
I understand using the following code eliminates this...
window.addEventListener("scroll", sHeader);
function sHeader(){
var yPosition = window.pageYOffset;
if ( yPosition = > 5 ){
header.style.height = "60px";
}
}
...however, I just don't like the look of it in HTML after executing, like this:
<header style="height: 60px;">
Is there any way, without using jQuery, that I can make the provided eventListener fire only once without having to remove it, since it is required again if the yPosition becomes less than 5px (header reverts back to original styles) and a user then decided to scroll back down the page again in the same session.
Thank you in advance!
As you describe the situation, you don't need to fire the event once. There are few ways to solve your problem.
Way 1
Use .classList.add instead of .className += to avoid class="shorter shorter shorter shorter shorter shorter shorter...".
window.addEventListener("scroll", sHeader);
function sHeader() {
var yPosition = window.pageYOffset;
if (yPosition >= 5){
header.classList.add('shorter');
} else {
header.classList.remove('shorter');
}
}
The classList property works in IE ≥ 10, but you can use a polyfill.
Way 2
Add a variable which remembers whether the header is shortened and check it in the event listener.
window.addEventListener("scroll", sHeader);
var isHeaderShorter = false;
function sHeader() {
var yPosition = window.pageYOffset;
var shouldBeShorter = yPosition >= 5;
// Checking whether the header should be changed
if (shouldBeShorter === isHeaderShorter) {
return;
}
if (shouldBeShorter) {
header.className += ' shorter'
} else {
header.className = header.className.split(' shorter').join('');
}
isHeaderShorter = shouldBeShorter;
}
{once: true} triggers event only once
window.addEventListener("scroll", sHeader, {once: true});

onmousedown/onmouseup function not working

I have a rectangle I am trying to move using javascript. I can get it to move left and right using functions, but when I hold the mouse down it doesn't continue to move. Here is my html code:
<button onmousedown="moveLeft();" onmouseup="stopMove();">LEFT</button>
<button onmousedown="moveRight();"
onmouseup="stopMove();">RIGHT</button><br><br>
Here is my javascript code (the conditional statements are just so the rectangle doesn't move off of the canvas):
function moveLeft () {
xx-=20;
if (xx<0) {
xx=0;
}
}
function moveRight() {
xx+=20;
if (xx>400) {
xx=400;
}
}
function stopMove () {
xx+=0;
}
When you press a mouse button, the mousedown event will fire just once. It does not continuously fire while you have the button held down. What you'll need to do is use a timer to begin the movement and then, on mouseup, stop the timer.
Also, don't use inline HTML event handlers (onmouseover, onmouseout, etc.). Here's why.
Lastly, since your moveLeft and moveRight functions are essentially the same thing, they can be combined into one function that simply takes in an argument that determines the direction.
Here's a working example:
// Get references to the HTML elements you'll need to interact with:
var btnLeft = document.getElementById("btnLeft");
var btnRight = document.getElementById("btnRight");
var box = document.getElementById("box");
// Set up event handlers for the HTML elements in JavaScript, using modern
// standards, not in the HTML. Both the left and right buttons need to
// call the same function, but with a different argument value. This is
// why the events are being bound to another function that wraps the actual
// call to the move function (so that an argument can be passed).
btnLeft.addEventListener("mousedown", function(){ move(-20); });
btnRight.addEventListener("mousedown", function(){ move(20); });
btnLeft.addEventListener("mouseup", stopMove);
btnRight.addEventListener("mouseup", stopMove);
// The counter needs to be accessible between calls to move
var xx = 0;
// We'll start an automatic timer, but we'll need to stop it later
// so we need a variable set up for that.
var timer = null;
// Only one function is needed to address the move operation
// The argument is what determines the direction
function move(amount) {
// Stop any previous timers so that we don't get a runaway effect
clearTimeout(timer);
xx += amount;
// Check the new position to see if it is off the visible page
if (xx < 0){
xx = window.innerWidth;
} else if(xx > window.innerWidth){
xx = 0;
}
// Just displaying the current value
box.textContent = xx;
// Move the box to the new location
box.style.left = xx + "px";
// Run the timer after a 250 millisecond delay and have
// it call this function again. Assign the variable to
// the timer.
timer = setTimeout(function() { move(amount) }, 250);
}
function stopMove () {
xx += 0;
// Stop the timer
clearTimeout(timer);
}
#box {
background-color:blue;
border:2px solid black;
color:yellow;
text-align:center;
font-weight:bold;
padding-top:.5em;
margin-top:3em;
/* Everything above is just for display and not actually needed.
But in order to move the box and to be able to have a consistent
size for it, the following is required: */
position:absolute;
height:50px;
width:50px;
}
<button id="btnLeft">LEFT</button>
<button id="btnRight">RIGHT</button>
<div id="box"></div>
Since the mouse evet does not fire while it is down, you need to fire the event manually until you detect the other event. So to do this, you need to either use setInterval or setTimeout
var moveTimer,
xx = 200;
function move (dir) {
xx+=20*dir;
if (xx<0) {
xx=0;
} else if (xx>400) {
xx=400
}
stopMove()
moveTimer = window.setTimeout(move.bind(this,dir), 100)
document.getElementById("out").value = xx;
}
function stopMove () {
if(moveTimer) window.clearTimeout(moveTimer);
moveTimer = null
}
window.addEventListener("mouseup", stopMove)
<button onmousedown="move(-1);">LEFT</button>
<button onmousedown="move(1);">RIGHT</button>
<input type="number" id="out"/>

Fixing the animation properties

I am doing some research at the moment into creating a new maths game for primary school children where divs from 0-9 appear at random inside a container.
A question is given at the beginning. Something like, multiples of 20. The user will then have to click on the correct ones, and they will then be counted at the end and a score will be given.
I have just changed the speed in which the divs appear so that they appear for longer and more than one at a time to make the game easier for younger children.
I used "fadeIn" like so..
$('#' + id).animate({
top: newY,
left: newX
}, 'slow', function() {}).fadeIn(2000);
}
My problem is that now when I shoot the correct or incorrect number the animation is very glitchy and I cannot figure out why.
Fiddle: http://jsfiddle.net/cFKHq/6/ (See version 5 to see what it was like before)
Inside startplay(), control the concurrency when calling scramble() , I do it with a global var named window.cont, so I replaced your following call:
play = setInterval(scramble, 1800);
for this one:
play = setInterval(function() {
if (window.cont){
window.cont = false;
scramble();
}
}, 1000);
The var window.cont needs to be set globally at the start of your code, like so:
var miss = 0;
var hit = 0;
var target = $("#target");
window.cont = true;
So with window.cont you now can control that animations are executed one after another, without overlapping, like so:
$('#'+id).css({
top: newY,
left: newX
}).fadeIn(2000, function() {
setTimeout(function() {
$('#' + id).slideUp('fast');
window.cont = true;
}, 1500);
});
See working demo

Categories

Resources