Why is the JavaScript function checking value before submit - javascript

I have been working on a website that randomly generates math equations, I have the javascript algorithm and the HTML but the problem is the function runs before the value is submitted. This is the code:
const duration = 60000
const end = Date.now() + duration
let correct = 0
let error = 0
let result = -1
function ask() {
const op1 = Math.floor(Math.random() * 100)
const op2 = Math.floor(Math.random() * 100)
result = op1 + op2
document.getElementById('eq').innerHTML = (`${op1} + ${op2} = ?`);
}
function handler(evt) {
document.getElementById("btn01").submit();
if ("btn01" == result) {
correct++
document.getElementById('f').innerHTML = ("correct!")
if (Date.now() < end) ask()
} else {
error++
document.getElementById('f').innerHTML = ("wrong :(")
}
}
document.addEventListener("keyup", handler)
ask()
setTimeout(() => {
document.getElementById('q').innerHTML = (`${correct} correct and ${error} error`)
document.removeEventListener("keyup", handler)
}, duration)
<body>
<p>Enter names in the fields, then click "Submit" to submit the form:</p>
<h1><span id="eq"></span></h1>
<form id="btn01">
<input type="number">
<input type="button" id="z" value="Submit" onclick="handler(evt)">
</form>
<h1><span id="f"></span></h1>
<h1><span id="q"></span></h1>
</body>
I have tried using onclick in both HTML and javascript but I either did them wrong or they did not work. Note that this is not a repost of other questions asked for different circumstances. Thanks

There are a couple of issues in your code. I have made a couple of changes and show below. The first is that you need to read the value from the input field. Not sure what you were trying to do reading the button. The second is the keyup event handler was annoying because it checked after every key press.
<!DOCTYPE html>
<html>
<body>
<p>Enter names in the fields, then click "Submit" to submit the form:</p>
<h1><span id="eq"></span></h1>
<form id="btn01">
<input type="number" id="answer">
<input type="button" id = "z" value="Submit" onclick="handler(event)">
</form>
<h1><span id="f"></span></h1>
<h1><span id="q"></span></h1>
<script>
const duration = 60000
const end = Date.now()+duration
let correct = 0
let error = 0
let result=-1
function ask() {
const op1 = Math.floor(Math.random()*100)
const op2 = Math.floor(Math.random()*100)
result = op1 + op2
document.getElementById('eq').innerHTML = (`${op1} + ${op2} = ?`);
}
function handler(evt) {
//document.getElementById("btn01").submit();
if (document.getElementById("answer").value == result) {
correct++
document.getElementById('f').innerHTML =("correct!")
if (Date.now()<end) ask()
}
else {
error++
document.getElementById('f').innerHTML =("wrong :(")
}
}
//document.addEventListener("keyup", handler)
ask()
setTimeout(()=>{
document.getElementById('q').innerHTML =(`${correct} correct and ${error} error`)
document.removeEventListener("keyup", handler)
}, duration)
</script>
</body>
</html>

several issues.
you should have added a click event listener to submit button, not 'keyup', because it listens to every button pushed and submits the form even though the user might have not submitted willingly.
The main error is caused by -> document.getElementById("btn01").submit(); in the handle function. when you add click event, button click will automatically submit form.
You can handle event listeners in this manner document.getElemetById('buttonIdExample').addEventListener("click", handler).
and remove the listener this way.
You can also define variable -> const Button = document.getElemetById('buttonIdExample') and then -> Button.addEventListener("click", handler).
finally, for the best practice, define more easy-to-understand variable names.

Related

word does not display in Chrome until you end the shuffle [duplicate]

This question already has answers here:
While True loop prevents page from loading
(5 answers)
Closed 24 days ago.
In this program below, the variable word does not display in any browser every time you shuffle.
let word = prompt("Enter a word:");
while (true) {
let scramble = scrambleWord(word);
displayWord(scramble);
let again = prompt("Scramble again? (y/n)");
if (again === "n") {
break;
}
}
function scrambleWord(word) {
word = word.split("").sort(() => Math.random() - 0.5).join("");
return word;
}
function displayWord(scramble) {
let displayArea = document.getElementById("display-area");
displayArea.innerHTML = scramble;
}
<!DOCTYPE html>
<html>
<body>
<div id="display-area"></div>
</body>
</html>
Any ideas what is wrong with it?
Regards,
Lee
the word should appear each time it's shuffled.
To do exactly what you want it´s necessary to put the prompt function inside a promisse and use a setTimeout() function to wait a minimum time to let the browse display the tag in the page.
like this:
function displayWord() {
getPrompt().then((word) => {
if (word !== 'n') {
document.getElementById('display-area').textContent = word
.split('')
.sort(() => Math.random() - 0.5)
.join('');
displayWord();
}
});
}
function getPrompt() {
return new Promise((resolve) => {
setTimeout(() => {
resolve(prompt('Enter a word (enter \'n\' to exit):'));
}, 30);
});
}
displayWord();
<div id="display-area"></div>
The problem is that the prompt() method blocks the JavaScript execution and does not allow the webpage to update and display the id="display-area" div element. As a result the code you provided wont appear each time it's shuffled.
Instead, what you can do is add a button instead of a prompt and add an Event Listener.
Below, I edited your code to show how you can achieve your desired output using button and Event Listener instead of prompt.
let scrambleButton = document.getElementById("scramble-button");
scrambleButton.addEventListener("click", scrambleWord);
function scrambleWord() {
let word = document.getElementById("word-input").value;
let scramble = word.split("").sort(() => Math.random() - 0.5).join("");
let displayArea = document.getElementById("display-area");
displayArea.innerHTML = "Original Word: " + word + "<br>Scrambled Word: " + scramble;
}
<div id="display-area"></div>
<input type="text" id="word-input">
<button id="scramble-button">Scramble</button>
Explanation: The word input id input element accepts data from the user. Whenever the scramble-button id button element is clicked, it will trigger the Event Listener calling the scrambleWord() and shuffle the word. I hope this will help you.
I'm not sure but
I think this might be due to the script loading before your DOM tree is finished loading. you can fix this by adding the defer tag after your script
Try it out and let me know if it worked :)
src = https://javascript.info/script-async-defer
As explained by #JohnnyMopp in the first comment, the loop is blocking the renderer from updating. But if you don't have to use prompt for this assignment then you can implement the main functionality using a form with a text field, where the user enter the word, and a submit button that will scramble the word when you click on it:
document.getElementById("word-form").addEventListener("submit", function(e) {
e.preventDefault();
let word = document.getElementById("word").value;
let scramble = scrambleWord(word);
displayWord(scramble);
});
/*let word = prompt("Enter a word:");
while (true) {
let scramble = scrambleWord(word);
displayWord(scramble);
let again = prompt("Scramble again? (y/n)");
if (again === "n") {
break;
}
}*/
function scrambleWord(word) {
word = word.split("").sort(() => Math.random() - 0.5).join("");
return word;
}
function displayWord(scramble) {
let displayArea = document.getElementById("display-area");
displayArea.innerHTML = scramble;
}
<!DOCTYPE html>
<html>
<body>
<form id="word-form">
<label>
Enter a word:
<input type="text" name="word" id="word" />
</label>
<input type="submit" name="submit" id="submit" value="submit" />
</form>
<div id="display-area"></div>
</body>
</html>

Javascript: Hidden Input Barcode Scanner

Here's my current setup:
I have a barcode scanner in keyboard mode. I am trying to scan to a hidden and out of focus input.
The barcode I am trying to read is as follows: asterisk [barcode-info] asterisk.
<form method="post">
<input type="hidden" name="action" value="barcode-scan"/>
<input type="hidden" name="barcode-input" value="" id="barcode-input" onchange="this.form.submit()" />
</form>
When a barcode input is made, Javascript should capture it and update the "barcode-input" hidden input, which will then submit itself to the server.
Someone recommended trying to use a paste event listener, but it simply didn't seem to capture the input at all.
Update: because of wonderful suggestions below, I've been able to get the input working! The form will test to see if two specific inputs follow each other, then it will execute the next function. Otherwise, it will erase any information contained in the log const. Ultimately, yes, I got this working correctly!
document.addEventListener('keyup', function(e){
const log = document.getElementById('barcode-input');
log.textContent += ' ' + e.code;
document.getElementById('barcode-input').value = log.textContent;
if (log.textContent.startsWith(' ShiftLeft')) {
if (log.textContent.startsWith(' ShiftLeft Backslash')) {
document.getElementById('barcode-input').form.submit();
console.log('e.code, submit barcode info');
}
}
else {
log.textContent = '';
document.getElementById('barcode-input').value = '';
}
});
Without an input[type="text"] element on the screen, you will need to capture the keyboard input manually. Something along the lines of:
document.addEventListener('keydown', (ev) => {
if (ev.ctrlKey || ev.altKey) return; // Ignore command-like keys
if (ev.key == 'Enter') {
// ...submit the content here...
} else if (ev.key == 'Space') { // I think IE needs this
document.getElementById('barcode-input').value += ' ';
} else if (ev.key.length == 1) { // A character not a key like F12 or Backspace
document.getElementById('barcode-input').value += ev.key;
}
});
That should get you most of the way...
Alternatively, rather than looking for events on the input or values of the input (*'s), define an event on the value and use the input event to simply set the value.
Once input has stopped, be it 1 second (or most likely much less) then fire off the form.
If you have to place the cursor into input, then scan. your prob only option is to use autofocus attribute and hide the input as you cant focus a hidden element, though you also cant focus multiple so keep that in mind if you're looking to scan into multiple inputs, then you will have to show the inputs, no way around it.
For example
let elm = document.querySelector('input[name="barcode-input"]')
// watcher on the value, after 1 second, it invokes an event, i.e post form
let timer = 0
Object.defineProperty(window, 'barcode', {
get: function () { return this.value },
set: function (value) {
clearTimeout(timer)
this.value = value
timer = setTimeout(() => {
console.log('Post form')
}, 1000) // do some tests, tweak if much less then 1 second to input the value
}
})
// it should trigger input even if its a keyboard
elm.addEventListener("input", e => barcode = e.target.value)
// ignore, below this line..
// set a value of barcode at intervals, only when its stopped entering (>1 second), then will it fire the callback
let i = 0
let t = setInterval(() => {
barcode = (barcode || '')+"X"
if (i >= 40) clearInterval(t)
i++
}, 100)
// ignore... grab value from hidden input, put in #current
setInterval(() => document.querySelector('#current').innerHTML = barcode, 1000)
<input type="text" name="barcode-input" autofocus style="display:none" />
<div id="current"></div>
Here's demonstrator using keypress that scans the incoming key stream for *[ and captures the barcode until it sees ]*. Then it sends the code to the server. Although I've reproduced the form in your HTML, the code here doesn't use it.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
Working...
<form method="post">
<input type="hidden" name="action" value="barcode-scan"/>
<input type="hidden" name="barcode-input" value="" id="barcode-input" onchange="this.form.submit()" />
</form>
<p id="response"></p>
<script>
(function(){
"use strict";
const bcAst = '*';
const bcLeft = '[' ;
const bcRight = ']';
let barcodeIncoming = false;
let lastChar = 0;
let barcode = '';
document.addEventListener('keypress', function(e){
function sendCode(barcode) {
console.log(barcode);
let fd = new FormData();
fd.append('barcode', barcode);
fetch('myFile.php', {
method: 'POST',
body: fd
})
.then(resp=>{
resp.text().then(txt=>{document.getElementById('response').innerText = txt;})
});
}
console.log(e.key);
switch (e.key) {
case bcAst:
if (barcodeIncoming && (lastChar === bcRight)) {
barcodeIncoming = false;
sendCode(barcode);
}
break;
case (bcLeft):
if (lastChar === bcAst) {
barcodeIncoming = true;
barcode = '';
}
break;
case (bcRight):
break;
default:
barcode += (barcodeIncoming)?e.key:'';
break;
}
lastChar = e.key;
});
})();
</script>
</body>
</html>
The current server file is very rudimetary, but serves the purpose here:
<?php
if (isset($_POST['barcode'])) {
echo "Your barcode is {$_POST['barcode']}";
} else {
echo "No barcode found";
}
Note - this has had only basic testing. You'll want to improve its resilience against possible collisions with similar data in the key stream.
transfrom
<input type="hidden" name="barcode-input" value="" id="barcode-input" onchange="this.form.submit()" />
in
<input type="test" name="barcode-input" value="" id="barcode-input" onchange="this.form.submit()" style="display:none;" />

Javascript push input into Array causes several arrays not one

This is a follow up to my question, seen here
I am trying to write that when a user enters in their name (string) into the field and hits enter, it pushes it into an array. It works, kinda. But I get an error when I try it one and then it produces multiple arrays when I try it another. I don't want to use jQuery.
Here is the HTML
<input type="text"
class="theplayer pre"
name="Player"
id="bind"
placeholder="Enter Names"
/>
<button type="button" id="thego" class="pre enterteam" value="click">Go</button>
Here is my js that works but it creates multiple arrays instead of pushing everything into one array (because the nextElementSibling is not called, I know this, see next block
let namesOfPlayers = [];
let currentValue = document.getElementById("bind").value;
let button = currentValue.nextElementSibling;
document.addEventListener('keypress', function (e) {
const key = e.which || e.keyCode;
if (key === 13) {
namesOfPlayers.push(currentValue);
console.log('namesOfPlayers', namesOfPlayers);
}
});
Here is my js that throws an error (I don't want to use jQuery)
I want that when a user hits enter or clicks the button that the string is submitted and added into the empty array. I can't for the life of me figure out how to make that work.
Thanks for your help!
You fetch the value of the input too soon. You should fetch it only when the button is clicked, not before.
Secondly, the button does not have a keypress event, nor a keyCode associated with it. You need to listen to the click event.
So do this:
let namesOfPlayers = [];
let input = document.getElementById("bind");
let button = input.nextElementSibling;
button.addEventListener('click', function (e) {
namesOfPlayers.push(input.value);
console.log('namesOfPlayers', namesOfPlayers);
});
<input type="text"
class="theplayer pre"
name="Player"
id="bind"
placeholder="Enter Names" />
<button type="button" id="thego" class="pre enterteam" value="click">Go</button>
Try this code, i added a click (for the button) and keypress (for the text input) events
so if you click enter when you focus on the text input the text in the input will be in the array.
and the same will happen if you click "Go" button
let namesOfPlayers = [];
let currentElement = document.getElementById("bind");
let button = currentElement.nextElementSibling;
let addPlayer = () => {
namesOfPlayers.push(currentElement.value);
console.log(namesOfPlayers); // Just for testing
}
currentElement.addEventListener('keypress', function (e) {
if (e.which === 13 || e.keyCode === 13) {
addPlayer();
}
});
button.addEventListener('click', addPlayer);
<input type="text"
class="theplayer pre"
name="Player"
id="bind"
placeholder="Enter Names"
/>
<button type="button" id="thego" class="pre enterteam" value="click">Go</button>
CurrentValue is defined outside of the event listener, so it only gets called once, on initialisation. That's why the push call only injects empty strings. Also, the button doesn't do anything because it doesn't have a listener.
Here's the updated code:
let namesOfPlayers = [];
// It's better to get the button by id instead of getting it by a previous child.
// This is because it might cause some unexpected behaviour if someone changed the HTML.
const button = document.getElementById("thego");
button.addEventListener('click', function (e) {
addItemToArray(namesOfPlayers);
});
document.addEventListener('keypress', function (e) {
const key = e.which || e.keyCode;
if (key === 13) {
addItemToArray(namesOfPlayers);
}
});
function addItemToArray(namesOfPlayers) {
const currentValue = document.getElementById("bind").value;
namesOfPlayers.push(currentValue);
console.log('namesOfPlayers', namesOfPlayers);
}
https://fiddle.jshell.net/4k4a9m6y/
But, you're better off with a form to improve performance.
let namesOfPlayers = [];
const form = document.getElementById("form");
form.addEventListener('submit', function (e) {
const currentValue = document.getElementById("bind").value;
namesOfPlayers.push(currentValue);
console.log('namesOfPlayers', namesOfPlayers);
});
<form id="form"
action="javascript:void(0);">
<input type="text"
class="theplayer pre"
name="Player"
id="bind"
placeholder="Enter Names"
/>
<button type="submit" id="thego" class="pre enterteam" value="click">Go</button>
</form>
https://fiddle.jshell.net/4k4a9m6y/2/

inner.html / handlers

as an incoming javascript coder, i'm stuck at a sample exercise...
<script language="JavaScript">
var num1;
var messages;
var answer = document.getElementById("guess").value;
var counter = 0;
answer = Math.floor(1 + Math.random() * 32);
function start() {
var button = document.getElementById("guessButton");
button.addEventListener("click", Myguess, false);
};
function Myguess() {
num1 = document.getElementById("guess").value;
do {
if (num1 == answer) {
messages.innerHTML = "Ahah!"
}
if (num1 < answer) {
messages.innerHTML = "Either you know the secer or you got lucky!";
}
if (num1 > answer) {
messages.innerHTML = "you should be able to do better";
}
}
}
</script>
<body>
<form action="#">
<input id="guessButton" type="button" value="guess">
<input id="inputfield" type="number" value="guess a number 1- 32">
</form>
</body>
this is supposed to print:
number of guesses is 5 or fewer: "either you know the secret or you got lucky"
Or number of guesses is 5 or more:"you should be able to do better"
Or number of guesses in 5 tries : "ahah!"
however it's not printing .../././
Initially there are few syntax errors to correct
do {} without while is not valid javascript.
start() is never called. I'm guessing you intended to use window.onload = start or <body onload="start();">
Your script is executed before the HTML elements it is modifying. If you want to access elements from the DOM you should access them within a function and/or place the script at the bottom of the body tag.
<script language="JavaScript"> is deprecated. I think you mean <script type="text/javascript"> although as that is the default the type is optional.
The messages variable is never assigned
You set text as the value to a number input. I suspect you intended to use placeholder="guess a number 1- 32". Note that placeholder is actually used to provide a hint about expected input. Direct instructions should use a label. This doesn't affect your javascript but is worth considering all the same.
Additionally myGuess() currently checks if the submitted value is less than the answer or more. You need to increment a count value and compare against that.
The below example do what you need
<form action="#">
<label for="inputfield">guess a number 1-32</label>
<input id="guessButton" type="button" value="guess">
<input id="inputfield" type="number">
</form>
<p id="messages"></p>
<script type="text/javascript">
var num1;
var target = 5;
var messages = document.getElementById("messages");
var counter = 0;
var answer = Math.floor(1 + Math.random() * 32);
function start() {
var button = document.getElementById("guessButton");
button.addEventListener("click", Myguess, false);
};
function Myguess() {
num1 = document.getElementById("inputfield").value;
if(num1 == answer) {
if (counter === target) {
messages.innerHTML = "Ahah!"
}
if (counter < target) {
messages.innerHTML = "Either you know the secer or you got lucky!";
}
if (counter > target) {
messages.innerHTML = "you should be able to do better";
}
} else {
counter++;
messages.innerHTML = "Keep trying";
}
}
window.onload = start;
</script>
<script language="JavaScript">
var num1;
var messages; // should be initialized inside start because at this moment it doen't exist
var answer;
var counter = 0;
answer = Math.floor(1 + Math.random() * 32);
window.addEventListener("load", start); // on loading the page call start;
function start() {
messages = document.getElementById("message"); // this should be something
var button = document.getElementById("guessButton");
button.addEventListener("click", Myguess, false);
};
function Myguess() {
num1 = document.getElementById("inputfield").value; // the id is "inputfield" not "guess"
if (num1 == answer) {
messages.innerHTML = "Ahah!"
}
// else if to stop checking again (if is correct but not the best)
else if (num1 < answer) {
messages.textContent = "Either you know the secer or you got lucky!"; //textContent is better than innerHTML
}
// same here
else if (num1 > answer) {
messages.innerHTML = "you should be able to do better";
}
}
</script>
<body>
<form action="#">
<input id="guessButton" type="button" value="guess">
<input id="inputfield" type="number" value="guess a number 1- 32">
</form>
<div id="message"></div>
</body>
Note: you was using do-while incorrectly (you was messing the while part). Anyway, do-while or any other loop will just loop forever if the answer is not correct because you are not letting the user to re-enter a number. What you need is to check whether the number is correct or not whenevr the user click the button (that parts you had it correct because you used the event listener).
What your code was doing (or supposed to be doing) is check if a user clicks the button and then loop if his answer was incorrect untill the answer is is correct (which is not going to happen because you never give the user another chance to enter a number again. He will get a chance after the function execution is finished. And because of the loop it will never be finished). It was never going to work because the loop waits for the user to enter another number (a correct one) to exit and the user is waiting for the loop to end to enter another number (see the paradox).
What it should do is to wait for the user to enter a number, check that number, prints the message accordingly for that number and then give the user to enter another number. (It is a loop (cycle) already so why need another loop)
The code you need is this:
<body>
<form id="form">
<input id="guessButton" type="submit" value="guess">
<input id="inputfield" type="number" placeholder="guess a number 1-32">
</form>
<div id="messages"></div>
<span id="counter"></span> tries
</body>
<script language="JavaScript">
document.getElementById('form').onsubmit = function() {
return Myguess();
};
var num1;
var messages = document.getElementById("messages");
var counterDiv = document.getElementById("counter");
counterDiv.innerHTML = 0;
var counter = 0;
answer = Math.floor(1 + Math.random() * 32);
function Myguess() {
num1 = document.getElementById("inputfield").value;
if (num1 == answer) {
messages.innerHTML = "Ahah!"
}
if (num1 < answer) {
messages.innerHTML = "Either you know the secer or you got lucky!";
}
if (num1 > answer) {
messages.innerHTML = "you should be able to do better";
}
counter++;
counterDiv.innerHTML = counter;
return false;
}
</script>
You can test it in this JSFiddle.
The function Myguess() is called when the form is submitted. There was no div messages missing in your code, so I added it. I also added the counter span which shows how many tries the player has had. Also the message "guess a number 1-32" is better added as placeholder. I hope that was helpful !

Displaying Counter on The Actual HTML Button

I have a 'like' button; and underneath the button, I can display the 'like count'.
However, I want the 'like count' value to be displayed on the actual button itself. For example, I want the button to say: "Like 5"
How can I display both text and a variable value on a button?
Maybe you can improving with this code that i did.
HTML
<form id = "form" method = "POST">
<input type = "submit" value = "Like" />
</form>
<br />
<div id = "clicks">
counter = <label id = "count">0</label> clicks !
</div>
JS
function CountOnFormSubmitEvent(form_id, _callback_)
{
var that = this, count = 0, callback = _callback_;
var form = document.getElementById(form_id);
if(form === null) { return null; }
var reset = function(){
count = 0;
};
form.addEventListener("submit", function(evt){
callback(evt, ++count, reset);
}, false);
}
//Reseting Process You can delete if you dont want it.
var counter = new CountOnFormSubmitEvent("form", function(event, count, reset_callback){
event.preventDefault();
if(count >= 10)
{
alert("Reseting the process");
reset_callback();
}
document.getElementById("count").innerHTML = count;
});
Here is the link Jsfiddle.
DEMO JSFIDDLE

Categories