I am new to JavaScript and just here asking for some guidance and best practice questions:
I want the letters of the alphabet to be in an interval upon the press of a button. I seem to have the entire alphabet aspect of this project answered. But I now want separate buttons to control specific sets of letters. I tried to use the same functions and code for the vowels and other sets of letter but they only go through an interval once and stop.
Here my javascript code:
var allLetters = "abcdefghijklmnopqrstuvwxyz".split("");
var vowels = 'aeiouy'.split('');
// start button function
let start = 0;
startButton.addEventListener("click", function () {
for (y = 0; y < allLetters.length; y++) {
setTimeout(() => getRandom(allLetters), y * 1000);
}
});
function getRandom (letters) {
var randomSet = letters[Math.floor(Math.random() * allLetters.length)];
console.log('set random', randomSet)
document.getElementById("demo3").innerHTML = randomSet;
};
// function that assigns entire alphabet
function setRandomLetter() {
var letter = allLetters[Math.floor(Math.random() * allLetters.length)];
console.log('setRandom ', letter)
document.getElementById("demo3").innerHTML = letter;
}
If I understand what you're asking, you want startButton to cycle through all of the letters in the "allLetters" variable, and then you want another button on the page to cycle through another set of letters, for instance the letters in the "vowels" variable. Is that it?
Assuming that's what your asking, I think the problem is in the first line of the getRandom() function. You're passing in letters as a parameter, but you're taking the length of allLetters. Change this...
var randomSet = letters[Math.floor(Math.random() * allLetters.length)];
...to this...
var randomSet = letters[Math.floor(Math.random() * letters.length)];
...and see if that fixes things.
Related
new to JS here and was wondering if someone could guide me on how I can pause and delete when implementing a typewriter effect in JavaScript.
I've got a function that successfully types out each word in an array, however I would like it to pause after typing each word and backspace or delete the letters before typing the next one.
//counter
var i = 0;
var index = 0;
var texts = ['Salesforce Consultant', 'Developer', 'Writer'];
var speed = 110;
let letter = '';
let currentText = '';
let delay = 25;
function typeWriter() {
//If counter is less than the # of letters in txt, reset array of words
if (i === texts.length) {
i = 0;
}
//Use count to select text to display
currentText = texts[i];
letter = currentText.slice(0, ++index);
document.querySelector("#demo").textContent = letter;
//If letters displayed are the same number of letters in the current text
if (letter.length === currentText.length) {
//Pause before deleting
//Delete letters in word
//Word is done displaying, and reset letters on screen
i++;
index = 0;
}
setTimeout(typeWriter, speed);
}
typeWriter();
<div id="demo"></div>
HTML
<div class="centered">
<div class="intro">
<p>A </p>
<p class ="typing" id="demo"></p>
</div>
</div>
You can do this by introducing a variable that determines how the index will change (+1 or -1). The different delay is just a different argument to setTimeout.
I would also suggest converting some global variables into function parameters: that way they are better (more narrowly) scoped. The change that these variables get, can be managed by what you let setTimeout pass on to the next call.
Here is how that could work:
const texts = ['Salesforce Consultant', 'Developer', 'Writer'];
const speed = 110;
const pause = 800; // <--- the longer delay between text direction changes
function typeWriter(i=0, index=1, direction=1) {
let displayed = texts[i].slice(0, index);
document.querySelector("#demo").textContent = displayed;
if (displayed.length >= texts[i].length) { // start removing after pause
setTimeout(() => typeWriter(i, index-1, -1), pause);
} else if (displayed.length === 0) { // go to next text after pause
setTimeout(() => typeWriter((i+1) % texts.length), pause);
} else { // continue in the current direction
setTimeout(() => typeWriter(i, index+direction, direction), speed);
}
}
typeWriter();
<div id="demo"></div>
I've been trying to get display a bunch of letters that continuously change. They only change each time I reload the page. Please help.
const action = false;
var i = 0;
function randomized() {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const still = document.getElementById('c1');
const still2 = [document.getElementById('c1'),document.getElementById('c2'),document.getElementById('c3'),document.getElementById('c4'),document.getElementById('c5'),document.getElementById('c6'),document.getElementById('c7'),document.getElementById('c8'),document.getElementById('c9'),document.getElementById('c10'),document.getElementById('c11'),document.getElementById('c12')]
while (action === false) {
i++;
var letter = possible.charAt(Math.floor(Math.random() * possible.length));
still2[i].innerHTML = letter;
}
/*for(var i = 0; action === false; i++){
var letter = possible.charAt(Math.floor(Math.random() * possible.length))
still2[i].innerHTML = letter;
};*/
}
As mentioned in another answer the while loop will lock the main thread and it will never render anything. I suggest using the requestAnimationFrame() function to queue the updates for the elements.
Below is a proof of concept you can adapt to your specific case:
A function to generate the random character
User global <span> selector for simplicity
A function to loop through the elements, update their content and queue the next frame indefinitely.
For the demo purposes stop the loop after 2 seconds. Note how the last frame animation is logged and used to then stop the infinite loop.
// Generate random letter
function randomLetter() {
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
return possible.charAt(Math.floor(Math.random() * possible.length));
}
// Id to stop the animation frame loop
let animationId = 0;
// Update all nodes at the same time
function updateNodes() {
// List all nodes to update
let nodes = document.getElementsByTagName('span');
for (let i = 0; i < nodes.length; i++) {
nodes[i].innerHTML = randomLetter();
}
// Queue the next update
animationId = requestAnimationFrame(updateNodes);
}
// Start the animation loop
animationId = requestAnimationFrame(updateNodes);
// Stops animation after 2 seconds
setTimeout(function(){
cancelAnimationFrame(animationId);
}, 2000);
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
Call your page load method inside window.onload and use localStorage
window.onload = function() {
randomized(localStorage.getItem("randomString"));// Retrieve
}
function randomized(preRandomString){
// Store and update localStorage
return prvRandomString + localStorage.setItem("randomString", "abc123");
}
The while loop locks the thread and prevents the page from rendering each of your letters. Try setInterval() or similar asynchronous loop to release the thread and show each new letter:
function setRandomLetter() {
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const still = document.getElementById('c1');
const letter = possible.charAt(Math.floor(Math.random() * possible.length));
still.innerText = letter;
}
// set a random letter every second
setInterval(setRandomLetter, 1000);
<span id="c1"></span>
I am very new to JavaScript and I'm sure this question has been answered quite a bit, but when I search my question I don't seem to find an answer (or one that I actually understand :D)
Currently, I'm trying to create a tool to help kids with there multiplication facts and I'm having trouble getting the program to generate new random numbers.
var r1 = Math.floor(Math.random() * 13);
var r2 = Math.floor(Math.random() * 13);
function start() {
println("Welcome to the multipilcation helper! ");
var num = readLine("Pick a number you want to practice or type 'random'!");
var ques = readLine("How many questions do you want?");
if (num == "random") {
for (var i = 0; i < ques; i++) {
var answer = r1 * r2;
println(r1 + "*" + r2);
var check = readLine("what is the answer");
if (check == answer) {
println("thats correct!");
} else {
println("thats wrong! ");
}
}
}
}
The problem is that my variables seem to pick a random number as soon as the script starts and stick with it instead of giving me a new random number.
Can anyone help me out and tell me how to get a new random number every time the variable is called?
Simply create yourself a method like the one below and use it like r() to get a new random number every call.
function r() {
return Math.floor(Math.random() * 13);
}
console.log(r());
console.log(r());
console.log(r());
In your loop you should be reassigning the random numbers so that they are reassigned every iteration of the loop. Otherwise they stay static to the value you give them at the top.
Also, you should use triple equals in Javascript when checking for equality as it is best practice.
function start() {
console.log("Welcome to the multipilcation helper! ");
var num = prompt("Pick a number you want to practice or type 'random'!");
var ques = prompt("How many questions do you want?");
if (num == "random") {
for (var i = 0; i < ques; i++) {
var r1 = Math.floor(Math.random() * 13);
var r2 = Math.floor(Math.random() * 13);
var answer = r1 * r2;
console.log(r1 + "*" + r2);
var check = prompt("what is the answer");
if (check == answer) {
console.log("thats correct!");
} else {
console.log("thats wrong! ");
}
}
}
}
start()
You random numbers are being static at the moment. They need to be called again. Move your r1 and r2 assignments inside the for.
I don't have enough reputation to comment, but will update the answer
if you explain it with more details.
You need to put the random call in a function in order for it to create a new number each time. When you assign it directly to a variable as you have, it only runs once and stores that value in the variable.
// pick a number between 0 and 13
var random = function() {
return Math.floor(Math.random() * 13);
}
function start(){
for(var i = 0; i < 15; i++){
// call random function for each number and store in a var
var number1 = random();
var number2 = random();
var answer = number1 * number2;
console.log('equation:', number1 + '*' + number2);
console.log('answer:', answer);
}
}
// call the start function
start()
In the below code, I want to function 2 to change the text in text to complete the cycle. Unfortunately var rand will not change text into being a different word. Rather it will always remain same the whole time.
var x = 0;
function function1() {
document.getElementById("text").textContent = rand;
}
function function2() {
if (document.getElementById("text").innerHTML === "Red") {
x += 1;
document.getElementById("text2").textContent = x;
function1();
}
}
//I have got the equivalent functions for blue, green and gold as well
var randomarray = ['Red', 'Blue', 'Green', 'Gold', ];
var rand = randomarray[Math.floor(Math.random() * randomarray.length)];
Can someone please show me how to fix this.
Move the declaration of rand to inside function1. That way it does indeed chose
a again a color each time function1 is called
function function1() {
var rand = randomarray[Math.floor(Math.random() * randomarray.length)];
document.getElementById("text").textContent = rand;
}
and comment out (or remove) the declaration you have outside both functions as it becomes irrelevant.
//var rand = randomarray[Math.floor(Math.random() * randomarray.length)];
I use a function that randomly selects another function, which works.
But sometimes it runs the same function twice or even more often in a row.
Is there a way to prevend this?
My current code:
window.setInterval(function(){
var arr = [func1, func2, func3],
rand = Math.floor(Math.random() * arr.length),
randomFunction = arr[rand];
randomFunction();
}, 5000);
Pretty simple so far. But how do I prevent func1 (for example) to run twice in a row
You can simply store the index of the last function called and the next time, get a random number which is not the last seen index, like this
var lastIndex, arr = [func1, func2, func3];
window.setInterval(function() {
var rand;
while ((rand = Math.floor(Math.random() * arr.length)) === lastIndex) ;
arr[(lastIndex = rand)]();
}, 5000);
The while loop is the key here,
while ((rand = Math.floor(Math.random() * arr.length)) === lastIndex) ;
Note: The ; at the end is important, it is to say that the loop has no body.
It will generate a random number and assign it to rand and check if it is equal to lastIndex. If they are the same, the loop will be run again till lastIndex and rand are different.
Then assign the current rand value to the lastIndex variable, because we dont't want the same function to be called consecutively.
How about a simple check to prevent picking an index that matches the previous pick?
var arr = [func1, func2, func3, ...];
var previousIndex = false;
var pickedIndex;
if (previousIndex === false) { // never picked anything before
pickedIndex = Math.floor(Math.random() * arr.length);
}
else {
pickedIndex = Math.floor(Math.random() * (arr.length - 1));
if (pickedIndex >= previousIndex) pickedIndex += 1;
}
previousIndex = pickedIndex;
arr[pickedIndex]();
This will pick a random function in constant time that is guaranteed to be different from the previous one.
You can select random values from 0-1. And after every run, swap the recently executed function in the array with the last element in the array i.e. arr[2].
var arr = [func1, func2, func3];
window.setInterval(function(){
var t, rand = Math.floor(Math.random() * (arr.length-1)),
randomFunction = arr[rand];
t = arr[rand], arr[rand] = arr[arr.length-1], arr[arr.length-1] = t;
randomFunction();
}, 5000);