Trying to understand JS functions - what am I doing wrong? - javascript

I'm currently working my way through a beginner's JavaScript course on Treehouse and keep getting stuck on functions. In effort to understand better, I tried creating a calculator which converts human years to dog years. Here is my code so far:
HTML:
<div id="calculator">
<form>
<label>What is your current age in human years? <br>
<input type="text" id="humanYears"></label> <br>
<button type="text" id="calculate">Calculate</button>
</form>
</div>
JS:
function calculate() {
var humanYears = document.getElementById("humanYears").value;
var dogYears = (humanYears * 7);
document.write(dogYears);
}
document.getElementById("calculate").onclick = function(){calculate(); };
The page flickers and I keep seeing the form, no result.
I know this code is incorrect but I don't understand why. I also know I can just copy other people's code from Github and have a functioning calculator but that kind of defeats the purpose of learning. I would rather know why my code doesn't work and what I can do to fix it. (I double, triple checked that the HTML and JS files were properly linked, which they are.)
Any JS wizards out there care to chime in?
Edit: When I enter an age into the form, it merely reloads, rather than displaying the age in dog years (which is the desired outcome).

Your code works, although as you've indicated it's not great.
function calculate() {
var humanYears = document.getElementById("humanYears").value;
var dogYears = (humanYears * 7);
document.write(dogYears);
}
document.getElementById("calculate").onclick = function(){calculate(); };
<div id="calculator">
<form>
<label>What is your current age in human years? <br>
<input type="text" id="humanYears"></label> <br>
<button type="text" id="calculate">Calculate</button>
</form>
</div>
Some notes for improvement:
Avoid document.write
Forms should have submit buttons (either <input type="submit" value="Calculate"> or <button type="submit">Calculate</button>
The parentheses around your arithmetic are superfluous: var dogYear = humanYears * 7; is sufficient
Not everything needs an id attribute, although that makes DOM queries easy and quick
You should handle the form's submit event as opposed to the button's click event as you'll want to handle if, say, I submit the form by pressing Enter on my keyboard
You don't need the extra function around calculate, document.getElementById('calculate').onclick = calculate; would suffice
With those notes in mind, here's how I'd improve your calculator:
var form = document.getElementById('calculator');
function calculate() {
var years = form['humanYears'].value,
dogYears = years * 7;
document.getElementById('answer').innerText = dogYears;
}
form.addEventListener('submit', calculate, false);
<form id="calculator">
<p>
<label>
What is your current age in human years?<br>
<input type="text" name="humanYears">
</label>
</p>
<p>
<button type="submit">Calculate</button>
</p>
<p>
Answer: <span id="answer"></span>
</p>
</form>
Things I've changed:
I'm using <p> tags to control whitespace instead of <br> which will further let me customize presentation with CSS if I choose to. You cannot style <br> elements.
I'm modifying a portion of the DOM, not the entire DOM
I've bound my event handler with addEventListener which is way less obtrusive
I'm accessing form elements through the natural structure the DOM provides instead of running a full DOM query for each element
I've reduced some code

Here your working code with as little changes as possible:
<div id="calculator">
<form>
<label>What is your current age in human years? <br>
<input type="text" id="humanYears"></label> <br>
<button type="text" id="calculate">Calculate</button>
</form>
</div>
<script>
function calculate() {
var humanYears = document.getElementById("humanYears").value;
var dogYears = (humanYears * 7);
document.write(dogYears);
}
document.getElementById("calculate").onclick = function(){calculate(); return false; };
</script>
Assuming you put everything in one file the script tags are missing. If not then you still need a script tag to load the JS file.
Your function needed a "return false;". If you omit that, the page will reload after writing your output and won't see the output. That happens because the default behaviour of a button in a form is to reload the page. By returning "false" you suppress that.

The main problem is that document.write doesn't do what you imagine it does:
Note: as document.write writes to the document stream, calling document.write on a closed (loaded) document automatically calls document.open, which will clear the document.
See the documentation for document.write: https://developer.mozilla.org/en-US/docs/Web/API/Document/write
A better way to this is to have an empty element on the page, which you then change the contents of:
function calculate() {
var humanYears = document.getElementById("humanYears").value;
var dogYears = humanYears * 7;
document.getElementById('output').innerText = dogYears;
}
document.getElementById("calculate").onclick = calculate;
<div id="calculator">
<form>
<label>What is your current age in human years? <br>
<input type="text" id="humanYears">
</label>
<br>
<button type="button" id="calculate">Calculate</button>
<div id="output"></div>
</form>
</div>
I've also made some small improvements to your script:
Changed the indentation of your HTML to be more readable
Changed your button to have type="button" - otherwise your form will submit and the page will reload when you click the button. In this case, you actually don't even need a form element, but it's not hurting anything. Alternatively, you could add return false to your calculate function - this would tell the browser not to submit the form and thus not reload the page
Changed how you're adding the onclick handler - there's no need to wrap the calculate function in another function. In javascript, functions can actually be passed around like a variable. This is why I set the value of onclick to just be calculate - notice however that I left out the (). You want the onclick to be a reference to the function, otherwise the calculate function would be executed immediately, and the onclick would be set to the return value of the function - in this case, that would be undefined.

Related

InnerHTML problems with Tip Calculator function

I'm trying to write a simple Tip Calculator for a computer science class I'm in. It's in HTML/JavaScript. The actual Tip Calculating function is written in JavaScript. I've been told to use innerHTML to display the output of the function in HTML. So from my understanding, innerHTML works by writing any value/variable (in this case the output of my function) to an HTML container with whatever id is defined.
At first I thought maybe it was just my code being in the wrong order. But I've tried moving the function definition around and that wasn't any help. I've verified that the input ID is correct when pulling the variables from HTML. I've done a lot of reading on similar problems and I can't seem to find what I'm doing wrong.
So heres where I define my function, and use innerHTML to write the output. The function is defined before the actual user input.
function calculateTip(){
var checkAmount = document.getElementById("amountBox").value;
var percentTip = document.getElementById("tipBox").value;
var tipTotal = checkAmount * (percentTip / 100);
document.getElementById("tipVar").innerHTML = tipTotal;
}
<body>
<P>
Enter the check amount:
$<input type="numeric" id="amountBox" size=10 value="">
<br>
Tip percentage:
%<input type="numeric" id="tipBox" size=4 value="">
</P>
<input type="button" value="Calculate Tip"
onclick="calculateTip();" >
<hr>
<div id="tipVar"></div>
</body>
So, I'm expecting when you enter the check amount and tip percentage and click the "Calculate Tip" button, it will run the function and innerHTML will write the output of the function to the page in the div container. However when I click the button seemingly nothing happens. If anyone has any help/guidance I'd greatly appreciate it.
You have a typo in the code:
use document.getElementById("tipVar").innerHTML = tipTotal;
Your code was not working because tipVar was undefined, It's an ID and should be used as a string.
I have updated the question snippet and it should work now.
You need to put "tipVar" in quotations inside your function.
Otherwise the value of an undefined variable called tipVar is passed in instead, and it finds no element by that id.
You just forgot the quotes on getElementById("tipBox");
<html>
<body>
<p> Enter the check amount:
<input type="numeric" id="amountBox" size=10 value="">
<br>
Tip percentage:
<input type="numeric" id="tipBox" size=4 value="">
</P>
<input type="button" value="Calculate Tip" onclick="calculateTip();">
<hr>
<div id="tipVar"></div>
<script>
function calculateTip(){
var checkAmount = document.getElementById("amountBox").value;
var percentTip = document.getElementById("tipBox").value;
var tipTotal = checkAmount * (percentTip / 100);
document.getElementById("tipVar").innerHTML = tipTotal;
}
</script>
</body>
</html>

How to set up a specific reject message for a HTML number input element?

I have a loop of html forms <input type="number">, which are basically simple algebra calculations for certain people to fill in. I set the correct answer by limiting both the max and min accepted number to the same number. However, in this way, if the participant gives a wrong answer, the reject message would be something like this: "values must be greater than or equal to ...". It is technically correct but I would like it to only say "incorrect answer, please try again".
Is there any way to do this?
Tried to use something like alert =, but it doesn't meet my requirements.
There's ${parameters.numbers} and ${parameters.answers} in the code because I am using lab.js for the looping. They just mean every time the number in the equation and the answer would change. For example, for the first loop ${parameters.numbers} is 200, and the corresponding answer ${parameters.answers} is 194. lab.js would take care of converting these two parameters to actual numbers for each loop of the form.
<form>
<label for="algebra">${parameters.numbers} - 6 = ?</label><br>
<input name="algebra" type="number" id="algebra" required="" max="${parameters.answers}" min="${parameters.answers}"><br>
<button type="submit">OK</button>
</form>
I try to avoid a dramatic alert dialogue for this, just a non-intrusive message like the default style would be good. If you want to recreate the default "values must be greater than or equal to ..." message, just replace the parameters like this would be good:
<form>
<label for="algebra">200 - 6 = ?</label><br>
<input name="algebra" type="number" id="algebra" required="" max="194" min="194"><br>
<button type="submit">OK</button>
</form>
I agree with #ElroyJetson that putting the answer inside the tag is not a good idea, but I focused this answer on the way you can set and unset the error message.
I used jQuery, but this can also be done with plain javascript.
The idea is to group the input tag with a span tag (here inside the div with class input-field).
When the value changes or when the form is submitted (in this case when the value changes), you remove any previous error message from the span tag, and then perform the validation. If there is an error you set it in the span tag.
In this way the error message will show below the input element.
To try it fill in an answer and click outside of the input box.
$(document).ready(function(){
$(".input-field").change(function(){
let $inputField = $(this);
let $input = $inputField.find("input");
let $errorMsg = $inputField.find("span.err-msg");
let max = Number($input.data("max"));
let min = Number($input.data("min"));
$errorMsg.text("");
let v = Number($input.val());
if(v < min || v > max){
$errorMsg.text("Invalid answer");
}
});
});
.err-msg{
color:red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<div class="input-field">
<label for="algebra">200 - 6 = ?</label><br>
<input name="algebra" type="number" id="algebra" required="" data-max="194" data-min="194"><br>
<span class="err-msg"></span>
</div>
</form>
Don't set the correct answer with min & max. Instead, just call a javascript function by giving your button tag an onClick to evaluate if the user's answer is correct.
<button onclick="evaluateAnswer('.algebra');" class="submitBtn" >OK</button>
Then your javascript should look something like this:
function evaluateAnswer(cssClass){
var usersAnswer = $(cssClass).val();
var actualCorrectAnswer = 100;
if(usersAnswer == actualCorrectAnswer){
//Do something to proceed
}else{
alert('Sorry, your answer is incorrect');
}
}
Also, I just noticed that you did not want to alert as-in a javascript alert. What you could do is style your message and give it a css class that has the property display:none. Then when you want to show the message when user enters the wrong answer, you can use javascript to remove the class, and also use javascript to add the class back when user enters correct answer.
Edit
You should maybe store your correct answers in a database, evaluate it's correctness serverside, and use Ajax to display the message to prevent users from being able to right-click -> view source and look at the answers in your client-side code
My current solution is like this. There is invisible html elements which stores the correct answer, and the js script validates if the input is correct. Again, the ${} parts represents variables that change in each loop.
html part
<main class="content-horizontal-center content-vertical-center">
<form name="mathEvaluation">
<label for="algebra">${parameters.numbers} - 6 = ?</label><br>
<input name="answer" type="number" id="answer" required="" size="3"><br>
<button type="submit">OK</button>
<input type="hidden" id="hidenAnswer" value=${parameters.answers} />
</form>
</main>
js part
this.options.validator = function(data) {
if(mathEvaluation.answer.value == mathEvaluation.hidenAnswer.value){
return true
} else {
alert("Please enter the correct number.")
}
}

How do I make a form's values change a page's CSS in real-time (without having to refresh the page)?

I am attempting to change the CSS on the page as a user types values into a form using javascript. For example - if they type a color value into said field it turns said button to that color. Or changes size if they provide input in the size field. I have not been able to find any examples relating to this. If you could point me to any resources regarding this that would be awesome!
**This is my first post, please let me know if I am doing anything incorrectly.
this input receives code of colors. ff0 - for example
var btn = document.getElementById('btn');
function changeColor(input) {
btn.style.background="#"+input.value;
}
<form>
<input id="inp" type="text" onInput="changeColor(this);">
<button id="btn">Click</button>
</form>
Funny enough this is something I decided to do a few weeks ago, you just create a blank style in the head section of your html page, add an id and use jquery to set the content of the style upon keyup of what ever you decide to use to set the values, e.g.
<pre contenteditable></pre>
<script>
$(document).ready(function(){
$('pre').keyup(function(){
$('#yourstyletagid').html($(this).html());
});
});
</script>
Something like this?
var button = document.getElementById("button");
var b = button.offsetWidth;
function a(input) {
button.style.width = b + input.value + "px";
}
<form>
<input type="number" onchange="a(this);" min="5">
<button id="button">Hello World</button>
</form>

Scan QR Code value into an input field

This is the scanner I am using...
On Web : https://atandrastoth.co.uk/main/pages/plugins/webcodecamjs/
On Git : https://github.com/andrastoth/WebCodeCamJS
It's working 100%. But I need to add some custom extra's.
When the QR Code is scanned it outputs my result into this paragraph tag.
<p id="scanned-QR"> The scanned code text value is printed out here </p>
However I need it to be an input field so I can use it's value in a url.
How can I set an input field equal to the value submitted to the Paragraph tag?
I have tried these methods and they failed :
Method 1
<input id="scanned-QR"> The scanned code text value is printed out here </input>
Method 2
<p id="scanned-QR" onchange="update"></p>
<input id="code_id_value" type="text" name="" value="">
<br>
<script>
function update(){
var code_id_value = document.getElementById("scanned-QR").innertext;
document.getElementById("code_id_value").value = code_id_value;
}
</script>
The key that you're missing is that the T in .innertext needs to be capitalised (as .innerText).
In addition to this, using inline event handlers is bad practice, and you should consider using .addEventListener() instead of onchange.
This can be seen working in the following:
document.getElementById("scanned-QR").addEventListener("click", update);
function update() {
var code_id_value = document.getElementById("scanned-QR").innerText;
document.getElementById("code_id_value").value = code_id_value;
}
// Demo
update();
<p id="scanned-QR">Text</p>
<input id="code_id_value" type="text" name="" value="">
Hope this helps! :)
So this is the solution I came up with.
Here's my paragraph and input function
<p id="scanned-QR" onchange="update">SCAN.BZ</p>
<input id="code_id_value" type="text" name="" value="">
Here's my function. WITH a interval for every millisecond or faster "I think it's every millisecond".
It runs smoothly and doesn't lag. and the result is practically immediate.
<script type="text/javascript">
setInterval(update,1);
function update() {
var code_id_value = document.getElementById("scanned-QR").innerHTML;
document.getElementById("code_id_value").value = code_id_value;
}
update();
</script>
Thanks for the help "Obsidian Age" Really appreciate it. :)

Converting text to lowercase/uppercase with a pending a radio button

I am writing a Javascript program that takes a users input text, then (pending a radio button check – lowerCase/UpperCase) converts the input text to either lowercase/upperCase and outputs the value back to the form.
Purely trying to learn on my own Javascript. I am moderately new (but savvy) to JS. Pretty solid on HTML, CSS, Java, but BRAND new with interacting with page elements.
I have dug around for two days to try and solve this. I have even checked out a few books at my local library. (Currently reading the text, Microsoft guide to CSS/HTML, and JS). What other books would you recommend in order to under JS more?
Here is the code below. Although I know one can use CSS in order to convert this and I have done this. I'm purely just wanting to figure out Javascript.
<!DOCTYPE html>
<html>
<head>
<title> Case Changer By: Elliot Granet</title>
<style>
function convert(){
var convertedText = document.test.input.value;
if(document.getElementById("lowerCase").checked = true){
var output = convertedText.toLowerCase();
}else {
output = convertedText.toUpperCase();
}
document.getElementById('outputText').value = output;
}
convert();
</head>
The rest -
<body>
<h3>Choose your Conversion method below:</h3>
<form action="getElementById">
<fieldset>
<input id="lowerCase" type="radio" name="case" value="lowerCase">Lower Case<br>
<input id ="upperCase" type="radio" name="case" value="upperCase">Upper Case<br><br>
</fieldset>
<fieldset>
<textarea id="inputText" name="input" form="inputText">Enter text here to be Converted...</textarea>
</fieldset><br>
<fieldset>
<textarea id ="outputText" name="output" form="outputText">Converted text will appear here...</textarea>
</fieldset>
<input type="button" value="Convert">
</form>
</body>
</html>
You need to make few changes to make this function work.
style is an invalid tag to put js code. You need to put it inside <script> tag
If you are writing this function inside header yo may come across error since before DOM is ready it will try to get value of textarea with id inputText.
document.getElementById(idName').value but not is right syntax to get the value of element using id
Attaching convert() with the button. So when you will click on button the function will execute.
5.document.getElementById("lowerCase").checked = true this is wrong.It mean that checkbox will get checked as = will assign the value . Instead you need to compare the value. So use == or ===
if you declare var output inside if loop it wont be available inside else. So you need to declare it outside the if-else loop
Hope this snippet will be useful
HTML
<input type="button" value="Convert" onclick="convert()">
JS
window.load =convert; // convert function will be called after window is ready
function convert(){
var output; //variable declaration outside if-else loop
var convertedText = document.getElementById('inputText').value; //document.getElementById
if(document.getElementById("lowerCase").checked == true){ // == comparision
output = convertedText.toLowerCase();
}
else {
output = convertedText.toUpperCase();
}
document.getElementById('outputText').value = output;
}
EXAMPLE

Categories

Resources