How to not overwrite button actions? - javascript

I have a table with random words and I want specific words to be grayed out when clicking one of the buttons. On the second press of the same button, the words that weren’t grayed on the first click are now gray, and the rest go back to being white (the second press is like inverting the output in a way). Here’s my code:
var pressCount = [0, 0, 0];
var table = document.getElementsByTagName("td");
document.body.addEventListener("click", function(event) {
var target = event.target;
var id = target.id;
var index;
if (id === "b1") {
index = 0;
} else if (id === "b2") {
index = 1;
} else if (id === "b3") {
index = 2;
} else if (id === "reset") {
reset();
return;
} else {
return;
}
pressCount[index]++;
if (pressCount[index] === 1) {
target.style.backgroundColor = "green";
var wordsToGray;
if (index === 0) {
wordsToGray = ["Behave", "Reach"];
} else if (index === 1) {
wordsToGray = ["Take", "Behave", "Utopia"];
} else if (index === 2) {
wordsToGray = ["Like", "Median"];
}
for (var i = 0; i < table.length; i++) {
if(wordsToGray.includes(table[i].innerHTML)) {
table[i].style.color = "gray";
} else {
table[i].style.color = "white";
}
}
} else if (pressCount[index] === 2) {
target.style.backgroundColor = "red";
var wordsToGray;
if (index === 0) {
wordsToGray = ["Take", "Riddle", "Like", "Move", "Median", "Utopia", "Walk"];
} else if (index === 1) {
wordsToGray = ["Riddle", "Like", "Move", "Reach", "Median", "Walk"];
} else if (index === 2) {
wordsToGray = ["Take", "Behave", "Riddle", "Move", "Reach", "Utopia", "Walk"];
}
for (var i = 0; i < table.length; i++) {
if(wordsToGray.includes(table[i].innerHTML)) {
table[i].style.color = "gray";
} else {
table[i].style.color = "white";
}
}
} else {
target.style.backgroundColor = "";
pressCount[index] = 0;
}
});
function reset() {
var table = document.getElementsByTagName("td");
for (var i = 0; i < table.length; i++) {
table[i].style.color = "white";
}
var b1Button = document.getElementById("b1");
b1Button.style.backgroundColor = "";
var b2Button = document.getElementById("b2");
b2Button.style.backgroundColor = "";
var b3Button = document.getElementById("b3");
b3Button.style.backgroundColor = "";
pressCount = [0, 0, 0];
}
table {
font-size: 30px;
width: 25%;
text-align: center;
border: none;
background-color: black;
<table>
<tr>
<td style="color:white;">Take</td>
<td style="color:white;">Behave</td>
<td style="color:white;">Riddle</td>
</tr>
<tr>
<td style="color:white;">Like</td>
<td style="color:white;">Move</td>
<td style="color:white;">Reach</td>
</tr>
<tr>
<td style="color:white;">Median</td>
<td style="color:white;">Utopia</td>
<td style="color:white;">Walk</td>
</tr>
</table>
<br>
<button id="b1">Button 1</button>
<button id="b2">Button 2</button>
<button id="b3">Button 3</button>
<button id="reset">RESET</button>
The problem is that when, for example, I press button 2 once and then button 1 once, the output shows only the words "Behave" and "Reach" grayed out (it’s the action on the first press of button 1). What I want the output to be, is the words "Take", "Behave", "Reach" and "Utopia" being grayed out. Meaning the action of button 2 isn’t overwritten.
I’m also thinking of having an action on the third button press that resets the buttons actions but I haven’t thought on how this is achievable and I’m getting ahead of myself here.

Related

Generated row of table event listener not working instantly

I have a table like this :
I have added an event listener assetTableEvent() to each text box in the table. My issue is when I add new row to the table, i also add the corresponding event listener to it assetTableEvent(), but the total value does not pop while entering value, it shows only when next row has values entered.
function assetTableEvent() {
let total = 0;
for (var k = 0; k < document.getElementById("assetTable").rows.length; k++) {
var a = document.getElementById("v" + k);
var o = document.getElementById("o" + k);
var t = document.getElementById("t" + k);
if (a == null || o == null) {
continue;
}
if (a.value.length > 0 && o.value.length > 0) {
t.value = Number.parseInt(a.value - o.value);
total = (Number.parseInt(t.value) + Number.parseInt(total));
document.getElementById("totalAssets").value = Number.parseInt(total);
}
}
}
I even tried calling assetTableEvent() every time there is a change, but it just does not work. Can somebody help me in Javascript how to make dynamically added rows correspond to event listener like above rows.
HTML for Asset table:
<div id="calcContainer">
<div id = "headingText" >
Child Maintenance Calculator
</div>
<div id="startPage">
<button id="startBtn">Start</button>
</div>
<div id="asset">
<table id="assetTable">
<tr>
<th>Asset</th>
<th>Value</th>
<th>Own</th>
<th>Total</th>
</tr>
</table>
<div id="totalAssetsDiv">
<Label for ="totalAssets">Total Assets</Label>
<input type="number" id = "totalAssets" readonly="true">
<br>
</div>
<div id ="rowOps">
<br> <button id="addRow" class = "addDel">Add Row</button>
<button id="removeRow" class = "addDel1">Delete Row</button><br>
</div>
</div>
And add row event listener :
document.getElementById("addRow").addEventListener("click", function () {
var table = document.getElementById("assetTable");
var row = table.insertRow();
for (let j = 0; j < 4; j++) {
var tb = document.createElement("INPUT");
var value = "", idNum = "";
if (j == 0) {
tb.setAttribute("type", "text");
tb.value = value;
}
else {
tb.setAttribute("type", "number");
}
//Setting textbox id
switch (j) {
case 0:
idNum = "a";
break;
case 1:
idNum = "v";
break;
case 2:
idNum = "o";
break;
case 3:
idNum = "t";
break;
}
tb.id = idNum + (table.rows.length);
if (tb.id.includes('t')) {
tb.setAttribute("readOnly", "true");
}
tb.classList.add("assetTBox");
let cell = row.insertCell(j);
tb.addEventListener("input", assetTableEvent, false);
cell.appendChild(tb);
}
});
Trying to use incremental IDs is more work than it is worth, especially when you start removing rows.
I suggest you use classes instead and delegate the event listener to the table itself. When an input event occurs you get the closest row and query for the elements within that row for the row total, then query all of the rows totals for the master total
Basic example with functional add row
const table = document.querySelector('#myTable'),
cloneRow = table.rows[0].cloneNode(true);
table.addEventListener('input',(e) => {
if (e.target.matches('.qty, .price')) {
const row = e.target.closest('tr'),
price = row.querySelector('.price').valueAsNumber || 0,
qty = row.querySelector('.qty').valueAsNumber || 0;
row.querySelector('.amt').value = qty * price;
setTotalAmt()
}
});
document.querySelector('#add-row').addEventListener('click', (e) => {
table.appendChild(cloneRow.cloneNode(true))
});
function setTotalAmt() {
const sum = [...table.querySelectorAll('.amt')].reduce((a, el) => a + (+el.value || 0), 0)
document.querySelector('#total').value = sum;
}
<button id="add-row">
Add Row
</button>
Total:<input id="total" />
<table id="myTable">
<tr>
<td>Qty:
<input type="number" class="qty" value="0" />
</td>
<td>Price:
<input type="number" class="price" value="0" />
</td>
<td>Amt:
<input class="amt" readonly value="0" />
</td>
</tr>
</table>
#charlietfl 's solition is more elegant but if you wonder what is the problem in your code, you should change the < to <= in k < document.getElementById("assetTable").rows.length; part
function assetTableEvent() {
let total = 0;
for (var k = 0; k <= document.getElementById("assetTable").rows.length; k++) {
var a = document.getElementById("v" + k);
var o = document.getElementById("o" + k);
var t = document.getElementById("t" + k);
if (a == null || o == null) {
continue;
}
if (a.value.length > 0 && o.value.length > 0) {
t.value = Number.parseInt(a.value - o.value);
total = (Number.parseInt(t.value) + Number.parseInt(total));
document.getElementById("totalAssets").value = Number.parseInt(total);
}
}
}
Here is the working example:
document.getElementById("addRow").addEventListener("click", function () {
var table = document.getElementById("assetTable");
var row = table.insertRow();
for (let j = 0; j < 4; j++) {
var tb = document.createElement("INPUT");
var value = "", idNum = "";
if (j == 0) {
tb.setAttribute("type", "text");
tb.value = value;
}
else {
tb.setAttribute("type", "number");
}
//Setting textbox id
switch (j) {
case 0:
idNum = "a";
break;
case 1:
idNum = "v";
break;
case 2:
idNum = "o";
break;
case 3:
idNum = "t";
break;
}
tb.id = idNum + (table.rows.length);
if (tb.id.includes('t')) {
tb.setAttribute("readOnly", "true");
}
tb.classList.add("assetTBox");
let cell = row.insertCell(j);
tb.addEventListener("input", assetTableEvent, false);
cell.appendChild(tb);
}
});
function assetTableEvent() {
let total = 0;
for (var k = 0; k <= document.getElementById("assetTable").rows.length; k++) {
var a = document.getElementById("v" + k);
var o = document.getElementById("o" + k);
var t = document.getElementById("t" + k);
if (a == null || o == null) {
continue;
}
if (a.value.length > 0 && o.value.length > 0) {
t.value = Number.parseInt(a.value - o.value);
total = (Number.parseInt(t.value) + Number.parseInt(total));
document.getElementById("totalAssets").value = Number.parseInt(total);
}
}
}
<div id="calcContainer">
<div id = "headingText" >
Child Maintenance Calculator
</div>
<div id="startPage">
<button id="startBtn">Start</button>
</div>
<div id="asset">
<table id="assetTable">
<tr>
<th>Asset</th>
<th>Value</th>
<th>Own</th>
<th>Total</th>
</tr>
</table>
<div id="totalAssetsDiv">
<Label for ="totalAssets">Total Assets</Label>
<input type="number" id = "totalAssets" readonly="true">
<br>
</div>
<div id ="rowOps">
<br> <button id="addRow" class = "addDel">Add Row</button>
<button id="removeRow" class = "addDel1">Delete Row</button><br>
</div>
</div>

JavaScript not further executed once a button is disabled

I am using next and prev buttons so one question will be shown at a time, however, once next or prev buttons are disabled, the other button doesn't work anymore either. Here's my code:
var showing = [1, 0, 0, 0];
var questions = ['q0', 'q1', 'q2', 'q3'];
function next() {
var qElems = [];
for (var i = 0; i < questions.length; i++) {
qElems.push(document.getElementById(questions[i]));
}
for (var i = 0; i <= showing.length; i++) {
if (showing[i] == 1) {
showing[i] = 0;
if (i == showing.length - 1) {
document.getElementById("next").disabled = true;
} else {
console.log(i);
qElems[i + 1].style.display = 'block';
qElems[i].style.display = 'none';
showing[i + 1] = 1;
}
break;
}
}
}
function prev() {
var qElems = [];
for (var i = 0; i < questions.length; i++) {
qElems.push(document.getElementById(questions[i]));
}
for (var i = 0; i <= showing.length; i++) {
if (showing[i] == 1) {
showing[i] = 0;
if (i == showing.length - 4) {
document.getElementById("prev").disabled = true;
} else {
qElems[i - 1].style.display = 'block';
qElems[i].style.display = 'none';
showing[i - 1] = 1;
}
break;
}
}
}
I think you want this simplified script
I had to guess the HTML, but there is only one function.
window.addEventListener("load", function() {
let showing = 0;
const questions = document.querySelectorAll(".q");
questions[showing].style.display = "block";
const next = document.getElementById("next");
const prev = document.getElementById("prev");
document.getElementById("nav").addEventListener("click", function(e) {
var but = e.target, dir;
if (but.id === "prev") dir = -1;
else if (but.id === "next") dir = 1;
else return; // not a button
questions[showing].style.display = "none"; // hide current
showing += dir; // up or down
next.disabled = showing === questions.length-1;
if (showing <= 0) showing = 0;
prev.disabled = showing === 0
questions[showing].style.display = "block";
})
})
.q { display:none }
<div class="q" id="q0">Question 0</div>
<hr/>
<div class="q" id="q1">Question 1</div>
<hr/>
<div class="q" id="q2">Question 2</div>
<hr/>
<div class="q" id="q3">Question 3</div>
<hr/>
<div id="nav">
<button type="button" id="prev" disabled>Prev</button>
<button type="button" id="next">Next</button>
</div>
Since this is a quiet interesting java script task, Im doing my own solution.
Hope this matches the requirement.
I have created 4 divs of which first one is only displayed at first. Remaining divs are placed hidden. On clicking next, the divs are displayed according to index. Once the last and first indexes are interpreted, the respective next and previous buttons are enabled and disabled.
var showing = [1, 0, 0, 0];
var questions = ['q0', 'q1', 'q2', 'q3'];
var qElems = [];
function initialize() {
for (var i = 0; i < questions.length; i++) {
qElems.push(document.getElementById(questions[i]));
}
}
function updatevisibilitystatus(showindex, hideindex) {
qElems[showindex].style.display = 'block';
qElems[hideindex].style.display = 'none';
showing[showindex] = 1;
}
function next() {
for (var i = 0; i <= showing.length; i++) {
if (showing[i] == 1) {
showing[i] = 0;
if (i == showing.length - 2) {
document.getElementById("next").disabled = true;
}
updatevisibilitystatus(i + 1, i);
document.getElementById("prev").disabled = false;
break;
}
}
}
function prev() {
for (var i = 0; i <= showing.length; i++) {
if (showing[i] == 1) {
showing[i] = 0;
if (i == 1) {
document.getElementById("prev").disabled = true;
}
updatevisibilitystatus(i - 1, i);
document.getElementById("next").disabled = false;
break;
}
}
}
<body onload="initialize()">
<div id="q0" style="display: block;">Q0</div>
<div id="q1" style="display: none;">Q1</div>
<div id="q2" style="display: none;">Q2</div>
<div id="q3" style="display: none;">Q3</div>
<button id="prev" disabled onclick="prev()">Prev</button>
<button id="next" onclick="next()">Next</button>
</body>

Implementing slide puzzle using Javascript

First off, thank you for reading this question. With this javascript code, I'm trying to implement a 4x4 slide number puzzle, which looks like this when completed. :
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 [blank]
Each number are represented by .gif number files which are on the same folder where this HTML file is.
When a user clicks "START" button below the puzzle, it shuffles pieces by repetitively swapping randomly chosen two pieces. (shuffle function)
When a user clicks a piece adjacent to the blank piece then it swaps the two. (movePiece function)
But the problem is when I click the START button and the piece adjacent to the blank piece, nothing happens.. even though except for this code's logic and algorithm is not different from the answer that my instructor's given and I can't find where is causing this problem.
Can anyone help me find out where is wrong with this code?
Any advice would be much appreciated.
<html>
<head>
<title>15 Puzzle Game</title>
<meta name="generator" content="Microsoft FrontPage 4.0" charset="UTF-8">
<script language="JavaScript">
var completed=true;
function tokenize(sep,str){
tokens = new Array();
i=0;
while(1)
{
idx=str.indexOf(sep);
if(idx == -1)
{
if(str.length>0)
{
tokens[i]=str;
}
break;
}
tokens[i++]=str.substring(0,idx);
str=str.substr(idx+1);
}
return tokens;
}
function getX(idx)
{
var rest=idx-Math.floor(idx/4)*4;
return (rest==0)?4:rest;
}
function getY(idx)
{
return Math.floor((idx-1)/4)+1;
}
function getIndex(x,y)
{
return x+(y-1)*4;
}
function newDirection(pos)
{
var dir;
if ((pos==2)||(pos==3)) dir=(Math.floor(Math.random()+0.5)==0)?-1:1;
else dir=(pos==1)?1:-1;
return (pos+dir);
}
function newIndex(idx)
{
var x,y;
x=getX(idx);
y=getY(idx);
if (Math.floor(Math.random()+0.5)==0) x=newDirection(x);
else y=newDirection(y);
return getIndex(x,y);
}
function isComplete()
{
if(completed) return 0;
for(var i = 1; i <= document.images.length; i++){
if(document.images[i-1].src != i+".gif") return 0;
}
return 1;
}
function getNum(idx){
var index = idx - 1;
var token[] = tokenize("/",document.images[index].src);
var numOfTokens = tokenize("/",document.images[index].src).length;
var num = tokenize(".", token[numOfTokens-1])[0];
return Number(num);
}
function shuffle()
{
var puzzles=new Array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
iter=Math.floor(Math.random()*200+0.5)+100;
for (i=0;i<iter;i++)
{
var ranNum = Math.floor(Math.random()*16)+1;
var newNum = newIndex(ranNum);
var temp = puzzles[ranNum-1];
puzzles[ranNum-1] = puzzles[newNum-1];
puzzles[newNum-1] = temp;
}
}
for(i=1;i<document.images.length+1;i++){
document.images[i-1].src = ""+puzzles[i-1]+".gif";
}
completed = false;
}
function movePiece(idx)
{
x = getX(idx);
y = getY(idx);
var flag = 0;
var tempIdx;
for(i=-1; i<=1 ; i=i+2){
if ((x==2)||(x==3)) dir=i;
else dir=(x==1)?1:-1;
var tmpx= (x+dir);
tempIdx = getIndex(tmpx,y);
if(getNum(tempIdx) == 16){ flag = 1; midx=tempIdx; }
}
for(i=-1; i<=1 ; i=i+2){
if ((y==2)||(y==3)) dir=i;
else dir=(y==1)?1:-1;
var tmpy= (y+dir);
tempIdx = getIndex(x,y);
if(getNum(tempIdx) == 16){ flag = 1; midx=tempIdx; }
}
if (flag == 1){
document.images[midx-1].src = document.images[idx-1].src;
document.images[idx-1].src = "16.gif";
}
if(isComplete()) alert('Congratulation!');
completed = true;
}
</script>
</head>
<body bgcolor="silver" text="black" link="#0000EE" vlink="#551A8B" alink="red">
<h2 align="center">
15 Puzzle</h2>
<div align="center">
<table border>
<tr>
<td width="50%" align="center">
<script language="JavaScript">
with(window.document)
{
open();
writeln('<table border=1 cellpadding=0 cellspacing=1>');
for(var i=1;i<17;i++)
{
if(i==1 || i==5 || i==9 || i==13 )
{
writeln('<tr>');
}
writeln(' <td width=49 height=49>');
writeln(' <a href=JavaScript:movePiece('+i+');>');
writeln(' <img src=',i,'.gif border=0 width=49 height=49 name=i',i,'></a>');
writeln(' </td>');
if(i==4 || i==8 || i==12 || i==16 )
{
writeln('</tr>');
}
}
writeln('</table>');
close();
}
</script>
</td>
</tr>
</table>
</div>
<p align="center">
<br>
</p>
<form method="get">
<p align="center">
<input type="button" value="START" onClick="shuffle()"></p>
</form>
</body>
</html>
javascript
and this is working code
<html>
<head>
<title>15 Puzzle Game</title>
<meta charset="UTF-8">
<script language="JavaScript">
var completed=true;
function tokenize(sep,str)
{
tokens = new Array();
i=0;
while(1)
{
idx=str.indexOf(sep);
if(idx == -1)
{
if(str.length>0)
{
tokens[i]=str;
}
break;
}
tokens[i++]=str.substring(0,idx);
str=str.substr(idx+1);
}
return tokens;
}
function getX(idx)
{
var rest=idx-Math.floor(idx/4)*4;
return (rest==0)?4:rest;
}
function getY(idx)
{
return Math.floor((idx-1)/4)+1;
}
function getIndex(x,y)
{
return x+(y-1)*4;
}
function newDirection(pos)
{
var dir;
if ((pos==2)||(pos==3)) dir=(Math.floor(Math.random()+0.5)==0)?-1:1;
else dir=(pos==1)?1:-1;
return (pos+dir);
}
function newIndex(idx)
{
var x,y;
x=getX(idx);
y=getY(idx);
if (Math.floor(Math.random()+0.5)==0) x=newDirection(x);
else y=newDirection(y);
return getIndex(x,y);
}
function isComplete() {
if(completed)
return false;
var prev = getPiece(1);
for(var i = 2; i < 17; i++) {
var current = getPiece(i);
if(current != prev+1)
return false;
prev = current;
}
return true;
}
function shuffle()
{
var puzzles=new Array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
iter=Math.floor(Math.random()*200+0.5)+100;
var blank = 15;
for (i=0; i<iter; i++)
{
var move = newIndex(blank+1)-1;
var t = puzzles[blank];
puzzles[blank] = puzzles[move];
puzzles[move] = t;
blank = move;
}
for(i = 0; i < 16; i++)
document.images[i].src = ""+puzzles[i]+".gif";
completed = false;
}
function movePiece(idx)
{
var current = getPiece(idx);
if(current == 16)
return;
var x = getX(idx);
var y = getY(idx);
var flag=false, midx=idx;
var dx = [0, 0, -1, 1], dy = [-1, 1, 0, 0];
for(var i = 0; i < 4; i++) {
if(1 <= x+dx[i] && x+dx[i] <= 4 && 1 <= y+dy[i] && y+dy[i] <= 4) {
if(getPiece(getIndex(x+dx[i], y+dy[i])) == 16) {
flag = true;
midx = getIndex(x+dx[i], y+dy[i]);
break;
}
}
}
if(flag) {
var t = document.images[idx-1].src;
document.images[idx-1].src = document.images[midx-1].src;
document.images[midx-1].src = t;
}
if(isComplete()) {
alert("Congratulation!");
completed = true;
}
}
function getPiece(idx) {
idx--;
var len = tokenize("/", document.images[idx].src).length;
return Number(tokenize(".", tokenize("/", document.images[idx].src)[len-1])[0]);
}
</script>
</head>
<body bgcolor="silver" text="black" link="#0000EE" vlink="#551A8B" alink="red">
<h2 align="center">
15 Puzzle</h2>
<div align="center">
<table border>
<tr>
<td width="50%" align="center">
<script language="JavaScript">
with(window.document)
{
open();
writeln('<table border=1 cellpadding=0 cellspacing=1>');
for(var i=1;i<17;i++)
{
if(i==1 || i==5 || i==9 || i==13 )
{
writeln('<tr>');
}
writeln(' <td width=49 height=49>');
writeln(' <a href=JavaScript:movePiece('+i+');>');
writeln(' <img src=',i,'.gif border=0 width=49 height=49 name=i',i,'></a>');
writeln(' </td>');
if(i==4 || i==8 || i==12 || i==16 )
{
writeln('</tr>');
}
}
writeln('</table>');
close();
}
</script>
</td>
</tr>
</table>
</div>
<p align="center">
<br>
</p>
<form method="get">
<p align="center">
<input type="button" value="START" onClick="shuffle()"></p>
</form>
</body>
</html>
The code you provided isn't a good read, so I've created my own version in React. I hope it'll help you to figure things out or at least inspire you to learn React.
https://codesandbox.io/s/wq8n9k5jr7

How to beat a JavaScript condition riddle?

I am using a foreach loop in php to load data from a mysql table. I'm using the data ID's loaded from the data base and applying it to the button values.
The buttons come in two colors, green and white. The buttons represent likes for liking comments or posts.
The total existing number of likes starts at 6 (div id="total")
white buttons
If button 1 has color of white and you click it, total likes (6) will increase by 1. If you click button 1 again, total likes (7) will decrease by 1.
If button 1, button 2, and button three are clicked, total likes (6) increases by 3 ( 1 for each button). If button 1, button 2 and button 3 are clicked again, the total likes (9) will decrease by 3.
The Puzzle
Green buttons
How do I make it so, When a green button is clicked, the total (6) decrease by 1, and if the button is clicked again, it should increase by 1. Unlike white buttons.
If Green button 3, 5 and 6 are clicked, the total (6) should decease by 3. if the same buttons are clicked again, total (6) increases by 3.
Here is my code
var colorcode = "rgb(116, 204, 49)";
var buttonid = str;
var elem = document.getElementById(buttonid);
var theCSSprop = window.getComputedStyle(elem, null).getPropertyValue("background-color");
var initialtotal = parseInt(document.getElementById("total").innerHTML, 10);
var likes = new Array();
function showUser(str) {
////// 1st condition /////
if (theCSSprop == colorcode) {
if (likes[value] == 0 || !likes[value]) {
likes[value] = 1;
} else {
likes[value] = 0;
}
var sum = 0;
for (i = 0; i < likes.length; i++) {
if (likes[i] == 1) {
sum--
}
}
}
////// 2nd condition /////
else {
if (likes[str] == 0 || !likes[str]) {
likes[str] = 1;
} else {
likes[str] = 0;
}
var sum = 0;
for (i = 0; i < likes.length; i++) {
if (likes[i] == 1) {
sum++
}
}
}
var tot = initialtotal + sum;
document.getElementById("total").innerHTML = tot;
}
<div id="total" style="width:100px;padding:50px 0px; background-color:whitesmoke;text-align:center;">6 </div>
<!---------------------------------------------------------------------------------------------------------------------->
<button id="5" value="5" onclick="showUser(this.value)">LIKE </button>
<button id="346" value="346" onclick="showUser(this.value)" style="background-color:rgb(116, 204, 49);">LIKE </button>
<button id="128" value="128" onclick="showUser(this.value)" style="background-color:rgb(116, 204, 49);">LIKE </button>
<button id="687" value="687" onclick="showUser(this.value)">LIKE </button>
<button id="183" value="183" onclick="showUser(this.value)" style="background-color:rgb(116, 204, 49);">LIKE </button>
<button id="555" value="555" onclick="showUser(this.value)">LIKE </button>
<!---------------------------------------------------------------------------------------------------------------------->
Instead of passing this.value to showUser(), just pass this. That way, the function can get the value and the style directly, without having to call getElementById() (you're not passing the ID). Then you need to set theCSSprop inside the function, so it's the property of the current button.
To make green buttons alternate direction from increment to decrement, you need a global variable that remembers what it did the last time the function was called.
Also, you don't need to write if(likes[str] == 0 || !likes[str]), since 0 is faley. Just write if(!likes[str]).
var colorcode = "rgb(116, 204, 49)";
var likes = new Array();
var greenIncr = -1;
function showUser(elem) {
var initialtotal = parseInt(document.getElementById("total").innerHTML, 10);
////// 1st condition /////
var str = elem.value;
var theCSSprop = window.getComputedStyle(elem, null).getPropertyValue("background-color");
if (theCSSprop == colorcode) {
if (!likes[str]) {
likes[str] = 1;
} else {
likes[str] = 0;
}
var sum = 0;
for (i = 0; i < likes.length; i++) {
if (likes[i] == 1) {
sum += greenIncr;
}
}
greenIncr = -greenIncr; // revese the direction of green button
}
////// 2nd condition /////
else {
if (!likes[str]) {
likes[str] = 1;
} else {
likes[str] = 0;
}
var sum = 0;
for (i = 0; i < likes.length; i++) {
if (likes[i] == 1) {
sum++
}
}
}
var tot = initialtotal + sum;
document.getElementById("total").innerHTML = tot;
}
<div id="total" style="width:100px;padding:50px 0px; background-color:whitesmoke;text-align:center;">6 </div>
<!---------------------------------------------------------------------------------------------------------------------->
<button id="5" value="5" onclick="showUser(this)">LIKE </button>
<button id="346" value="346" onclick="showUser(this)" style="background-color:rgb(116, 204, 49);">LIKE </button>
<button id="128" value="128" onclick="showUser(this)" style="background-color:rgb(116, 204, 49);">LIKE </button>
<button id="687" value="687" onclick="showUser(this)">LIKE </button>
<button id="183" value="183" onclick="showUser(this)" style="background-color:rgb(116, 204, 49);">LIKE </button>
<button id="555" value="555" onclick="showUser(this)">LIKE </button>
<!---------------------------------------------------------------------------------------------------------------------->
First naive implementation can look like this
class Counter {
constructor(initial) {
this.initial = initial
this.white = [false, false, false]
this.green = [false, false, false]
}
changeGreen(index) {
this.green[index] = !this.green[index]
}
changeWhite(index) {
this.white[index] = !this.white[index]
}
get total() {
return this.initial + this.white.reduce((total, current) => total + current, 0) + this.green.reduce((total, current) => total - current, 0)
}
}
let counter = new Counter(6)
const render = counter => {
document.querySelector('#total').innerHTML = counter.total
}
render(counter)
;['#first', '#second', '#third'].map((selector, index) => {
document.querySelector(selector).addEventListener('click', e => {
e.target.classList.toggle('pressed')
counter.changeWhite(index)
render(counter)
})
})
;['#fourth', '#fifth', '#sixth'].map((selector, index) => {
document.querySelector(selector).addEventListener('click', e => {
e.target.classList.toggle('pressed')
counter.changeGreen(index)
render(counter)
})
})
.green {
background: #00aa00
}
.pressed {
border-style: inset
}
<div id="total">0</div>
<p>
<button id="first">First</button>
<button id="second">Second</button>
<button id="third">Third</button>
<button id="fourth" class="green">Fourth</button>
<button id="fifth" class="green">Fifth</button>
<button id="sixth" class="green">Sixth</button>
</p>
But after all I've finished with something like
class Counter {
constructor(initial, strategy) {
this.initial = initial;
this.elements = [];
this.strategy = typeof strategy === 'function' ? strategy : () => {}
}
addElement(content, type, next) {
const element = {
content: content,
type: type,
state: false
};
this.elements.push(element);
return next(element, this.elements.length - 1);
}
toggleElementState(index) {
this.elements[index].state = !this.elements[index].state
}
get total() {
return this.strategy(this.initial, this.elements)
}
}
const initialize = () => {
Counter.WHITE = Symbol('white');
Counter.GREEN = Symbol('green');
const counter = new Counter(6, (initial, buttons) => {
return initial +
buttons.filter(button => button.type === Counter.WHITE).reduce((total, current) => total + Number(current.state), 0) +
buttons.filter(button => button.type === Counter.GREEN).reduce((total, current) => total - Number(current.state), 0)
});
const render = counter => {
document.querySelector('#total').innerHTML = counter.total
};
const createButton = (element, index) => {
const button = document.createElement('button');
button.setAttribute('data-id', index);
button.classList.add(element.type === Counter.GREEN ? 'green' : 'none');
button.textContent = element.content;
document.querySelector('#buttons').appendChild(button)
};
const addButton = (type, ...selectors) => {
selectors.forEach(selector => counter.addElement(selector, type, createButton));
};
render(counter);
addButton(Counter.WHITE, '#first', '#second', '#third');
addButton(Counter.GREEN, '#fourth', '#fifth', '#sixth');
addButton(Counter.WHITE, '#first', '#second', '#third');
document.querySelector('#buttons').addEventListener('click', function(e) {
e.target.classList.toggle('pressed');
counter.toggleElementState(parseInt(e.target.dataset.id));
render(counter)
})
};
document.addEventListener('DOMContentLoaded', initialize);
.green {
background: #00aa00
}
.pressed {
border-style: inset
}
<div id="total">0</div>
<p id="buttons">
</p>

How can I create a variable condition as a parameter in javascript?

I want to test how many red/black/even/odd comes up in a row in the game of roulette.
The following function will loop through a list of spins n and give how many times in a row red won and lost. The same function can be used for all the other types of even wins however the check is different
color[n[i]] == "red"
I want to pass a different check into this function to test for evens
n[i]%2 == 0
Can this be done?
function test(n)
{
var wins = parseInt(0);
var losses = parseInt(0);
for(var i=0;i<n.length;i++)
{
if(color[n[i]] == "red")
{
wins += 1
losses = 0
}
else
{
wins = 0
losses += 1
}
}
.
.
.
PART 2
This is the full code. If you click the 'Enter Spins' button and the 'Toggle Number Pad' button, then add the number 8 twice, then 3 alerts will display.
I can not seem to get the the 3 messages to show up on separate lines. I tried some examples, but it always adds the line return before the last message.
Do you know how to get the multiple messages on separate lines?
<html>
<head>
<style>
.bntcal {
padding: 10px 10px 10px 10px;
margin: 10px;
}
.bntcaladd {
padding: 10px 10px 10px 10px;
margin: 10px;
}
.bntshow{
padding: 5px 5px 5px 5px;
margin: 5px;
width: 10%;
}
.spanhide {
display: none;
}
.bell {
float:left;
display: none;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
var wheel0 = [37,32,15,19,4,21,2,25,17,34,6,27,13,36,11,30,8,23,10,5,24,16,33,1,20,14,31,9,22,18,29,7,28,12,35,3,26];
var wheel00 = [37,28,9,26,30,11,7,20,32,17,5,22,34,15,3,24,36,13,1,38,27,10,25,29,12,8,19,31,18,6,21,33,16,4,23,35,14,2];
var wheel = wheel00;
var wColor = "";
var numbers = [];
var color = [];
$(document).ready(function(){
// --- Menu Buttons
$("#enterSpins").click(function(){
$("#divSpins").show();
$("#divAlerts").hide();
$("#divHowTo").hide();
});
$("#setAlert").click(function(){
$("#divAlerts").show();
$("#divSpins").hide();
$("#divHowTo").hide();
});
$("#howTo").click(function(){
$("#divHowTo").show();
$("#divSpins").hide();
$("#divAlerts").hide();
});
// ---- Sub Buttons
$("#enterPad").click(function(){
$("#showSpinsPad").toggle();
$("#clearBox").toggle();
$("#clearBox1").toggle();
if(!$("#showSpinsPad").is(":hidden"))
{
$("#spins").prop("disabled", true)
}
else
{
$("#spins").prop("disabled", false)
}
});
$(".bntcal").click(function(){
$("#currentSpin").text($("#currentSpin").text()+$(this).val())
if ($("#currentSpin").text().length > 2)
{
$("#currentSpin").text($(this).val())
}
});
$("#clear").click(function(){
$("#currentSpin").text("")
});
$("#add").click(function(){
getWheel()
currentSpin = $("#currentSpin").text()
if(currentSpin.length > 0)
{
if ($("#spins").val().length > 0)
{
$("#spins").val($("#spins").val() + ", ");
}
if(parseInt(currentSpin)<37)
{
$("#spins").val($("#spins").val() + currentSpin);
}
if(parseInt(currentSpin) == 37)
{
$("#spins").val($("#spins").val() + "0");
}
if(parseInt(currentSpin) == 38)
{
$("#spins").val($("#spins").val() + "00");
}
if(parseInt(currentSpin)>38)
{
$("#spins").val($("#spins").val() + "0");
}
$("#currentSpin").text("")
}
var n = GetUserNumbers();
run(n)
});
$("#undo").click(function(){
var n = GetUserNumbers();
if (n.length>0)
{
n.pop();
}
$("#spins").val(n)
run(n)
});
$("#clean").click(function(){
$("#spins").val("")
});
$("#run").click(function(){
var n = GetUserNumbers();
run(n)
});
});
// ---------------------------------------------------------------
// --------------------- FUNCTIONS -------------------------------
// ---------------------------------------------------------------
function run(n)
{
$("#alert").text("")
// Evens
var conditions = ['color[n] == "red"','color[n] == "black"','n%2 == 0 && n<37','n%2 == 1 && n<37','n > 18 && n<37','n < 19 && n>0']
var checklocation = ['Red','Black','Even','Odd','High','Low']
var idWins = "#evenwin"
var idLosses = "#evenloss"
checkCondition(n, conditions, checklocation, idWins, idLosses)
// Dozens
var conditions = ['n%3 == 1','n%3 == 2','n%3 == 0','n>=1 && n<=12','n>=13 && n<=24','n>=25 && n<=36']
var checklocation = ['Row 1 [1,2,3..]','Row 2 [2,3,4..]','Row 2 [3,6,9..]','Dozen 1 [1-12]','Dozen 1 [13-24]','Dozen 1 [25-36]']
var idWins = "#dozenwin"
var idLosses = "#dozenloss"
checkCondition(n, conditions, checklocation, idWins, idLosses)
}
function checkCondition(n, conditions, checklocation, idWins, idLosses)
{
for(var i=0; i<conditions.length; i++)
{
var check = function(n){ if(conditions[i]){ return true; } else { return false; }}
var wins = checkWins(n, check)
var losses = checkLosses(n, check)
if(wins >= $(idWins).val()) { $("#alert").text($("#alert").text()+" "+checklocation[i]+" loses "+wins+" times in a rows.<br/>")}
if(losses >= $(idLosses).val()) { $("#alert").text($("#alert").text()+" "+checklocation[i]+" loses "+losses+" times in a rows.<br/>")}
}
}
function checkWins(n, condition)
{
var wins = parseInt(0);
for(var i=0;i<n.length;i++)
{
if(condition(n[i]))
{
wins += 1
}
else
{
wins = 0
}
}
return wins
}
function checkLosses(n, condition)
{
var losses = parseInt(0);
for(var i=0;i<n.length;i++)
{
if(condition(n[i]))
{
losses = 0
}
else
{
losses += 1
}
}
return losses
}
$.fn.multiline = function(text){
this.text(text);
this.html(this.html().replace(/\n/g,'<br/>'));
return this;
}
function getWheel()
{
if($("input[name=wheel]:checked").val()=="0")
{
wheel = wheel0
}
else
{
wheel = wheel00
}
color = GetColor(wheel)
}
function reset()
{
evenwins = parseInt(0);
}
function GetUserNumbers()
{
var n = $("#spins").val().split(",");
for(var x=0; x<n.length; x++)
{
if(n[x].trim() == "0")
{
n[x] = "37";
}
if(n[x].trim() == "00")
{
n[x] = "38";
}
n[x] = parseInt(n[x].trim());
}
return n;
}
function GetColor(wheel)
{
var color = Array();
if(wheel.length==37)
{
color[1] = "red";
color[2] = "black";
color[3] = "red";
color[4] = "black";
color[5] = "red";
color[6] = "black";
color[7] = "red";
color[8] = "black";
color[9] = "red";
color[10] = "black";
color[11] = "black";
color[12] = "red";
color[13] = "black";
color[14] = "red";
color[15] = "black";
color[16] = "red";
color[17] = "black";
color[18] = "red";
color[19] = "red";
color[20] = "black";
color[21] = "red";
color[22] = "black";
color[23] = "red";
color[24] = "black";
color[25] = "red";
color[26] = "black";
color[27] = "red";
color[28] = "black";
color[29] = "black";
color[30] = "red";
color[31] = "black";
color[32] = "red";
color[33] = "black";
color[34] = "red";
color[35] = "black";
color[36] = "red";
color[37] = "green";
}
if(wheel.length==38)
{
color[1] = "red";
color[2] = "black";
color[3] = "red";
color[4] = "black";
color[5] = "red";
color[6] = "black";
color[7] = "red";
color[8] = "black";
color[9] = "red";
color[10] = "black";
color[11] = "black";
color[12] = "red";
color[13] = "black";
color[14] = "red";
color[15] = "black";
color[16] = "red";
color[17] = "black";
color[18] = "red";
color[19] = "red";
color[20] = "black";
color[21] = "red";
color[22] = "black";
color[23] = "red";
color[24] = "black";
color[25] = "red";
color[26] = "black";
color[27] = "red";
color[28] = "black";
color[29] = "black";
color[30] = "red";
color[31] = "black";
color[32] = "red";
color[33] = "black";
color[34] = "red";
color[35] = "black";
color[36] = "red";
color[37] = "green";
color[38] = "green";
}
return color;
}
</script>
</head>
<body>
Toggle Displays</br><br/>
<div >
<button class="bntshow" id="enterSpins">Enter Spins</button><br/>
<button class="bntshow" id="setAlert">Set Alerts</button><br/>
<button class="bntshow" id="howTo">How To</button><br/>
<input type="radio" name="wheel" value="0">0 Wheel<br/>
<input type="radio" name="wheel" value="00" checked>00 Wheel<br/>
</div><br/>
<div id="alert"></div>
<hr>
<!-- Enter Spins -->
<span class="spanhide" id="divSpins">
<button class="bntcaladd" id="enterPad">Toggle Numberpad</button><br/>
<br/>
<span class="spanhide" id='showSpinsPad'>
<br/>
<button class="bntcal" id="calculator" value="0">0</button>
<button class="bntcal" id="calculator" value="00">00</button><br/>
<button class="bntcal" id="calculator" value="1">1</button>
<button class="bntcal" id="calculator" value="2">2</button>
<button class="bntcal" id="calculator" value="3">3</button><br/>
<button class="bntcal" id="calculator" value="4">4</button>
<button class="bntcal" id="calculator" value="5">5</button>
<button class="bntcal" id="calculator" value="6">6</button><br/>
<button class="bntcal" id="calculator" value="7">7</button>
<button class="bntcal" id="calculator" value="8">8</button>
<button class="bntcal" id="calculator" value="9">9</button><br/>
<button class="bntcaladd" id="clear">Clear</button>
<button class="bntcaladd" id="add">ADD</button><span id="currentSpin"></span>
<br/>
<button class="bntcaladd" id="undo">Undo</button><br/>
<span id="currentSpin"></span>
<br/>
</span>
<span id="clearBox">Enter roulette numbers separated by a comma</span><br/>
<textarea rows="10" cols="50" id="spins"></textarea><br/><br/>
<span id="clearBox1">
<button id="clean">Clear Box</button>
<button id="run">Run</button>
</span>
</span>
<!-- Set Alerts -->
<span class="spanhide" id="divAlerts">
<h2>Evens</h2>
<input type="text" id="evenwin" value="2"> Wins in a row<br>
<input type="text" id="evenloss" value="6"> Losses in a row<br>
<br><br>
<h2>Dozens</h2>
<input type="text" id="dozenwin" value="6"> Wins in a row<br>
<input type="text" id="dozenloss" value="6"> Losses in a row<br>
<br><br>
</span>
<!-- How To -->
<span class="spanhide" id="divHowTo">
How To
</span>
</body>
</html>
Yes, absolutely!
In JavaScript, you are capable of saving functions to variables, and hence pass them around as parameters; this is one of the most powerful aspects of JavaScript. So for example, if you want to check if the color is red, you can write a condition test function that returns true/false as follows:
var checkColor = function(nElement){
var color = color(nElement);
if(color == 'red'){
return true;
}
else if(color == 'black'){
return false;
}
}
So now, you have a variable checkColor that is a function that checks if a color is red or not. Now, you can pass this function into your test function like this:
function test(n,testFunc)
{
var wins = parseInt(0);
var losses = parseInt(0);
for(var i=0;i<n.length;i++)
{
if(testFunc(n[i])) //testFunc = checkColor in this case since we passed in checkColor
{
wins += 1
losses = 0
}
else
{
wins = 0
losses += 1
}
}
test(n,checkColor); //This is where you pass in checkColor as your test func
And so for example, if we wanted to add another test for an even, we could write a function as so:
var checkEven = function(nElement){
if(nElement % 2 == 0){
return true;
}
else{
return false;
}
}
And we could simply run test using this new condition like:
test(n,checkEven);
And so from here, you should get the idea of how to create a test function and pass it into a universal test function. If you need clarification, don't hesitate to ask!
Simply pass the condition as function.
Javascript:
const myFunctionByCondition = (conditionFn) => {
const index = 10
if (conditionFn(index)) return "Condition applies"
return "Condition does not apply"
}
const val = myFunctionByCondition(i => i >= 10)
Typescript:
const myFunctionByCondition = (conditionFn: (i: number) => boolean) => {
const index = 10
if (conditionFn(index)) return "Condition applies"
return "Condition does not apply"
}
const val = myFunctionByCondition(i => i >= 10)

Categories

Resources