JavaScript not updating the DOM and crashing the browser - javascript

I have written the following HTML for a button that on click calls a function and the output of the function is written in a div in the DOM. But it is not updating the DOM anyway, but freezing the whole browser tab as well as the HTML page. Please help.
Thank you in advance
let rows = [];
let cols = [];
let secKey = "";
const generateKey = () => {
var count = 0;
while (count != 5) {
let randomNumber = Math.floor((Math.random() * 10));
if (!rows.includes(randomNumber)) {
rows.push(randomNumber);
count++;
}
}
count = 0;
while (count != 6) {
let randomNumber = Math.floor((Math.random() * 10));
if (!cols.includes(randomNumber)) {
cols.push(randomNumber);
count++;
}
}
// put on the document
secKey = `${cols[0]}${rows[0]}${cols[1]}${rows[1]}${cols[2]}${rows[2]}${cols[3]}${rows[3]}${cols[4]}${rows[4]}${cols[5]}`;
document.querySelector("#sec-key").innerHTML = `Your secret key is <strong id="sec-key">${secKey}</strong>`; // #sec-key is a div where I want to show the output
};
Html:
<div class="key-container">
<button id="generate-key" class="util-btn" onclick="generateKey()">Generate new secret key</button>
<p class="key-holder" id="sec-key">
<!--output is expected here-->
</p>
<p id="caution">*please remember the secret key for decryption</p>
</div>

The problem is that upon running the function a second time, the globals likely already include the random values, and so the count variable is never incremented and the loop spins infinitely.
Either initialize the globals inside the function implementation, or use the length of the array instead of a counter. Second approach is shown below:
let rows = [];
let cols = [];
let secKey = "";
const generateKey = () => {
while (rows.length != 5) {
let randomNumber = Math.floor((Math.random() * 10));
if (!rows.includes(randomNumber)) {
rows.push(randomNumber);
}
}
while (cols.length != 6) {
let randomNumber = Math.floor((Math.random() * 10));
if (!cols.includes(randomNumber)) {
cols.push(randomNumber);
}
}
// put on the document
secKey = `${cols[0]}${rows[0]}${cols[1]}${rows[1]}${cols[2]}${rows[2]}${cols[3]}${rows[3]}${cols[4]}${rows[4]}${cols[5]}`;
document.querySelector("#sec-key").innerHTML = `Your secret key is <strong id="sec-key">${secKey}</strong>`; // #sec-key is a div where I want to show the output
};

Related

Shuffle an array of cards on click of a button

I want to be able to click on the button below and shuffle the cards in my card deck.
So far I have created an event listener which when clicked calls the function shuffleCards which takes an array. The array I have passed in is the one provided to me in the exercise which is an array of cards.
Nothing happens when I click on the button, I know it is something to do with scope but I do not know how to amend my code to make this work properly.
Thank you in advance.
HTML
<button type="button" id="shuffle" class="shuffle" class="btn btn-lg btn-secondary">Shuffle</button>
JAVASCRIPT
// Part given in exercise which creates a deck of cards:
const suit = 'hearts';
const cardsWrapper = document.querySelector('.cards-wrapper');
function createCards() {
const cards = [];
// Create an array with objects containing the value and the suit of each card
for (let i = 1; i <= 13; i += 1) {
const cardObject = {
value: i,
suit,
};
cards.push(cardObject);
}
// For each dataObject, create a new card and append it to the DOM
cards.forEach((card, i) => {
const positionFromLeft = i * 15;
const cardElement = document.createElement('div');
cardElement.setAttribute('data-value', card.value);
cardElement.classList.add('card', `${card.suit}-${card.value}`);
cardElement.style.left = `${positionFromLeft}px`;
cardsWrapper.append(cardElement);
});
}
// part written by me
const shufflebtn = document.getElementById('shuffle');
shufflebtn.addEventListener("click", () => {
shuffleCards(cards);
})
function shuffleCards(array) {
var i = 0
, j = 0
, temp = null
for (i = array.length - 1; i > 0; i -= 1) {
j = Math.floor(Math.random() * (i + 1))
temp = array[i]
array[i] = array[j]
array[j] = temp
}
return array
}
made some changes to code where i am not talking about html instead giving a solution for your card shuffle.
created a create cards button which triggers createCards function then, try clicking your shuffle and see console log you can see a shuffled array.
Note: click on create cards Button before you click on shuffle as you might log empty array
Also i changed the scope of cards as it should be accessible to other functions
const suit = 'hearts';
var cards = [];
function createCards() {
for (let i = 1; i <= 13; i += 1) {
const cardObject = {
value: i,
suit,
};
cards.push(cardObject);
}
}
const shufflebtn = document.getElementById('shuffle');
const creatorBtn = document.getElementById('creator');
shufflebtn.addEventListener("click", () => {
cards = shuffleCards(cards);
})
creatorBtn.addEventListener("click", () => {
createCards();
})
function shuffleCards(array) {
var i = 0,
j = 0,
temp = null
for (i = array.length - 1; i > 0; i -= 1) {
j = Math.floor(Math.random() * (i + 1))
temp = array[i]
array[i] = array[j]
array[j] = temp
}
console.log(array)
return array;
}
<button type="button" id="shuffle" class="shuffle" class="btn btn-lg btn-secondary">Shuffle</button>
<button type="button" id="creator" class="creator" class="btn btn-lg btn-secondary">create cards</button>

How do I get Javascript to remember a variable that is reset in my function, yet initially defined outside of my function?

I'm creating a game where the computer tries to guess the user's number based on user feedback like too high or too low. I'm using a binary search. The functions work properly, however, every time the buttons are pressed, the code resets to make the original list from 1 to 100 making the guess 50 instead of remembering the new list and guess defined inside my functions.
var list = new Array();
for (i = 0; i <= 100; i++) {
list.push(i)
}
//console.log(list)
// List is intially an empty array (list). The
// for loop generates integers from
// 0 to 100 and pushes them into the array.
var guess = list[Math.floor((list.length / 2))];
console.log(guess);
var toolow = function(guess) {
while (list.includes(guess) == true) {
list.shift()
};
var guess = list[Math.floor((list.length / 2) - 1)];
console.log(list);
console.log(guess)
}
// toolow(guess)
var toohigh = function(guess) {
var last = parseInt(list.length);
while (list.includes(guess) == true) {
list.pop()
};
var guess = list[Math.round(list.length / 2)];
console.log(list);
console.log(guess)
}
// toohigh(guess)
<h1> Guess Your Number </h1>
<button id="TooLow" onclick="toolow(guess);"> Too Low</button>
<button id="TooHigh" onclick="toohigh(guess);">Too High</button>
your over use of the variable guess is causing all sorts of issues
no need to pass guess from onclick to the function
don't declare a var guess inside the functions
et voila - your code works now
var list = new Array();
for (i = 0; i <= 100; i++) {
list.push(i)
}
//console.log(list)
// List is intially an empty array (list). The
// for loop generates integers from
// 0 to 100 and pushes them into the array.
var guess = list[Math.floor((list.length / 2))];
console.log(guess);
var toolow = function() {
while (list.includes(guess) == true) {
list.shift()
};
guess = list[Math.floor((list.length / 2) - 1)];
console.log(list);
console.log(guess)
}
// toolow(guess)
var toohigh = function() {
var last = parseInt(list.length);
while (list.includes(guess) == true) {
list.pop()
};
guess = list[Math.round(list.length / 2)];
console.log(list);
console.log(guess)
}
// toohigh(guess)
<h1> Guess Your Number </h1>
<button id="TooLow" onclick="toolow();"> Too Low</button>
<button id="TooHigh" onclick="toohigh();">Too High</button>

Trying to generate numbers with eventListener

I want generate random lottery numbers, ranging from 1-59 with 7 numbers showing. They have to generate on the click of a submit button. Im struggling to get it to write to the console log saying random is not defined.
let lottoNum = [];
while (lottoNum.length < 7) {
let random = Math.floor(Math.random() * 59) + 1;
if (lottoNum.indexOf(random) === -1) lottoNum.push(random);
}
let btn = document.getElementById("Button");
button.addEventListener("click", function getNumbers() {
return random;
});
random is not defined
You was close, you should research into scopes however. Try the following:
generateNumbers = () => {
let lottoNum = [];
while (lottoNum.length < 7) {
let random = Math.floor(Math.random() * 59) + 1;
if (lottoNum.indexOf(random) === -1) lottoNum.push(random);
}
return lottoNum;
}
let btn = document.getElementById("Button");
btn.addEventListener("click", function getNumbers() {
const nums = generateNumbers();
console.log(nums);
});
I've put your main code into a function and returned it from said function. From there i've called the function in your click listener and logged them. You can do anything you'd like where i've done console.log however.
The reason you had your "random is not defined" is because you do let random inside your while loop. That means anything that isn't inside of the {} of your while loop cannot read random. hence the function and return :)

Trying to add a conditional to a function, and receiving an error on execution

So, first and foremost, it's important to note that I'm adding a feature to something I didn't design. I'm really new to JavaScript, and I'm trying to edit an existing Discord bot. I discovered that the simplest way to achieve my goal would be to edit the root function at which it generates Random numbers. The relavant snippet of the original code (taken from the dice-expression-evaluator module https://github.com/dbkang/dice-expression-evaluator) is as follows:
Dice.prototype.roll = function () {
var rolls = [];
var sum = 0;
for (var i = 0; i < this.diceCount; i++) {
var roll = random.integer(1, this.sideCount) * this.coefficient;
rolls.push(roll);
sum += roll;
}
return {roll: sum, dice: rolls};
};
This original code works just fine, but doesn't include my desired feature (a simple-but-verbose sort of whitelist.) the 4 variables not defined in that particular code block are rather self-explanatory. My version of the code (slightly edited for privacy reasons) is as follows:
Dice.prototype.roll = function () {
var rolls = [];
var sum = 0;
var range = this.whitelist(); //already tried it with () after whitelist
console.log(range.join(','));
for (var i = 0; i < this.diceCount; i++) {
var roll = random.integer(range[0], range[1]) * this.coefficient; //changed the 2 function arguments, but both are still integers
rolls.push(roll);
sum += roll;
}
return {roll: sum, dice: rolls};
};
Dice.prototype.whitelist = function () {
let user0 = "a";
let user1 = "b";
let user2 = "c";
let user3 = "d";
let user = message.author.id;
let die = this.sideCount;
console.log(user);
console.log(string(die));
if (user==user0) {
var min = Math.ceil(0.76 * die);
var max = die;
} else if (user==user1) {
var min = Math.ceil(0.76 * die);
var max = die;
} else if (user==user2) {
var min = 1;
var max = die;
} else if (user==user3) {
var min = 1;
var max = die;
} else {
var min = 1;
var max = die;
}
return [min, max];
};
The message.author.id variable is available to the function that started the whole function chain 3 scopes up, but in MY version of the code, (even after correcting a few missing semicolons and similarly minute errors) a dice expression that is perfectly functional in the original code generates an "invalid dice expression" error. Other than the introduction of a new variable and the variables in the random.integer call, I see no functional difference between the old and new versions of Dice.prototype.roll. By my understanding, my whitelist function returns an array of integers, and those integers are being injected directly into the random.integer function call in a perfectly reasonable way... I am incredibly confused.

How do I write a for loop that stops at every third index item, and continues inserting items to a new (carousel) page?

I have the following code:
page.listSuccess = function (data, status, xhr) {
console.log(data);
if (data && data.items) {
var itemsQty = Math.ceil(data.items.length / 3);
for (var index = 0; index < itemsQty; index++) {
var itemData = {};
var itemClone = page.insertItemDOM(itemData);
if (index == 0) {
itemClone.addClass("active");
console.log(itemClone);
}
}
}
for (var index = 0; index < data.items.length; index++) {
var testimonialData = {}
testimonialData.title = data.items[index].title;
testimonialData.body = data.items[index].body;
testimonialData.starRating = data.items[index].starRating;
testimonialData.id = data.items[index].id;
page.insertTestimonialDOM(testimonialData);
}
}
At the moment, this code inserts all(5) my testimonials on one page. I need three per page, but I'm unsure as to how to go about it.
itemClone = a page on the carousel
testimonialData = a testimonial
insertItemDOM function =
page.insertItemDOM = function (itemData) {
var newItem = $($("#itemTemplate").html()).clone();
var targetLoc = $('.carousel-inner');
targetLoc.attr("data-target", "true");
targetLoc.append(newItem);
return newItem;
}
insertTestimonialDOM function =
page.insertTestimonialDOM = function (testimonialData) {
var newTemplate = $($("#testimonialTemplate").html()).clone();
newTemplate.find('.title').html(testimonialData.title);
newTemplate.find('.body').html(testimonialData.body);
newTemplate.find('.starRating').html(testimonialData.starRating);
var targetLoc = $('.carousel-inner');
targetLoc.attr("data-target", "true");
targetLoc.append(newTemplate);
}
Let me explain the concept for you. What you want is after every 3 loop execution the loop shall work it again and enter details in a new page.
Let's make two function.
var index;
var theinitial = function(z)
{
index = z
var counter = 1;
insertionfunction();
}
var insertionfunction = function()
{
for (var zzz = index; zzz < data.items.length; zzz++) {
if (counter <= 3)
{
itemClone = page.insertItemDOM(itemData);
}
else
{
theinitial(zzz);
}
}
Here the first request you make to 'theinitial function' with 1 as value of z then the function will call the insertion function and now the loop will run for 3 times then after three times the value of zzz is used to call the initial function again. Now your index is 4, hence the loop will start from 4th element and run for 3 more times as counter is reinitialized to 1.
I don't really know how your page insertion thing works therefore I am explaining the concept to you.

Categories