Counter not working in jQuery - javascript

I am trying to run my counter for 3 times. once I reach 3 tries the button is supposed to be disabled. I tried couple variations of this solution to no avail. the issue is right on my rollItAgain function. I have my counter starting at 3, and a for loop with an if statement inside. I am also running my randomFunction() inside my if statement, not sure if this is good practice. As of now, I only click reroll once and it gets disabled. I would like it to run at least 3 times.
// 'use strict';
var array = [];
var random = Math.ceil(Math.random() * 9);
var newStars = "<div class='star'><img src='http://i.imgur.com/kXH65I7.png'></div>";
$(document).ready(init);
function init(){
for (var i = 0; i < random; i++){
$('#starbox').append(newStars);
//Create Event Handler for selectNumbers Function
}
$('.numbers').click(selectNumbers);
$('#checked').click(confirm);
$('.numbers').click(toggleButton);
$('#playagain').click(playItAgain);
$('#reroll').click(rollItAgain);
}
function randomFunction(){
$('#starbox').empty();
random = Math.ceil(Math.random() * 9);
for (var i = 0; i < random; i++){
$('#starbox').append(newStars);
}
}
//selectNumbers function
function selectNumbers(){
var num = $(this).text();
// $(this).css('background-color', 'red');
array.push(num);
// console.log(array);
sum = array.reduce(function(a, b){
return Number(a) + Number(b);
});
console.log(sum);
//Check if numbers has select class
console.log(num);
}
function toggleButton(){
$(this).toggleClass('select');
}
function confirm(){
if (sum === random){
$('#displayResult').append("Correct!");
// $('.select').css('display', 'none');
} else {
$('#displayResult').append("Wrong, try again!!");
}
$('.select').remove();
}
function rollItAgain(){
// debugger;
var counter = 3;
// debugger;
for (var j = 0; j < counter; j++){
if(j === counter){
randomFunction();
counter++;
} else {
$('#reroll').attr('disabled', 'disabled');
}
}
}
function playItAgain(){
location.reload();
}
#numberbox {
width: 400px;
height: 100px;
border: 2px solid green ;
}
.numbers {
height: 100px;
width: 100px;
background-color:transparent;
border: 2px solid #000;
margin: 5px;
line-height: 100px;
display: inline-block;
border-radius: 50%;
text-align: center;
border: 2px solid #000;
font-size: 30px;
}
#starbox {
min-height: 300px;
min-width: 400px;
background-color:transparent;
border: 2px solid #000;
margin:100px 100px;
}
.star {
display: inline-block;
}
.select {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Mathgame1</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="https://code.jquery.com/jquery-2.2.1.min.js"></script>
<script src="main.js"></script>
</head>
<body>
<div id="starbox"></div>
<p id="displayResult"></p>
<table id="numberbox" >
<button id="playagain">Play it Again</button>
<button id="checked">checked</button>
<button id="reroll">reroll</button>
<tr >
<td class="numbers">1</td>
<td class="numbers">2</td>
<td class="numbers">3</td>
</tr>
<tr >
<td class="numbers">4</td>
<td class="numbers">5</td>
<td class="numbers">6</td>
</tr>
<tr >
<td class="numbers">7</td>
<td class="numbers">8</td>
<td class="numbers">9</td>
</tr>
</table>
</body>
</html>

Ask yourself why wouldn't this code run through three times? That's what a loop does. What you're really wanting is not a loop but just a counter. The thing that triggers the rolling is the click events, not a counting loop.
First off, you are misapplying a few concepts. You have a counter variable which looks to actually represent the counter maximum. j is more appropriately called your counter. But you need to keep track of the counter value between calls to rollItAgain, so declare it outside of your function. Then increment the counter whenever rollItAgain is called. You don't have to write a loop because the clicking of the button will take care of calling the function multiple times. Secondly, change your check; you want to run the random function when the counter is less than the limit:
var counter = 0;
var limit = 3;
function rollItAgain(){
if (counter < limit) {
randomFunction();
counter++;
} else {
$('#reroll').attr('disabled', 'disabled');
}
}

The problem in your code is that you never get to condition if(j === counter){ to roll dice because your iteration only goes as far as while j < counter. So this never happens.
Rewrite your function to as below, check demo - Fiddle:
function rollItAgain() {
// debugger;
var counter = 3;
// debugger;
for (var j = 0; j <= counter; j++) {
if (j < counter) {
randomFunction();
} else {
$('#reroll').attr('disabled', 'disabled');
}
}
}

Related

Sequential animations on HTML element

guys. I'm trying to create a group of sequential "animations" through css classes on my buttons, but i keep getting a problem where all my buttons receive the effect on the same time and not one after another.
The function playAllSequence should hightlight each button one after another following the sequence present in an array.
I've already tried to put the setTimeOut function inside a closure and tried changed my declaration to let instead of var.
What am i missing?
Thanks in advance
// Get number of buttons on the document
var numberOfButtons = document.querySelectorAll(".btn").length;
var collectionButtonsClicked = [];
var collectionOfRandomColors = [];
var buttonsColors = ["blue", "green", "red", "yellow"];
var gameTitle = document.querySelector("#level-title");
// detecting clicks on the buttons
for ( let i = 0; i < numberOfButtons; i++) {
document.querySelectorAll(".btn")[i].addEventListener("click", function () {
collectionButtonsClicked.push(this.id);
// call click animation function
clickAnimation ();
// Only checks when arrays have the same length so the user have to click all the sequence again
if (collectionButtonsClicked.length === collectionOfRandomColors.length) {
checkClick();
}
})};
// detecting button press to start the game
document.addEventListener("keydown", function (event) {
if (event.key === "a") {
gameTitle.innerHTML = "Game Started";
generateRandomColor();
playAllSequence();
}
});
// check if the click is correct
function checkClick () {
// if correct - Generate new color, disable buttons and play the sequence on all buttons
let arrayRandomStringfied = JSON.stringify(collectionOfRandomColors);
let arrayClickedStringfied = JSON.stringify(collectionButtonsClicked);
if (arrayRandomStringfied === arrayClickedStringfied) {
generateRandomColor();
playAllSequence();
console.log("acertou!")
// erasing click array so the player has to click all the color again
collectionButtonsClicked = [];
} else {
//call fail animation function
failAnimation();
// function to reset the arrays and the title
restartGame();
console.log("errou!")
}
}
//Generate random color and return array - User will have to follow this colors
function generateRandomColor () {
let randomIndex = Math.floor(Math.random() * 4);
collectionOfRandomColors.push(buttonsColors[randomIndex]);
return collectionOfRandomColors;
}
function playAllSequence () {
// disabling all buttons
for ( let i = 0; i < numberOfButtons; i++) {
document.querySelectorAll(".btn")[i].disabled = true;
}
for ( let i = 0; i < collectionOfRandomColors.length; i++ ) {
doSetTimeOut(i);
}
// Enabling all buttons again
for ( let i = 0; i < numberOfButtons; i++) {
document.querySelectorAll(".btn")[i].disabled = false;
}
}
function doSetTimeOut (i) {
let activeButton = document.querySelector("." + collectionOfRandomColors[i]);
// Add pressed effect
activeButton.classList.add("pressed");
// Remove pressed effect after 1 second
setTimeout(function() {
activeButton.classList.remove("pressed")
}, 1000);
}
function clickAnimation () {
}
function failAnimation () {
}
function restartGame () {
collectionOfRandomColors = [];
collectionButtonsClicked = [];
gameTitle.innerHTML = "Press A key to Start";
}
body {
text-align: center;
background-color: #011F3F;
}
#level-title {
font-family: 'Press Start 2P', cursive;
font-size: 3rem;
margin: 5%;
color: #FEF2BF;
}
.container {
display: block;
width: 50%;
margin: auto;
}
.btn {
margin: 25px;
display: inline-block;
height: 200px;
width: 200px;
border: 10px solid black;
border-radius: 20%;
}
.game-over {
background-color: red;
opacity: 0.8;
}
.red {
background-color: red;
}
.green {
background-color: green;
}
.blue {
background-color: blue;
}
.yellow {
background-color: yellow;
}
.pressed {
box-shadow: 0 0 20px white;
background-color: grey;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Simon</title>
<link rel="stylesheet" href="styles.css">
<link href="https://fonts.googleapis.com/css?family=Press+Start+2P" rel="stylesheet">
</head>
<body>
<h1 id="level-title">Press A Key to Start</h1>
<div class="container">
<div class="row">
<div type="button" id="green" class="btn green">
</div>
<div type="button" id="red" class="btn red">
</div>
</div>
<div class="row">
<div type="button" id="yellow" class="btn yellow">
</div>
<div type="button" id="blue" class="btn blue">
</div>
</div>
</div>
<script src="index.js" charset="utf-8"></script>
</body>
</html>
Well, I don't see your sample code to animate even the first button.
If you need independent separate events to happen '1 by 1' visually, you might use a i*1000 as a setTimeout second argument.
If not, here's the code doing something close to what you want to achieve, i believe. Define a function that sets the props you need (box-shadow in this example) for an element taken by index, and sets timeout for a function that will remove the props and call the first function again with the next index:
function animateBtnsSequence( i ){
var btns = document.querySelectorAll(".btn");
btns[i].style.boxShadow = '0 0 20px 1px white';
window.setTimeout(function(){
btns[i].style.boxShadow = '';
if( btns[i+1] )
animateBtnsSequence( i + 1 );
}, 1000)
}
function playAllSequence () {
animateBtnsSequence( 0 );
}

TicTacToe checkwin if statement does not go through even when conditions are met

<h1>TicTacToe!</h1>
<table>
<tr>
<td class="cell left"id="0"></td>
<td class="cell "id="1"></td>
<td class="cell"id="2"></td>
</tr>
<tr>
<td class="cell left"id="3"></td>
<td class="cell"id="4"></td>
<td class="cell"id="5"></td>
</tr>
<tr>
<td class="cell left"id="6"></td>
<td class="cell"id="7"> </td>
<td class="cell"id="8"></td>
</tr>
</table>
body {
font-family: system-ui;
background: #ffffff;
color: black;
text-align: center;
}
td {
border: 2px solid black;
height: 100px;
width: 100px;
cursor: pointer;
}
table {
margin-left: auto;
margin-right: auto;
border-collapse: collapse;
font-size: 20px;
}
table tr:first-child td {
border-top: 0;
}
table tr:last-child td {
border-bottom: 0;
}
table tr td:first-child {
border-left: 0;
}
table tr td:last-child {
border-right: 0;
}
td:hover{background-color: #99e6ff ;opacity: 0.3;}
cells = document.querySelectorAll('.cell');
player = "X";
ai = "O";
function startgame(){
console.log(cells[2].innerText);
for (var i = 0; i < 9; i++){
cells[i].innerText = "";
cells[i].addEventListener("click",add_text);
}
}
function add_text(cell){
document.getElementById(cell.target.id).innerText = player;
if(checkwin()){
console.log("Game over");
}
}
function checkwin(){
for(var i = 0; i < 7; i+=3){
console.log("i",cells[i].innerText);
console.log("i 1 ",cells[i+1].innerText);
console.log("i 2",cells[i+2].innerText);
console.log(player);
if(cells[i].innerText == cells[i+1].innerText == cells[i+2].innerText == player){
console.log("S");
return True;
}
for(i = 0; i < 3; i++){
if(cells[i].innerText == cells[i+3].innerText == cells[i+6].innerText == player){
console.log("S");
return True;
}
}
for(i = 0; i < 3; i+=2) {
if(cells[i].innerText == cells[5].innerText == cells[i+6].innerText == player){
console.log("S");
return True;
}
}
}
}
startgame();
You might be able to access the pen with this link https://codepen.io/mark3334/pen/WNjXoOL?editors=0011. I don't understand why the check win function doesn't work. After clicking on the table the script does console.log on the innertext and it all shows up as "X" yet the if statement doesn't go through. Also for the event listener I don't get why there's no brackets I heard that for events you're not supposed to and something to do with calling a function and referencing the object but I don't really get it.
I see two basic problems:
Your inner loops are reusing i, which will prevent the outer loop from running through all desired values of i.
Your comparisons are wrong, e.g.:
if(cells[i].innerText == cells[5].innerText == cells[i+6].innerText == player){
This evaluates to:
if(((cells[i].innerText == cells[5].innerText) == cells[i+6].innerText ) == player){
The first expression (cells[i].innerText == cells[5].innerText) evaluates to a Boolean (true or false), which is then compared to a string (cells[i+6].innerText), which gives you an erroneous result.
Instead, to compare multiple values you must create multiple comparisons and join them with && (logical "and"):
if(
cells[i].innerText == cells[5].innerText
&&
cells[i].innerText == cells[i+6].innerText
&&
cells[i].innerText== player
){
You'll need to make this change to all three comparisons.

Why I have NaN on Node.js?

I'm making a bulletin board now. Above is the template code for it, where page function has NaN. What is the reason for this error, and how should I fix it?
The code below is written in node.js.
module.exports = {
HTML:function(title, board, control, page){
return `
<!DOCTYPE html>
<html>
<head>
<title>${title}</title>
<meta charset="utf-8">
<style type="text/css">
ul.board, ol.board {
list-style: none;
margin: 0px;
padding: 5px;
}
form {
display: inline;
}
table.type09 {
border-collapse: separate;
text-align: left;
line-height: 2;
}
table.type09 thead th {
padding: 10px;
font-weight: bold;
vertical-align: top;
color: #369;
border-bottom: 3px solid #003699;
}
table.type09 tbody th {
width: 150px;
padding: 10px;
font-weight: bold;
vertical-align: top;
border-bottom: 1px solid #ccc;
background: #f3f6f7;
}
table.type09 td {
width: 350px;
padding: 10px;
vertical-align: top;
border-bottom: 1px solid #ccc;
}
</style>
</head>
<body>
<div id="board">
<table class="type09">
<thead>
<tr>
<th>제목</th>
<th>작성자</th>
<th>날짜</th>
<th>조회수</th>
</tr>
</thead>
<tbody>
${board}
</tbody>
</table>
${control}
</div>
${page}
</body>
</html>`;
},board: function (lifeboards) {
var board = ``;
for (i = 0; i < lifeboards.length; i++) {
var article = lifeboards[i];
var titleBold = article.titleBold;
board += `<tr>`;
if(titleBold == "1") {
board += `<td> <b><공지>${article.title}</b> </td>`;
board += `<td>${article.writer}</td>`;
board += `<td>${article.day}</td>`;
board += `<td>${article.see}</td>`;
board += `</tr>`;
}
}
for (i = 0; i < lifeboards.length; i++) {
var article = lifeboards[i];
var titleBold = article.titleBold;
board += `<tr>`;
if(titleBold == "1") {
board += `<td> ${i+1}. <b>${article.title}</b> </td>`;
} else if(titleBold == "0") {
board += `<td>${i+1}. ${article.title}</td>`;
}
board += `<td>${article.writer}</td>`;
board += `<td>${article.day}</td>`;
board += `<td>${article.see}</td>`;
board += `</tr>`;
}
return board;
},page:function (lifeboards) {
var page = ``;
page =+ `<tr>`;
page =+ `<td colspan="5">`;
for(j = 0; j < lifeboards.length/5; j++) {
page =+ `[${j+1}]`;
}
page =+ `</td>`;
page =+ `</tr>`;
return page;
}
}
The picture below shows how it works.
I don't know how much more detail Stackoverflow wants, but this is all my code and there's nothing more to explain.
Please use this one , you need to add concat ( + ) operator first then =. e.g. +=
page: function (lifeboards) {
var page = ``;
page += `<tr>`;
page += `<td colspan="5">`;
for (j = 0; j < lifeboards.length / 5; j++) {
page += `[${j + 1}]`;
}
page += `</td>`;
page += `</tr>`;
return page;
}
Hope this will solve the issue.

Update element with ajax don't affect until for loop end

I want to print a lot of numbers ONE-BY-ONE with AJAX.
something like this: (each new line is update of previous line!)
output is:
1
12
123
1234
12345
123456
...
I tried a lot and read a lot of this same problem, but i couldn't find my right Answer.
The real problem is every FOR LOOP in javascript will NO affect the DOM after it will END the loop. I just want update the DOM inside the FOR LOOP while working on a long running job.
Please look at my code.
$("#btn").on("click", dowork);
function dowork() {
document.getElementById("foo").innerHTML = "working";
setTimeout(function() {
var counter = 100; // i want assign counter = 2000000000
for (var i = 0; i < counter; i++) {
document.getElementById("print_here").innerHTML += i;
}
document.getElementById("foo").innerHTML = "done!";
}, 50);
}
#btn {
background: #1f1f1f;
padding: 10px;
font-weight: bolder;
color: #fff;
width: 50%;
margin: auto;
margin-top: 10px;
text-align: center;
cursor: pointer;
}
#print_here {
overflow-wrap: break-word;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="btn">CLICK TO DO WORK</div>
<div id="foo"></div>
<div id="print_here"></div>
Thanks for any answer and help to solve this problem.
Your DOM is "locked" while it is being updated and redrawn ones the loop is done. You can free up the resource to let the DOM update each time wrapping your DOM change in a setTimeout, similar to:
setTimeout(function(){
document.getElementById("print_here").innerHTML += i;
},1);
To ensure setTimeout uses the correct value for i use let i instead of var i
$("#btn").on("click", dowork);
function dowork() {
document.getElementById("foo").innerHTML = "working";
var counter = 3000; // i want assign counter = 2000000000
for (let i = 0; i < counter; i++) {
setTimeout(function() {
document.getElementById("print_here").innerHTML += i;
}, 1);
}
document.getElementById("foo").innerHTML = "done!";
}
#btn {
background: #1f1f1f;
padding: 10px;
font-weight: bolder;
color: #fff;
width: 50%;
margin: auto;
margin-top: 10px;
text-align: center;
cursor: pointer;
}
#print_here {
overflow-wrap: break-word;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="btn">CLICK TO DO WORK</div>
<div id="foo"></div>
<div id="print_here"></div>
I want change the #foo into "done!" after the FOR statement is END
You could check if you are at your last item you process within the setTimeout, similar to:
if (i == counter - 1){
document.getElementById("foo").innerHTML = "done!";
}
$("#btn").on("click", dowork);
function dowork() {
document.getElementById("foo").innerHTML = "working";
var counter = 3000; // i want assign counter = 2000000000
for (let i = 0; i < counter; i++) {
setTimeout(function() {
document.getElementById("print_here").innerHTML += i;
if (i == counter - 1){
document.getElementById("foo").innerHTML = "done!";
}
}, 1);
}
}
#btn {
background: #1f1f1f;
padding: 10px;
font-weight: bolder;
color: #fff;
width: 50%;
margin: auto;
margin-top: 10px;
text-align: center;
cursor: pointer;
}
#print_here {
overflow-wrap: break-word;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="btn">CLICK TO DO WORK</div>
<div id="foo"></div>
<div id="print_here"></div>
You need to let the call stack complete so the browser can do its work on the page. If you bog down the one main thread, page updates aren't going to occur.
One way to do this is use setImmediate or nextTick. This is non-standard, so check this polyfill: https://www.npmjs.com/package/browser-next-tick
Basically, you do an iteration, then tell the browser to do the next iteration as soon as possible... and this occurs on a fresh call stack.
Here is the working code for you:
$("#btn").on("click", dowork);
function dowork() {
document.getElementById("foo").innerHTML = "working";
setTimeout(function() {
var i, j, row = 5;
var html = "";
for (i = 1; i <= row; i++) {
for (j = 1; j <= i; j++) {
html += "<span>" + j + "</span>";
}
html += "</br>";
}
console.log(html);
document.getElementById("print_here").innerHTML = html;
}, 50);
}
#btn {
background: #1f1f1f;
padding: 10px;
font-weight: bolder;
color: #fff;
width: 50%;
margin: auto;
margin-top: 10px;
text-align: center;
cursor: pointer;
}
#print_here {
overflow-wrap: break-word;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="btn">CLICK TO DO WORK</div>
<div id="foo"></div>
<div id="print_here"></div>
Rows is the number of rows you want to print.

web programming_javascript: Error with Grade result in javascript

i have create a student information javascript.Everything is ok but i have a problem in the result of student's grade.It's alway show grade F every score.Ex.when total score is 100 it's show F but when total score is 500 it still show F.
Here is my code of java and html
'
var Column= ["ID", "Name","Gender","Javascript","Data structure","Network","VB.net","Corel Draw","Total", "Average","Grade"];
var arr = ["","","","0","0","0","0","0","0","0",""];
var i = 0;
var j = 0;
var x;
var grade;
if(arr[8]>=450 && arr[8]<500)
grade= "A";
else if(arr[8]>=400 && arr[8]<450)
grade= "B";
else if(arr[8]>=350 && arr[8]<400)
grade= "C";
else if(arr[8]>=300 && arr[8]<350)
grade= "D";
else if(arr[8]>=250 && arr[8]<300)
grade= "E";
else (arr[8]<250)
grade= "F";
x = parseInt(window.prompt("Number of Student"));
for (j = 0 ; j <= x-1 ; j++) {
//
for (i = 0 ; i <= 7; i++) {
arr[i] = window.prompt("Please Input " + Column[i] );
}
arr[8]= parseInt(arr[3]) + parseInt(arr[4]) + parseInt(arr[5]) + parseInt(arr[6]) + parseInt(arr[7]);
arr[9]= parseInt(arr[8])/5;
arr[10]=grade;
document.write("<tr>");
for (i = 0 ; i <= 10 ; i++) {
//
document.write("<td>"+ arr[i] + "</td> ");
}
document.write("</tr>");
//
}
document.write("</table>");
<html>
<head>
<title>Korm-Chantola</title>
<link rel="stylesheet" type="text/css" href="style for table.css">
</head>
<body>
<div class="watermark">KORM-CHANTOLA<br>ID-B121561<br>ROOM-A201</div>
<center>
<h1>STUDENT SCORE INFORMATION</h1>
<table class="table1"
border="5" padding="2px"
width="700px">
<tr >
<th>ID</th>
<th>Name</th>
<th>Gender</th>
<th>JavaScript</th>
<th>Data Structure</th>
<th>Network</th>
<th>VB.net</th>
<th>Corel Draw</th>
<th>Total</th>
<th>Average</th>
<th>Grade</th>
</tr>
<script type="text/javascript" src="JScript.js"></script>
</center>
</body>
</html>
table.table1,td,th{
border: 1px solid black;
}
table.table1 td {
text-align: center;
height: 50px;
vertical-align: bottom;
padding: 15px;
background-color:#CCCCCC;
color:#0D3821;
}
table.table1 th{
color:white;
background-color:#3B3B99;
padding: 10px;
}
h1 {
text-shadow: 15px 10px 8px black;
text-align: center;
text-decoration: underline;
color:#1C127D;
}
body {
background-color: #E6E6E6;
}
.watermark {
position: left;
opacity: 0.25;
font-size: 2em;
width: 100%;
text-align: left;
z-index: 1000;
}
![This is Screenshot of problem][10]
It will do because for grade A you are testing if it is less than 500. It's not so it will fall through to the else condition. Change to <=500 and it should work for grade A.
Second problem is the (arr[8]<250). The else condition is executing this as the result of the if block. The following line of code is grade="F" for it will always be set to F no matter what happened in the if block. Lose the (arr[8]<250).
With these two changes it should work as required.
Hint: Even for one line blocks within an if statement I prefer to wrap the block in {}. This way it is a lot easier to see what is going on (in the above case it would throw up a syntax error).

Categories

Resources