I was creating a dialog to confirm action by user.
We can achieve that by confirm() dialog like this:
function btnChangeBodyColorFunc() {
let text = "You are going to change body color.Are you sure";
if (confirm(text) == true) {
document.body.style.backgroundColor = "red";
console.log("You changed!");
} else {
document.body.style.backgroundColor = "";
console.log("You canceled!");
}
}
<button onclick="btnChangeBodyColorFunc()">Change body color to red</button>
But can it be sort of custom like this:
let iConfirmToGoAhead = ""
let confirmDialog = document.querySelector(".confirmDialog");
function btnChangeBodyColorFunc() {
confirmDialog.style.display = "flex";
if (iConfirmToGoAhead === "true") {
document.body.style.backgroundColor = "red";
console.log("You changed!");
iConfirmToGoAhead = ""
} else if (iConfirmToGoAhead === "false") {
document.body.style.backgroundColor = "";
console.log("You canceled!");
iConfirmToGoAhead = ""
}
}
let confirmDialogBtn = document.querySelectorAll(".confirmDialogContent button");
for (let i = 0; i < confirmDialogBtn.length; i++) {
confirmDialogBtn[i].addEventListener('click', confirmDialogBtnFunc)
}
function confirmDialogBtnFunc() {
confirmDialog.style.display = "none";
iConfirmToGoAhead = this.dataset.confirmationValue;
}
.confirmDialog {
position: fixed;
display: none;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.7);
height: 100vh;
width: 100vw;
}
.confirmDialogContent {
margin: auto;
}
<button onclick="btnChangeBodyColorFunc()">Change body color to red</button>
<div class="confirmDialog">
<div class="confirmDialogContent">
You are going to change body color.Are you sure
<button data-confirmation-value="true">Yes sure</button>
<button data-confirmation-value="false">No don't change</button>
</div>
</div>
But this way it don't wait for iConfirmToGoAhead value to be confirmed and execute the function.
Know this is how JS works that execute the codes which comes first. I tried use of async and await but that also don't work and throw error(might not applied it right).
Can do required functionality by adding conditions to second function but thought a common way for all critical actions through 1 dialog and change according to it.
Is it possible to have a custom confirmation dialog like this or have to use conditions in 2nd function. Any ideas are most welcome
Thanks for help in advance
As you mentioned in this line, any button click action inside the class confirmDialogContent, should trigger an event & call this function confirmDialogBtnFunc. But you have written all functionality inside the function btnChangeBodyColorFunc.
This function will call only when you click the button Change body color to red. If you make any click event inside the confirmation popup, it will call the confirmDialogBtnFunc function as you mentioned inside the for loop
let confirmDialogBtn = document.querySelectorAll(".confirmDialogContent button");
for (let i = 0; i < confirmDialogBtn.length; i++) {
confirmDialogBtn[i].addEventListener('click', confirmDialogBtnFunc)
}
I have rewritten the code, Please look into it.
I hope that would be useful for you :)
let iConfirmToGoAhead = ""
let confirmDialog = document.querySelector(".confirmDialog");
function btnChangeBodyColorFunc() {
confirmDialog.style.display = "flex";
}
let confirmDialogBtn = document.querySelectorAll(".confirmDialogContent button");
for (let i = 0; i < confirmDialogBtn.length; i++) {
confirmDialogBtn[i].addEventListener('click', confirmDialogBtnFunc)
}
function confirmDialogBtnFunc() {
iConfirmToGoAhead = this.dataset.confirmationValue;
confirmDialog.style.display = "flex";
if (iConfirmToGoAhead === "true") {
document.body.style.backgroundColor = "red";
console.log("You changed!");
iConfirmToGoAhead = ""
} else if (iConfirmToGoAhead === "false") {
document.body.style.backgroundColor = "";
console.log("You canceled!");
iConfirmToGoAhead = ""
}
confirmDialog.style.display = "none";
}
.confirmDialog {
position: fixed;
display: none;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.7);
height: 100vh;
width: 100vw;
}
.confirmDialogContent {
margin: auto;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button onclick="btnChangeBodyColorFunc()">Change body color to red</button>
<div class="confirmDialog">
<div class="confirmDialogContent">
You are going to change body color.Are you sure
<button data-confirmation-value="true">Yes sure</button>
<button data-confirmation-value="false">No don't change</button>
</div>
</div>
</body>
</html>
Related
I am working on The Odin Project and I am on the etch-a-sketch section. I believe I have every part working except resizing the grid when a new number is entered. Any help would be greatly appreciated.
const container = document.getElementById("container");
const button = document.querySelector("input");
button.addEventListener('click', ()=> {
numOfSquares();
})
function numOfSquares() {
if (button.value === "number of squares") {
let newNumPerRow = prompt("how many squares per side would you like?", "");
let parse = parseInt(newNumPerRow);
makeRows(parse);
}
}
function hoverColor() {
let items = document.querySelectorAll('.gridItems');
items.forEach(item => {
item.addEventListener('mouseover', () => {
item.style.backgroundColor = 'orange';
});
});
}
function clearGrid() {
const gridArray = Array.from(container.childNodes);
gridArray.forEach(element => {
container.removeChild(element);
})
}
function makeRows (numberPerRow) {
clearGrid();
const total = (numberPerRow * numberPerRow) + numberPerRow;
const box = numberPerRow + 1;
for (i=0; i < total; i++) {
const div = document.createElement('div');
container.appendChild(div).className = "gridItems";
if (i % box === 0) {
div.style.cssText = "border: 0; height: 0; width: 100%";
} else {
div.style.cssText = "border: 1px solid black; height: 25px; width: 25px";
}
}
hoverColor();
}
makeRows(16);
I have tried to change the inline div style in javascript portion underneath the makeRows function, but nothing seems to work. Unless I completely miss something.
CSS
* {
box-sizing: border-box;
}
#container {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Etch-A-Sketch Project</title>
<link rel="stylesheet" href="style.css">
<script src="index.js" defer></script>
</head>
<body>
<input type="button" value="number of squares">
<div id="container">
</div>
</body>
</html>
I'm not familiar with the project exactly, but taking a look at your js, it looks like you're hard-coding the width value for the elements. Something like this may be helpful if you need to use flex:
function makeRows(numberPerRow) {
clearGrid();
const total = numberPerRow * numberPerRow + numberPerRow;
const box = numberPerRow + 1;
for (i = 0; i < total; i++) {
const div = document.createElement("div");
container.appendChild(div).className = "gridItems";
if (i % box === 0) {
div.style.cssText = "border: 0; height: 0; width: 100%";
} else {
//dynamically resize?
div.style.cssText = `border: 1px solid black; height: ${
1000 / numberPerRow
}px; width: ${1000 / numberPerRow}px`;
//dynamically resize?
}
}
hoverColor();
}
Since you are making a grid though, it may be more helpful to use grid layout rather than flex.
https://developer.mozilla.org/en-US/docs/Web/CSS/grid
https://www.w3schools.com/css/css_grid.asp
I'm giving you a solution using display: grid as this is the preferred method to use when creating a grid (it's in the name).
I left the HTML the exact same.
const container = document.getElementById("container");
const button = document.querySelector("input");
button.addEventListener('click', ()=> {
numOfSquares();
})
function numOfSquares() {
if (button.value === "number of squares") {
let newNumPerRow = prompt("how many squares per side would you like?", "");
let parse = parseInt(newNumPerRow);
makeRows(parse);
}
}
function hoverColor() {
let items = document.querySelectorAll('.gridItems');
items.forEach(item => {
item.addEventListener('mouseover', () => {
item.style.backgroundColor = 'orange';
});
});
}
function clearGrid() {
const gridArray = Array.from(container.childNodes);
gridArray.forEach(element => {
container.removeChild(element);
})
}
function makeRows (numberPerRow) {
clearGrid();
//Set the grid template columns straight from JavaScript
container.style.gridTemplateColumns = `repeat(${numberPerRow}, 1fr)`;
//Resolved an issue here that was adding an extra row
const total = numberPerRow * numberPerRow;
//Idk what the point of box was so I removed it for the sake of the answer
for (i = 0; i < total; i++) {
const div = document.createElement('div');
container.appendChild(div).className = "gridItems";
//Moved the gridItem styling to CSS
}
hoverColor();
}
makeRows(16);
* {
box-sizing: border-box;
}
#container {
display: grid;
width: 100%; /* Set whichever width you want here */
aspect-ratio: 1/1;
}
.gridItems {
border: 1px solid black;
}
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Etch-A-Sketch Project</title>
<link rel="stylesheet" href="style.css">
<script src="index.js" defer></script>
</head>
<body>
<input type="button" value="number of squares">
<div id="container">
</div>
</body>
</html>
Add this at the top of you js and specify the size of your grid in px. You can add it to makeRows as a variant:
const preservedWidth = 600;
Also add boxWidth to makeRows to calculate the width of your grid element:
const boxWidth = preservedWidth / numberPerRow;
Change this:
div.style.cssText = "border: 1px solid black; height: 25px; width: 25px";
to:
div.style.cssText = `border: 1px solid black; height: ${boxWidth}; width: ${boxWidth}`;
This is the whole JS code:
const container = document.getElementById("container");
const button = document.querySelector("input");
const preservedWidth = 300;
button.addEventListener('click', ()=> {
numOfSquares();
})
function numOfSquares() {
if (button.value === "number of squares") {
let newNumPerRow = prompt("how many squares per side would you like?", "");
let parse = parseInt(newNumPerRow);
makeRows(parse);
}
}
function hoverColor() {
let items = document.querySelectorAll('.gridItems');
items.forEach(item => {
item.addEventListener('mouseover', () => {
item.style.backgroundColor = 'orange';
});
});
}
function clearGrid() {
const gridArray = Array.from(container.childNodes);
gridArray.forEach(element => {
container.removeChild(element);
})
}
function makeRows (numberPerRow) {
clearGrid();
const total = (numberPerRow * numberPerRow) + numberPerRow;
const box = numberPerRow + 1;
const boxWidth = preservedWidth / numberPerRow;
for (i=0; i < total; i++) {
const div = document.createElement('div');
container.appendChild(div).className = "gridItems";
if (i % box === 0) {
div.style.cssText = "border: 0; height: 0; width: 100%";
} else {
div.style.cssText = `border: 1px solid black; height: ${boxWidth}; width: ${boxWidth}`;
}
}
hoverColor();
}
makeRows(16);
So right now I have a 20 by 20 grid and I want the user to be able to click and select multiple cells in the grid. There is a method I was able to find online but the problem is that mouseover takes over and highlights the cells right when the mouse is over the cells and this is not what I want. I want the user click on a cells then basically drag their mouse and highlight the cells that they want then execute mouseup once they let go.
These are my files.
let graph = document.getElementById("container");
graph.style.display = "flex";
function createGraph() {
let j = 0;
for (let i = 0; i < 20; i++) {
let row = document.createElement("div");
row.id = "row" + i;
row.style.height = "50px";
row.style.width = "50px";
graph.appendChild(row);
let currentRow = document.getElementById("row" + i);
j++;
for (let j = 0; j < 20; j++) {
let cell = document.createElement("div");
cell.classList.add("cells");
///id's are used later in the project
cell.id = "index" + j + i;
cell.style.border = "1px solid black";
cell.style.height = "50px";
cell.style.width = "50px";
currentRow.appendChild(cell);
}
}
}
createGraph();
function main() {
document.querySelectorAll(".cells").forEach(item => {
["mousedown", "mouseover", "mouseup"].forEach(function(e) {
item.addEventListener(e, function() {
item.style.backgroundColor = "red";
})
})
})
}
main();
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<div id="container"></div>
</body>
</html>
So in the main function I added an even listener to all the cells and I am trying to change their color to red. The problem is that the mouseover event takes over the mousedown which is what I want to happen first. How can I make it so the user is able to first click down on a cell then drag their mouse and keep highlighting cells and once they let go of the mouse the highlighting stops. Is there away to first execute the mousedown, then mouseover and finally the mouseup?
I refactored your code a little. Here is a simple example how you can use toggle state:
let graph = document.getElementById('container');
function createGraph() {
for (let i = 0; i < 20; i++) {
let row = document.createElement('div');
row.id = 'row' + i;
row.className = 'rows';
for (let j = 0; j < 20; j++) {
let cell = document.createElement('div');
cell.className = 'cells';
cell.id = 'index' + j + i;
row.appendChild(cell);
}
graph.appendChild(row);
}
}
createGraph();
function main() {
let canSelect = false;
document.addEventListener('mousedown', () => canSelect = true);
document.addEventListener('mouseup', () => canSelect = false);
document.querySelectorAll('.cells').forEach(item => {
['mousedown', 'mouseover'].forEach(function(e) {
item.addEventListener(e, () => {
if (!canSelect && e !== 'mousedown') return;
item.style.backgroundColor = 'red';
})
})
})
}
main();
#container {
display: flex;
}
.rows, .cells {
width: 50px;
height: 50px;
}
.cells {
border: 1px solid black;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<div id="container"></div>
</body>
</html>
The trick with things like this is to only add the mouseover event on mousedown to begin with. mouseover is generally an expensive event to have anyways (because it fires a lot), so you only "turn it on" when you want and remove it when you don't.
Also, if you're hooking the same event to multiple elements in the same parent, it is far better to assign the event to the parent and then check the target and act when it is one of the children you want (usually using the .matches() method).
Then, you don't have to worry about mousemove firing first, because it'll always fire second. Just be aware it'll probably fire MANY times per cell, so you need to write your code to handle that.
let targetElements = [];
const parent = document.querySelector('.parent');
const mouseoverHandler = ({ target }) => {
if (!target.matches('.parent span')
|| targetElements.includes(target)) {
return;
}
targetElements.push(target);
};
parent.addEventListener('mousedown', ({ target }) => {
// use whatever selector makes sense for your children
if (!target.matches('.parent span')) return;
// reset the list here in case they mouseup-ed outside of the parent
targetElements = [];
// turn mouseover "on"
parent.addEventListener('mouseover', mouseoverHandler);
targetElements.push(target);
console.log('mouseover on');
});
parent.addEventListener('mouseup', ({ target }) => {
// use whatever selector makes sense for your children
if (!event.target.matches('.parent span')) return;
// turn mouseover "off"
parent.removeEventListener('mouseover', mouseoverHandler);
// do something with them
targetElements.forEach(el => el.classList.toggle('on'));
console.log('mouseover off');
});
.parent {
border: 2px solid #333;
width: 150px;
display: flex;
flex-wrap: wrap;
}
.parent span {
flex: 0 0 50px;
flex-wrap: wrap;
height: 50px;
border: 1px solid #CCC;
margin: -1px;
height: 50px;
display: -block;
}
.parent span:hover {
/* doesn't seem to work in the demo window */
background: #EEC;
cursor: pointer;
}
.parent span.on {
background: #F00;
}
<div class="parent">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
I am trying to learn Javascript.
I watched some Javascript course on Youtube and am trying to create my first project.
Project should be simple tic-tac-toe game.
Functionality:
First click on box should fill with "X"
Second click on another box should fill with "Y"
Third click on another box should fill with "X" again and so on until all boxes will be filled with character.
there is my codes
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="main">
<table>
<tr>
<td class="b1-1"></td>
<td class="b1-2"></td>
<td class="b1-3"></td>
</tr>
<tr>
<td class="b2-1"></td>
<td class="b2-2"></td>
<td class="b2-3"></td>
</tr>
<tr>
<td class="b3-1"></td>
<td class="b3-2"></td>
<td class="b3-3"></td>
</tr>
</table>
</div>
<script src="script.js" type="text/javascript"></script>
</body>
</html>
CSS
.main {
padding: 100px 0;
width: 360px;
margin: 0 auto;
}
table, tbody {
margin: 0;
padding: 0;
width: 360px;
height: 360px;
}
tr {
width:360px;
height: 120px;
margin: 0;
padding: 0;
}
td {
text-align: center;
width:120px;
height: 120px;
border: 1px solid #333;
margin: 0;
padding: 0;
font-size: 50px;
}
Javascript
var action = document.querySelectorAll('td');
var gameState = 0;
for (var i = 0; i <= action.length - 1; i++) {
getClassName = "." + action[i].classList.value;
if (gameState === 0) {
document.querySelector(getClassName).addEventListener("click", chasviX(i));
} else {
document.querySelector(getClassName).addEventListener("click", chasviO(i));
}
}
function chasviX(cord) {
document.querySelector("." + action[cord].classList.value).addEventListener("click", event => {
document.querySelector("." + action[cord].classList.value).textContent = "X";
gameState = 1;
});
};
function chasviO(cord) {
document.querySelector("." + action[cord].classList.value).addEventListener("click", event => {
document.querySelector("." + action[cord].classList.value).textContent = "O";
gameState = 0;
});
};
There is project link also - https://jsfiddle.net/qwy2k571/
At the moment each box is filling with "X".
I know i didn't understand closures and scope chains exactly but please give me an correct code to understand it by example.
Thanks in advance and best regards.
Since you are using querySelectorAll which will give a collection, you can iterate that and directly add event listener to it. Aslo you are adding multiple eventlistener which is not required
var action = document.querySelectorAll('td');
var gameState = 0;
action.forEach((item) => {
item.addEventListener('click', (e) => {
if (gameState === 0) {
e.target.textContent = "X";
gameState = 1;
} else {
e.target.textContent = "0";
gameState = 0;
}
})
})
.main {
padding: 100px 0;
width: 360px;
margin: 0 auto;
}
table,
tbody {
margin: 0;
padding: 0;
width: 360px;
height: 360px;
}
tr {
width: 360px;
height: 120px;
margin: 0;
padding: 0;
}
td {
text-align: center;
width: 120px;
height: 120px;
border: 1px solid #333;
margin: 0;
padding: 0;
font-size: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">
<table>
<tr>
<td class="b1-1"></td>
<td class="b1-2"></td>
<td class="b1-3"></td>
</tr>
<tr>
<td class="b2-1"></td>
<td class="b2-2"></td>
<td class="b2-3"></td>
</tr>
<tr>
<td class="b3-1"></td>
<td class="b3-2"></td>
<td class="b3-3"></td>
</tr>
</table>
</div>
Here I made a working jsfiddle: https://jsfiddle.net/1jnkepLg/1/
I simplified the JS part to:
var gameState = 0; // Holds the current game state
var cells = document.getElementsByTagName("td"); // list of cells of the game board
// attach an event listener at each cell.
for (var i=0;i<cells.length;i++)
{
cells[i].addEventListener("click", chasvi);
}
function chasvi()
{
// in event callbacks "this" refers to the element that triggered the event. In this case, it is the TD element.
this.textContent = gameState ? "X" : "0";
// switch the game state
gameState = !gameState;
}
In this case, one event listener is enough, you can determine what X|0 to draw at the callback function.
In your first loop : for (var i = 0; i <= action.length - 1; i++) { ... } you are adding events listeners to each cells. Since the variable gameState is initialized to 0, the condition if (gameState === 0) { ... } will always be true within that loop.
Instead of checking the status of the game during the initialization, just add an event listener as you did, to each cells.
To make sure you pass the correct parameter to the event, you need to wrap the callback within function() { chasvi(param); }, and the whole body of the loop inside another anonymous function, setting another variable to the coordinate i :
for (var i = 0; i <= action.length - 1; i++) {
(function(){
let coor = i;
let getClassName = "." + action[i].classList.value;
document.querySelector(getClassName).addEventListener("click", function() { chasvi(coor); });
}());
}
Note that I changed the name of the function to chasvi because you can manage the case X or O in that function.
In each of the functions chasviX and chasviO you are again adding an event listener. This is not good, because on each clicks, you'll add one more event.
Before clicking, there's already an event.
After clicking once, there are 2 events. Another click, and there's 3 events, and so on...
I suggest you to change thoses functions to 1 function that handles both cases :
function chasvi(cord)
{
let TextToDisplay;
if (gameState === 0)
{
TextToDisplay = "X";
gameState = 1;
}
else
{
TextToDisplay = "O";
gameState = 0;
}
document.querySelector("." + action[cord].classList.value).textContent = TextToDisplay;
}
Since there's only 2 states for gameState, you can use a boolean value. You can initialize it to var gameState = false; I randomly choose false for the X.
And then, the function can be simplified to :
function chasvi(cord)
{
let TextToDisplay;
if (gameState === false)
{
TextToDisplay = "X";
}
else
{
TextToDisplay = "O";
}
gameState = !gameState; // This swaps the state true/false
document.querySelector("." + action[cord].classList.value).textContent = TextToDisplay;
}
This kind of notation :
let TextToDisplay;
if (gameState === false)
{
TextToDisplay = "X";
}
else
{
TextToDisplay = "O";
}
Can be simplified using ternary expressions :
let TextToDisplay = gameState ? "O" : "X"; // This means if gameState is true, then "O" is returned, else "X"
Final code can looks like this :
var action = document.querySelectorAll('td');
var gameState = false;
for (var i = 0; i <= action.length - 1; i++) {
(function(){
let coor = i;
getClassName = "." + action[i].classList.value;
document.querySelector(getClassName).addEventListener("click", function() { chasvi(coor); });
}());
}
function chasvi(cord) {
let TextToDisplay = gameState ? "O" : "X";
gameState = !gameState;
document.querySelector("." + action[cord].classList.value).textContent = TextToDisplay;
}
.main {
padding: 100px 0;
width: 360px;
margin: 0 auto;
}
table, tbody {
margin: 0;
padding: 0;
width: 360px;
height: 360px;
}
tr {
width:360px;
height: 120px;
margin: 0;
padding: 0;
}
td {
text-align: center;
width:120px;
height: 120px;
border: 1px solid #333;
margin: 0;
padding: 0;
font-size: 50px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="main">
<table>
<tr>
<td class="b1-1"></td>
<td class="b1-2"></td>
<td class="b1-3"></td>
</tr>
<tr>
<td class="b2-1"></td>
<td class="b2-2"></td>
<td class="b2-3"></td>
</tr>
<tr>
<td class="b3-1"></td>
<td class="b3-2"></td>
<td class="b3-3"></td>
</tr>
</table>
</div>
<script src="script.js" type="text/javascript"></script>
</body>
</html>
The problem with your solution is that the for loop you have written assigns event listeners for setting an 'X' on the board to every single square BEFORE there is even a single click on the board. This means your if logic will never assign an 'O', since all clicks will call chasviX()
You should instead use a forEach() function of an NodeList like your action variable:
var gameState = false;
action.forEach(function(act) {
act.addEventListener("click", function(event) {
// If gameState is false(logical 0), place an 'X' on the board
// Otherwise, place a 'O'
event.target.textContent = gameState ? 'X' : 'O';
// Invert state at the end
gameState = !gameState;
});
})
Your mistake is that you create the events in such a manner that they depend only on the current value of gameState, before any moves were made. You need to check and change the value of gameState inside the event:
var action = document.querySelectorAll('td');
var gameState = 0;
for (var i = 0; i <= action.length - 1; i++) {
action[i].addEventListener("click", function() {
this.textContent = (gameState = (gameState + 1) % 2) ? 'x' : '0';
})
}
https://jsfiddle.net/fby3g12v/
I am trying to make a simple game using JavaScript and HTML.
The game consists of having two buttons on the screen with random numbers and clicking the one that is smaller.
At the end, you will get your results.
What I am having trouble with is getting the random number generated in JavaScript to print on the button and getting the data back to JavaScript from the button.
var number = prompt('Choose Your Difficulty, Easy, Normal, Or Hard?');
var number = number.toUpperCase(); //Chooses difficulty
if (number === 'EASY')//easy difficulty
{
var difficulty = 20;
}else if (number === 'NORMAL')//normal difficulty
{
var difficulty = 100;
}else if(number === 'HARD')//hard difficulty
{
var difficulty = 1000;
}else
{
alert('Please Enter A Valid Answer')//if value is not valid
}
var number1 = Math.floor((Math.random()* difficulty) + 1);//random number 1
var number2 = Math.floor((Math.random()* difficulty) + 1);//random number 2
//----------------------Code i found but im not sure now to use it--------------
// 1. Create the button
var button = document.createElement("button");
button.innerHTML = "Do Something";
// 2. Append somewhere
var body = document.getElementsByTagName("body")[0];
body.appendChild(button);
// 3. Add event handler
button.addEventListener("click", function() {
alert("did something");
});
//-----------------------------------------------------------------------------
button {
margin-top: 20px;
line-height: 60px;
font-weight: bold;
padding: 0 40px;
background: salmon;
border: none;
}
button:hover {
background: lightsalmon;
}
<!DOCTYPE html>
<html>
<head>
<title>
Speed Game
</title>
<link href="css/styles.css" rel="stylesheet"
type="text/css">
<script src="../script/script.js"></script>
</head>
<body>
<button id= "button">
Do Something!
</button>
</body>
</html>
How can I solve this problem?
First of all, welcome to the world of programming!
Second, here's the game you wanted. I've done everything using functions, so understanding it should be easy.
Try to play a few games first!
The concept is pretty simple, really, so after playing a bit, look at the code and try to figure it out on your own!
var number;
var difficulty = 0;
var randomNumOne;
var randomNumTwo;
var buttonOne = document.getElementById("buttonOne");
var buttonTwo = document.getElementById("buttonTwo");
var tempButton;
function requestDifficulty(){
number = prompt('Choose Your Difficulty, Easy, Normal, Or Hard?');
number = number.toUpperCase();
setDifficulty();
}
function setDifficulty(){
if (number === 'EASY'){
difficulty = 20;
startGame();
}else if (number === 'NORMAL'){
difficulty = 100;
startGame();
}else if(number === 'HARD'){
difficulty = 1000;
startGame();
}else{
alert('Please Enter A Valid Answer');
requestDifficulty()
}
}
function startGame(){
randomNumOne = Math.floor((Math.random()* difficulty) + 1);
randomNumTwo = Math.floor((Math.random()* difficulty) + 1);
buttonOne.innerHTML = randomNumOne;
buttonTwo.innerHTML = randomNumTwo;
}
function getResults(pressedButton){
tempButton = pressedButton;
if(tempButton == "buttonOne"){
if(randomNumOne < randomNumTwo){
alert("Correct!")
}else{
alert("False!")
}
}else if(tempButton == "buttonTwo"){
if(randomNumTwo < randomNumOne){
alert("Correct!")
}else{
alert("False!")
}
}
}
requestDifficulty();
button {
margin-top: 20px;
line-height: 60px;
font-weight: bold;
padding: 0 40px;
background: salmon;
border: none;
}
button:hover {
background: lightsalmon;
}
<!DOCTYPE html>
<html>
<head>
<title>
Speed Game
</title>
</head>
<body>
<button id="buttonOne" onclick="getResults('buttonOne');">
random number 1
</button>
<button id="buttonTwo" onclick="getResults('buttonTwo')">
random number 2
</button>
</body>
</html>
I think this is working but not really. I also don't think that it is the best approach.
The timer serves as another function running while having the ability to change the pulsing rate of the image.
I have tried to use gifs instead of because they have different speeds, there isn't a smooth transition when switching between images.
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript" src="https://code.jquery.com/jquery-latest.js"></script>
<style>
#red-square {
position: absolute;
display: inline-block;
z-index: 1;
top : 200px;
right: 200px;
height: 100px;
width: 100px;
background-color: red;
}
</style>
</head>
<body>
<div id="result"></div>
<div id="red-square"></div>
<button onclick="speedOne();">speed one</button>
<button onclick="speedTwo();">speed two</button>
<button onclick="speedThree();">speed three</button>
<script>
var counter = 0,
stopTimeoutTwo = null,
stopTimeoutThree = null,
currentSpeed = "speed one";
function runCounter() {
counter++;
result.textContent = counter;
if(currentSpeed == "speed one") {
if((counter%60) == 0) {
$("#red-square").hide();
}else if((counter%60) != 0) {
$("#red-square").show();
}
}
else if(currentSpeed = "speed two") {
if((counter%45) == 0) {
$("#red-square").hide();
}else if((counter % 45) != 0) {
$("#red-square").show();
}
}else if(currentSpeed = "speed three") {
if((counter%30) == 0) {
$("#red-square").hide();
}else if((counter%30) != 0) {
$("#red-square").show();
}
}
if(counter < 1e5) timer = setTimeout(runCounter, 0);
}
runCounter();
function stepOne() {
currentSpeed = "speed one";
}
function stepTwo() {
currentSpeed = "speed two";
}
function stepThree() {
currentSpeed = "speed three";
}
</script>
</body>
</html>
You can use setInterval to create your efect like so: Fiddle!
This is the JS I used:
var speed = 4000;
var inter;
var square = document.getElementById("red-square");
square.style.backgroundColor = "red";
function myTime(){
inter = setInterval(function(){
console.log(square.style.backgroundColor+" "+speed);
if(square.style.backgroundColor == "red"){
square.style.backgroundColor = "blue";
}
else{
square.style.backgroundColor = "red";
}
}, speed);
}
function changSpeed(s){
clearInterval(inter);
speed = s;
inter=null;
myTime();
}
myTime();
the rest is your code.