not able to use animation for typing game - javascript

I was trying to build a game, but I am not able to setInterval properly. The word is not getting printed on the screen when I click on the start game button, after 5seconds it directly shows GAME OVER.
var btn= document.querySelector('#btn');
btn.addEventListener("click", myMove);
function myMove() {
var word = document.querySelector('#word');
var input=document.querySelector('#written');
var words=['xylophone', 'cat', 'bat', 'chollima'];
var i=0;
var id = setInterval(frame, 5000);
function frame() {
word.innerHTML=words[i];
i = (i < 3) ?( i+1) : 0;
if (input.innerHTML== word.innerHTML) {
clearInterval(id);
} else {
word.innerHTML='GAME OVER';
}
}
}
<div id="heading">TYPING GAME</div>
<label>
<div id="word"></div>
<br>
<input type="text" id="written">
</label>
<button id="btn">START</button>
</body>

Actually, there are some issues with your current solution.
First of all, you are changing the word.innerHTML for the first time after the 5 second interval, so it will instantly get replaced by GAME OVER, so with a difference of some millisecond the innerHTML will be change and you won't be able to see the desired output.
Then you are using input.innerHTML for your condition where innerHTML only uses for HTML elements which are containing some content within them (got opening and closing tags) whilst for taking input value you should use input.value.
Thus, in order to make your code work, you should replace the innerHTML in the very first place before executing the setInterval. Then after calling the interval if the condition met you should increment the i value and then call your interval again recursively.
So your final code should be something like this:
var btn = document.querySelector('#btn');
btn.addEventListener("click", myMove);
function myMove() {
var word = document.querySelector('#word');
var input = document.querySelector('#written');
var words = ['xylophone', 'cat', 'bat', 'chollima'];
var i = 0;
word.innerHTML = words[i];
var id = setInterval(frame, 5000);
function frame() {
if (input.value == word.innerHTML) {
clearInterval(id);
i = (i < 3) ? (i + 1) : 0;
word.innerHTML = words[i];
id = setInterval(frame, 5000)
} else {
word.innerHTML = 'GAME OVER';
}
}
}
<div id="heading">TYPING GAME</div>
<label>
<div id="word"></div>
<br>
<input type="text" id="written">
</label>
<button id="btn">START</button>

Don't use input.innerHTML, use input.value instead:
var btn= document.querySelector('#btn');
btn.addEventListener("click", myMove);
function myMove() {
var word = document.querySelector('#word');
var input=document.querySelector('#written');
var words=['xylophone', 'cat', 'bat', 'chollima'];
var i=0;
var id = setInterval(frame, 5000);
function frame() {
word.innerHTML=words[i];
i = (i < 3) ?( i+1) : 0;
if (input.value == word.innerHTML) {
clearInterval(id);
} else {
word.innerHTML='GAME OVER';
}
}
}
<div id="heading">TYPING GAME</div>
<label>
<div id="word"></div>
<br>
<input type="text" id="written">
</label>
<button id="btn">START</button>
</body>

Related

Repeating a div based on user input (JavaScript solution preferred)

Looking for the simplest implementation of the following problem:
I have a user input number field like:
<input type="number" id="numInput" name="numInput" value="1" onchange="myFunc()">
<div id="demo">*** TEST ***</div>
I want to replicate the #demo div based on the #numInput value entered by the user, e.g. if the user enters '5', there would be five #demo divs displayed on the page. At the moment, I'm using the following function:
function myFunc() {
var newArray = [];
var numInput = document.getElementById('numInput').value;
var x = document.getElementById('demo').innerHTML;
for(var i=0; i<numInput; i++) {
newArray.push(x);
}
document.getElementById('demo').innerHTML = newArray;
}
but this is adding to the existing array rather than outputting the exact number of divs based on user input. Please advise. Thanks.
There should not be multiple same id values.
function myFunc() {
let numInput = document.getElementById("numInput");
while (numInput.nextSibling) {
numInput.nextSibling.remove();
}
let numInputval = document.getElementById('numInput').value;
for(var i=numInputval; i>0; i--) {
var newDiv = document.createElement('div');
newDiv.setAttribute('id', 'demo' + i);
newDiv.innerHTML = '*** TEST ***';
numInput.parentNode.insertBefore(newDiv, numInput.nextSibling);
}
}
<input type="number" id="numInput" name="numInput" onchange="myFunc()">
+Edit
You can also manipulate <form> with javascript.
function myFunc() {
let numInput = document.getElementById("numInput");
while (numInput.nextSibling) {
numInput.nextSibling.remove();
}
let numInputval = document.getElementById('numInput').value;
for(var i=numInputval; i>0; i--) {
var newInput = document.createElement('input');
newInput.setAttribute('id', 'demoInput' + i);
newInput.setAttribute('type', 'text');
newInput.setAttribute('name', 'demoInputName' + i);
newInput.setAttribute('onchange', 'myFormChangeListener(this)');
numInput.parentNode.insertBefore(newInput, numInput.nextSibling);
numInput.parentNode.insertBefore(document.createElement('br'), numInput.nextSibling);
}
}
function myFormChangeListener(element) {
console.log(element);
console.log(element.value);
myForm.action = 'http://the.url/';
myForm.method = 'post';
console.log(myForm);
//myForm.submit;
}
<form id="myForm">
<input type="number" id="numInput" name="numInput" onchange="myFunc()">
</form>

Changing image while clicking button in html/javascript

Please i want to change the temperature level in each button click. In a way to have a white arrow in a first time, two white arrow i a seconde time .... i have images withe 1 arrow, 2 arrow ext.
this my image in html :
<div id="WBR"><img src="assets/AWImages/V0.png"></div>
<button id= "HI" class="circle" >+</button>
I simulate the button click in javascript like this :
let addb = document.querySelector('#HI');
addb.addEventListener('click', () =>{
input.value = parseInt(input.value)+1;
if((input.value)<5)
{
socket.emit('Value of hum changed',input.value);
}
else
{
input.value =4;
}
});
I really appreciate ur help ;)
let addb = document.querySelector('#WBR');
let wbr = document.querySelector('#HI');
var f = document.querySelector('#f');
var Score = 0;
var win = 5;
var gameOver = false;
addb.addEventListener("click", function () {
if (!gameOver) {
Score++ ;
if (Score == win) {
gameOver = true;
addb.style.color = "green";
}
f.innerHTML = Score;
}
});
<div id="WBR"><img src="assets/AWImages/V0.png"></div>
<button id= "HI" class="circle" >+</button>
<p id="f">0</p>

use location.hash to keep page status in javascript

I am doing a practice that use location.hash to keep page's state, what i have done using the below code is
1.click any button, the button's innerHTML will be written into the div#cont
2.refresh the page, it keeps the changes in the div#cont
<body>
<button id="a">A</button>
<button id="b">B</button>
<button id="c">C</button>
<div id="cont"></div>
<script>
// var hashValue;
function getHash() {
var hashValue = location.hash;
return hashValue;
}
function draw() {
var cont = getHash();
if (cont) {
document.getElementById('cont').innerHTML = cont.slice(1);
}
}
btns = document.getElementsByTagName('button');
for (i = 0; i < btns.length; i++) {
btns[i].index = i;
btns[i].onclick = function() {
location.hash = btns[this.index].innerHTML;
}
}
window.onhashchange = function() {
draw();
}
draw();
</script>
</body>
And what i want to achieve next is add three other buttons(D,E,F) and a new div, when clicking one of the D\E\F, the innerHTMl will written into the new div.
The final goal is
click one of the A\B\C, the value will be written into 'contABC'
click one of the D\E\F, the value will be written into 'contDEF'
keep the changes when the page refresh
because this time it has to record two value, and i have no idea how to use hash to do that, anyone can help? Thanks in advance!
This is HTML:
<button id="a">A</button>
<button id="b">B</button>
<button id="c">C</button>
<button id="d">D</button>
<button id="e">E</button>
<button id="f">F</button>
<div id="contABC"></div>
<div id="contDEF"></div>
Try by structuring the way you store the hash value , like using a separator -
<body>
<button data-attr='ABC' id="a">A</button>
<button data-attr='ABC' id="b">B</button>
<button data-attr='ABC' id="c">C</button>
<button data-attr='DEF' id="d">D</button>
<button data-attr='DEF' id="e">E</button>
<button data-attr='DEF' id="f">F</button>
<div id="contABC"></div>
<div id="contDEF"></div>
<script>
// var hashValue;
function getHash() {
var hashValue = location.hash && location.hash.slice(1);
return hashValue && hashValue.split('-');
}
function draw() {
var cont = getHash();
if (cont && cont.length>0) {
document.getElementById('contABC').innerHTML = cont[0];
document.getElementById('contDEF').innerHTML = cont[1];
}
}
btns = document.getElementsByTagName('button');
var seperator = '-';
for (i = 0; i < btns.length; i++) {
btns[i].index = i;
btns[i].onclick = function() {
var cont = getHash() || [];
if(btns[this.index].dataset.attr=='ABC'){
location.hash = btns[this.index].innerHTML + seperator + cont[1];
}else{
location.hash = cont[0] + seperator + btns[this.index].innerHTML ;
}
}
}
window.onhashchange = function() {
draw();
}
draw();
</script>
</body>

How to show nearest div id for a given input number?

Let's say I have the following input field:
<input id="inputField" type="number" value="">
and some divs such as:
<div id="1000"></div>
<div id="1200"></div>
<div id="1500"></div>
<div id="1900"></div>
...
When the user enters a number in the input field, I want my code to go to the nearest div id to that number.
e.g: If user enters 1300 then show div with id = "1200".
What's the most efficient way to implement that in javascript considering there will be a large number of divs?
Right now I'm doing:
<script>
function myFunction()
{
var x = document.getElementById("inputField").value;
if(x >= 1750 && x <= 1900)
{
window.location.hash = '#1800';
}
}
</script>
One way is to wrap all your divs with number ids in another div if you can (and give it some id, say 'numbers'); this allows you to find all the divs in your javascript file.
Javascript:
// Get all the divs with numbers, if they are children of div, id="numbers"
let children = document.getElementById('numbers').children;
let array = [];
for (i = 0; i < children.length; i++) {
// Append the integer of the id of every child to an array
array.push(parseInt(children[i].id));
}
// However you are getting your input number goes here
let number = 1300 // Replace
currentNumber = array[0]
for (const value of array){
if (Math.abs(number - value) < Math.abs(number - currentNumber)){
currentNumber = value;
}
}
// You say you want your code to go to the nearest div,
// I don't know what you mean by go to, but here is the div of the closest number
let target = document.getElementById(currentNumber.toString());
Let me know if there's more I can add to help.
Demo
function closestNum() {
let children = document.getElementById('numbers').children;
let array = [];
for (i = 0; i < children.length; i++) {
array.push(parseInt(children[i].id));
}
let number = document.getElementById('inputnum').value;
currentNumber = array[0]
for (const value of array) {
if (Math.abs(number - value) < Math.abs(number - currentNumber)) {
currentNumber = value;
}
}
let target = document.getElementById(currentNumber.toString());
document.getElementById('target').innerHTML = target.innerHTML;
}
<div id="numbers">
<div id="1000">1000</div>
<div id="2000">2000</div>
<div id="3000">3000</div>
<div id="4000">4000</div>
<div id="5000">5000</div>
</div>
<br />
<input type="text" id="inputnum" placeholder="Input Number" onchange="closestNum()" />
<br />
<br /> Target:
<div id="target"></div>
With some optimization this shall be ok-
var element;
document.addEventListener("change",
function(evt){
if(element && element.classList){
element.classList.remove("selected", false);
element.classList.add("unselected", true);
}
var listOfDivs =
document.querySelectorAll(".unselected");
var val = evt.target.value;
var leastAbs=listOfDivs[0].id;
for(let anIndex=0, len=listOfDivs.length;anIndex<len;anIndex++){
if(Math.abs(listOfDivs[anIndex].id-val)<leastAbs){
leastAbs = Math.abs(listOfDivs[anIndex].id-val);
element = listOfDivs[anIndex];
}
}
element.classList.remove("unselected");
element.classList.add("selected");
});
.selected{
background-color:red;
}
.unselected{
background-color:yellow;
}
.unselected, .selected{
width:100%;
height:50px;
}
<input id="inputField" type="number" value="">
<div id="1000" class='unselected'>1</div>
<div id="1200" class='unselected'>2</div>
<div id="1500" class='unselected'>3</div>
<div id="1900" class='unselected'>4</div>
This may work for you. Loops through each div and compared it to your inputted ID. Tracks closest one, hides all divs, then displays the closest.
document.getElementById("inputField").addEventListener("change", function(){
var divs = document.getElementsByTagName("div");
var closestDiv = -1;
var inputId = document.getElementById("inputField").value;
for(var i=0; i<divs.length; i++)
{
if(Math.abs(inputId - closestDiv) > Math.abs(inputId - divs[i].id) || closestDiv == -1)
{
closestDiv = divs[i].id;
for (var x = 0; x < divs.length; x++) {
divs[x].style.display = 'none';
}
divs[i].style.display = "block";
}
}
});
See it Live: jsfiddle.net

how to stop a message from a javascript timer from repeating?

I have a timer for my game, but the message will keep going on the mage, so it says it multiple times, i was wondering how you can get it to say it once.
<head>
<script type="text/javascript">
var c=10;
var t;
var timer_is_on=0;
function timedCount() {
document.getElementById('txt').value = c;
c = c - 1;
if (c == -1||c < -1){
var _message = document.createTextNode("You have mined 1 iron ore!");
document.getElementById('message').appendChild(_message);
startover();
}
}
function startover() {
c = 10;
clearTimeout(t);
timer_is_on=0;
doMining();
}
function doMining() {
if (!timer_is_on) {
timer_is_on = true;
t = setInterval(function () {
timedCount();
}, 1000);
}
}
</script>
<SPAN STYLE="float:left">
<form>
<input type="button" value="Mining" onClick="doMining()">
<input type="text" id="txt">
</form>
</SPAN>
<html>
<center>
<div id='message'></div>
Instead of setInterval use window.setTimeout.
This will trigger the function only once.
Edit: if you mean you want one message to appear and update every time, first add global counter:
var mineCount = 0;
Then change the code to this:
if (c <= -1) {
mineCount++;
var _message = "You have mined " + mineCount + " iron ore" + ((mineCount > 1) ? "s" : "") + "!";
document.getElementById('message').innerHTML = _message;
startover();
}
This will assign the contents of the element instead of adding to it each time.
Your startOver function calls doMining(). Surely, it shouldn't...?

Categories

Resources