I am creating my first web app and have run in to an issue pretty early on!
I have created a function which extracts the information that the user keys into the HTML input field. The way it should work is that when the user enters their income and clicks the submit button, the income is stored in a variable for me to use throughout the rest of my JavaScript code.
Looking at the console log, the function is coming up as 'not defined'.
I appreciate the code is probably not very clean but I just want to get it working as it's my first small project!
Any ideas where I am going wrong?
Here's the HTML:
<div class="row input-1">
<label for="Gross Annual Salary">£</label>
<input type="number" name="Gross Annual Salary" id="Ann-Sal" placeholder="Gross Annual Salary" required>
<input type="button" class="submit-btn" value="Submit" onclick="getInc();">
</div>
Here's the JavaScript:
function getInc() {
var inc = document.getElementById("Ann-Sal");
}
I remove semiclon from onclick end and it works
<div class="row input-1">
<label for="Gross Annual Salary">£</label>
<input type="number" name="Gross Annual Salary" id="Ann-Sal" placeholder="Gross Annual Salary" required>
<input type="button" class="submit-btn" value="Submit" onclick="getInc()">
</div>
<script>
function getInc() {
console.log('works');
var inc = document.getElementById("Ann-Sal");
}
</script>
<script>
function getInc() {
console.log('works');
var inc = document.getElementById("Ann-Sal");
}
</script>
<div class="row input-1">
<label for="Gross Annual Salary">£</label>
<input type="number" name="Gross Annual Salary" id="Ann-Sal" placeholder="Gross Annual Salary" required>
<input type="button" class="submit-btn" value="Submit" onclick="getInc()">
</div>
First of all make sure you have your <script> after the body (ie: put it after the last closing <div>), secondly if you want to what the user typed in you should get the elements value. When you set inc equal to document.getElementById("Ann-Sal"); you are giving it the DOM element instead of the it's value instead you should put:
function getInc() {
var inc = document.getElementById("Ann-Sal");
}
Then you will get the value the user inputted to the code.
Also, a tip use addEventListener() instead of the onclick attribute, it's better practice.
Ok, so I tried to fix it myself using some of Tom O's code above here:
var buttonEl = document.querySelector('input[type="button"]');
var inputEl = document.getElementById("Ann-Sal");
var annInc;
function clickHandler() {
annInc = parseFloat(inputEl.value);
console.log(annInc);
}
buttonEl.addEventListener('click', clickHandler);
HTML:
<div class="row input-1">
<label for="Gross Annual Salary">£</label>
<input type="number" name="Gross Annual Salary" id="Ann-Sal" placeholder="Gross Annual Salary" required>
<input type="button" class="submit-btn" value="Submit">
</div>
This didn't work. There was no error message but nothing was logged to the console when submitting an income into the input field.
I then reconfigured the Javascript code to this:
var buttonEl = document.querySelector('input[type="button"]');
var inputEl = document.getElementById("Ann-Sal");
var annInc;
function clickHandler() {
if (!inputEl.value.length) {
console.error('A salary is required!');
return;
}
annInc = parseFloat(inputEl.value);
console.log(annInc);
}
buttonEl.addEventListener('click', clickHandler);
This then worked. I didn't use the if statement to validate the users input previously because I used 'required' in the input element within my HTML code which basically does the same thing right? So i'm guessing the reason why the code wasn't working because the 'return' statement wasn't used?
Would someone be kind enough to explain to me why the return statement enabled this to work?
I'm sure for some of you experienced guys, my lack of understanding must be painful for you! I am super determined to get my head around this though.
Many thanks
Besides the other answers, I just wanna point it out that is missing the .value in your function, otherwise, you won't get the value.
function getInc() {
var inc = document.getElementById("Ann-Sal").value
}
Related
I am trying to get an event handler on an HTML form. I am just trying t get the simplest thing working, but I just cannot see what I am missing.
It is part of a wider project, but since I cannot get this bit working I have reduced it down the most very basic elements 1 text field and a button to try and see what it is I am missing.
All I want to do is get some text entered and flash up message in a different area on the screen.
The user enters text into the input field (id=owner).
The plan is that when the button (id="entry") is pressed the event handler (function "entry") in the entry.js file should cause a message to display.
I don't want the form to take me to a different place it needs to stay where it is
I just want some form of text to go in the: <div id="feedback" section.
When I can get it working: I intend the create the text from the various text fields that get entered.
I Know that this is beginner stuff & I know that I have reduced this down such that it barely worth thought but I would welcome any input please & thank you.
HTML code is:
<form method="post" action="">
<label for="owner">Input Owner: </label>
<input type="text" id="owner" />
<div id="feedback"></div>
<input type="submit" value="enter" id="entry" />
</form>
<script src="entry.js"></script>
Code for entry.js is:
function entry() {
var elOwner = document.getElementById('owner');
var elMsg = document.getElementByID('feedback');
elMsg.textContent = 'hello';
}
var elEntry = document.getElementById('entry');
elEntry.onsubmit=entry;
I have tried:
Adding in a prevent default:
window.event.preventDefault();
doing this through an event Listener:
elEntry.addEventListener('submit',entry,false);
using innerHTML to post the message:
elMsg.innerHTML = "
At present all that happens is that the pushing submit reloads the page - with no indication of any text being posted anywhere.
One issue is that you have a typo, where getElementById capitalized the D at the end.
Another is that preventDefault() should be called on the form element, not the input.
Here's a working example that corrects those two mistakes.
function entry(event) {
var elOwner = document.getElementById('owner');
var elMsg = document.getElementById('feedback');
elMsg.textContent = 'hello';
event.preventDefault();
}
var entryForm = document.getElementById('entry').form;
entryForm.onsubmit = entry;
<form method="post" action="">
<label for="owner">Input Owner: </label>
<input type="text" id="owner" />
<div id="feedback"></div>
<input type="submit" value="enter" id="entry" />
</form>
I also defined a event parameter for the handler. I don't remember is window.event was ever standardized (it probably was), but I'd prefer the parameter.
Be sure to keep your developer console open so that you can get information on errors that may result from typos.
var elEntry = document.getElementById('entry');
elEntry.addEventListener("click", function(e) {
e.preventDefault();
var elMsg = document.getElementById('feedback');
elMsg.textContent = 'hello';
});
<form method="post" action="">
<label for="owner">Input Owner: </label>
<input type="text" id="owner" />
<div id="feedback"></div>
<input type="submit" value="enter" id="entry" />
</form>
Can someone explain IntegerField() to me? I have searched everywhere and haven't found a good example for what I am looking for. I have a counter on my website; the up-arrow adds 1, the down-arrow subtracts 1. However, when I click either arrow, it just returns NaN, and it wont update. Any ideas?
wtform:
class BetaForm(FlaskForm):
streak = IntegerField('Streak')
total = IntegerField('Total')
submit = SubmitField('Update')
Route
def beta():
form = BetaForm()
if form.validate_on_submit():
current_user.streak = form.streak.data
current_user.total = form.total.data
db.session.commit()
flash('Your account has been updated!', 'success')
return render_template('betaone.html', form=form)
HTML:
<div class="row">
<p class="col-12 font100" id="streakcounter">{{ form.streak }}</p>
<button id="betabuttonplus" onclick="addStreak()"><i class="fa fa-plus"></i></button>
</div>
<form method="POST" action="">
<div class="form-group">
{{ form.submit(class="my-button btn btn-outline-info") }}
</div>
</form>
JS
function addStreak() {
var streak = document.getElementById("streakcounter").innerHTML;
streak++;
document.getElementById("streakcounter").innerHTML = streak;
}
The problem here is in javascript:
document.getElementById("streakcounter").innerHTML
retrieves the entire input element, but we only want to update its value attribute. This function will update the value correctly:
function addStreak() {
document.getElementById("streak").value++;
}
It's possible to avoid having to use javascript to update the form by using an html5 type="number" input; modern browsers will automatically provide up and down arrows ("spinners") to update the value. WTForms provides these inputs in its html5 modules.
from wtforms import Form
from wtforms.fields import html5 as h5fields
from wtforms.widgets import html5 as h5widgets
class MyForm(Form):
foo = h5fields.IntegerField('foo')
bar = h5fields.IntegerField('bar', widget=h5widgets.NumberInput(min=1, max=1000, step=5))
form = MyForm()
for f in form:print(f)
<input id="foo" name="foo" step="1" type="number" value="">
<input id="bar" max="1000" min="1" name="bar" step="5" type="number" value="">
I need help with this. I need to make the value in the other place change all the time while user session is active. How can I get the value from a span and make other value in a data change?
Look at there!
1 <div class="pt-uea-container">
2 <span class="pt-uea-currency pt-uea-currency-before"> € </span>
3 <input type="text" class="pt-field pt-uea-custom-amount" autocomplete="off" name="pt_items[1][amount]" id="pt_uea_custom_amount_1" value="199" placeholder="" data-parsley-errors-container="#pt_uea_custom_amount_errors_1">
4 <input type="hidden" class="pt-field pt-uea-custom-amount-formatted" name="pt_items[1][amount]" value="199" data-pt-price="199">
5 <input type="hidden" name="pt_items[1][label]" value="Amount:">
6 <input type="hidden" name="pt_items[1][tax_percentage]" value="0">
7 <input type="hidden" name="pt_items[1][type]" value="open">
8 <div id="pt_uea_custom_amount_errors_1"></div>
9 <span class="form-price-value">85</span>
10 </div>
The value in row 9 needs to constantly change values in row 3 and 4 on the same session. Don't mind the value in row 6.
Let me know how I can get this done. Or maybe a different approach?
Greetings!
========
So this is what I got for now from you guys:
jQuery(document).ready(function($) {
var checkViewport = setInterval(function() {
var spanVal = $('.form-price-value').text();
$('#pt_uea_custom_amount_1').val(spanVal);
$('#pt_uea_custom_amount_formatted_1').val(spanVal);
$('#pt_uea_custom_amount_formatted_1').attr('data-pt-price', spanVal);
}, 1000);
});
This code works, but it only affects my needs when I put my mouse in pt-field pt-uea-custom-amount and add a space in it. Then it does apply to the page source. But this is not correct. The source needs to get changed too without touching that class or a space or something!
You can easily do this with the help of jQuery.
With the help of jQuery I would do like this.
Understanding what input field needs to be tracked for changes. I will give all this field a class (track-me).
In the document ready, I will look for changes for that tracked field.
On change of that field I will get the value and put in other input fields (class copy-to - or you can do whatever you like).
See an example below,
HTML
<form>
<div class="">
<input type="text" class="track-me" value=""/>
</div>
<div class="">
<input type="text" class="copy-to" value=""/>
</div>
<div class="">
<input type="text" class="copy-to" value=""/>
</div>
<div class="">
<input type="text" class="copy-to" value=""/>
</div>
<div class="">
<div class="">Please type anything in the first input box</div>
</div>
</form>
jQuery
$(document).ready(function(){
$('.track-me').change(function (){
$('.copy-to').val($(this).val())
});
});
I made comments in the above jQuery code so you can understand. Also, I have made a fiddle so you can play and have a look. In this fiddle, I am using Bootstrap4 just for the purpose of styling, you don't have to worry about that.
Link to fiddle
https://jsfiddle.net/anjanasilva/r21u4fmh/21/
I hope this helps. Feel free to ask me any questions if you have. Cheers.
This is not an ideal solution. I'm not sure there is a verified way of listening for when the innerHTML of a span element changes. This sort of stuff is usually based on user interaction, and the value of the span will be modified by your page. The best solution would be to use the same method that updates the span element to update the values of you hidden input fields.
However, I've placed an interval that will run every second, that takes the text value of the span element and gives it to the values of the 2 input fields:
function start() {
setInterval(function() {
document.getElementById("pt_uea_custom_amount_1").value = document.getElementById("price_value").innerHTML;
document.getElementById("pt_uea_custom_amount_2").value = document.getElementById("price_value").innerHTML;
}, 1000);
}
window.onload = start();
<div class="pt-uea-container">
<span class="pt-uea-currency pt-uea-currency-before"> € </span>
<input type="text" class="pt-field pt-uea-custom-amount" autocomplete="off" name="pt_items[1][amount]" id="pt_uea_custom_amount_1" value="199" placeholder="" data-parsley-errors-container="#pt_uea_custom_amount_errors_1">
<input type="hidden" class="pt-field pt-uea-custom-amount-formatted" name="pt_items[1][amount]" value="199" data-pt-price="199" id="pt_uea_custom_amount_2">
<input type="hidden" name="pt_items[1][label]" value="Amount:">
<input type="hidden" name="pt_items[1][tax_percentage]" value="0">
<input type="hidden" name="pt_items[1][type]" value="open">
<div id="pt_uea_custom_amount_errors_1"></div>
<span id="price_value" class="form-price-value">85</span>
</div>
MutationObserver should work here..
const formValuePrice = document.querySelector( '.form-price-value' );
const inputText = document.querySelector( 'input[type="text"]' );
// timer to change values
window.setInterval( () => {
formValuePrice.textContent = Math.round( Math.random() * 100 );
}, 1000 );
// mutation observer
const observer = new MutationObserver( ( mutationsList ) => {
inputText.value = formValuePrice.textContent;
} );
observer.observe( formValuePrice, { childList: true } );
https://codepen.io/anon/pen/LgWXrz?editors=1111
try this, simple using jquery, you can check in inspect element for value attribute data-pt-price
Update: you can using jquery event .on() like change, click, keyup or else to Attach an event handler function for one or more events to the selected elements,
you can read the doc here.
here the updated code
$(function() {
var spanVal = $('#price_value').text();
$('#pt_uea_custom_amount_1').val(spanVal);
$('#pt_uea_custom_amount_formatted_1').val(spanVal);
$('#pt_uea_custom_amount_formatted_1').attr('data-pt-price', spanVal);
$('#pt_uea_custom_amount_1').on('change click keyup', function() {
$('#pt_uea_custom_amount_formatted_1').val($(this).val());
$('#price_value').text($(this).val());
$('#pt_uea_custom_amount_formatted_1').attr('data-pt-price', $(this).val());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="pt-uea-container">
<span class="pt-uea-currency pt-uea-currency-before"> € </span>
<input type="text" class="pt-field pt-uea-custom-amount" autocomplete="off" name="pt_items[1][amount]" id="pt_uea_custom_amount_1" value="199" placeholder="" data-parsley-errors-container="#pt_uea_custom_amount_errors_1">
<input type="hidden" class="pt-field pt-uea-custom-amount-formatted" name="pt_items[1][amount]" value="199" data-pt-price="199" id="pt_uea_custom_amount_2">
<input type="hidden" name="pt_items[1][label]" value="Amount:">
<input type="hidden" name="pt_items[1][tax_percentage]" value="0">
<input type="hidden" name="pt_items[1][type]" value="open">
<div id="pt_uea_custom_amount_errors_1"></div>
<span id="price_value" class="form-price-value">85</span>
</div>
I've created a basic profit calculator which is pretty much working fine. My issue is that every time I enter a number into each of the relevant fields, you can see the workings out in the "Total profit" field. It first tells me my entry is NaN, then -infinity, and then shows the workings. Once I click on my calculate button, I am then finally displayed with the correct number.
For this post I am not concerned with why it is producing the NaN (not a number), but why am I seeing it populated in the field in the first place. I want this field to remain blank until I click Calculate, and then see the resulting number. I suspect it's to do with my JavaScript code but I am a complete newbie - and very stuck.
Your thoughts are most appreciative.
<form id="profitCalculator" action="" class="dark-matter">
<h1>Profit Calculator</h1>
<fieldset>
<p><label>Case Cost:<br />£
<input name="casecost" type="text" value="" size="14" maxlength="8" /></label></p>
<p><label>Units per case:<br /> <input name="packs" type="text" value="1" size="14" maxlength="8" /></label></p>
<p><label>Sell price:<br /> £ <input name="sell_price" type="text" value="" size="14" maxlength="8" /></label></p>
<p><input type="button" class="button" OnClick="Circle_calc(this.form);" value="Calculate"></p>
<p>Total Profit:<br /> £ <input name="profit" type="text" value="0" autocomplete="off" SIZE=14></p>
<p><input type="reset" class="button" value="Reset"></p>
</fieldset>
</form>
And the JavaScript
<script type="text/javascript">
document.getElementById('profitCalculator').onclick = function () {
var casecost = this.elements['casecost'].value || 0;
var packs = this.elements['packs'].value || 0;
var sell_price = this.elements['sell_price'].value || 0;
var profit = (sell_price - casecost) / packs;
this.elements['profit'].value = profit.toFixed(2);
}
</script>
Thank you
You've set a click handler on the form element. Since click events bubble, clicks on the elements inside the form bubble to the form as well. So that's triggering an update to your profit element on anything that any element considers a click.
This diagram from the DOM3 events spec (which has since been folded into the DOM4 spec's events section) may help clarify how bubbling works:
You have a Onclick event on your button that calls Circle_calc function.
Change your function passing the form element as a parameter, and it will work.
Circle_calc = function (form) {
var casecost = form.elements['casecost'].value || 0;
var packs = form.elements['packs'].value || 0;
var sell_price = form.elements['sell_price'].value || 0;
var profit = (sell_price - casecost) / packs;
form.elements['profit'].value = profit.toFixed(2);
}
JsFiddle here
var name = document.getElementById('contact-name'),
email = document.getElementById('contact-email'),
phone = document.getElementById('contact-phone'),
message = document.getElementById('contact-message');
function checkForm() {
if (name.value == '') {
alert('test');
}
}
I was simply trying to make sure everything was working before I began learning actual client-side validation.
Here is the HTML
<form role='form' name='contactForm' action='#' method="POST" id='contact-form'>
<div class="form-group">
<label for="contact-name">First and Last Name</label>
<input type="text" class="form-control" id="contact-name" name="contactName" placeholder="Enter your name.." pattern="[A-Za-z]+\s[A-Za-z]+">
</div>
<div class="form-group">
<label for="contact-email">Email address</label>
<input type="email" class="form-control" id="contactEmail" name="contactEmail" placeholder="Enter Email" required>
</div>
<div class="form-group">
<label for="contact-phone">Phone Number</label>
<input type="number" class="form-control" id="contactPhone" name="contactPhone" placeholder="Enter Phone Number" required'>
</div>
<div class="form-group">
<label for='contactMessage'>Your Message</label>
<textarea class="form-control" rows="5" placeholder="Enter a brief message" name='contactMessage' id='contact-message' required></textarea>
</div>
<input type="submit" class="btn btn-default" value='Submit' onclick='checkForm()'>
</fieldset>
</form>
I took the required attribute off, and if I leave the name field empty it goes right to the other one when i click submit. To check whether javascript was working at all, i did an basic onclick function that worked.
Maybe someone can explain to me what is wrong with the checkForm function. Thanks in advance.
P.S The form-group and form-control classes belong to bootstrap
Change your javascript to this:
var contactName = document.getElementById('contact-name'),
email = document.getElementById('contact-email'),
phone = document.getElementById('contact-phone'),
message = document.getElementById('contact-message');
function checkForm() {
if (contactName.value === '') {
alert('test');
}
}
Okay, Hobbes, thank you for editing your question, now I can understand your problem.
Your code faces three two issues.
Your control flow. If you want to validate your field, you have to obtain its value upon validation. You instead populate variable name when the page loads, but the user will enter the text only after that. Hence you need to add var someVariableName = document.getElementById(...); to the beginning of the checkForm() function.
global variables. Please do not use them like that, it is a good design to avoid global variables as much as possible, otherwise you bring upon yourself the danger of introducing side effects (or suffering their impact, which happens in your situation). The global context window already contains a variable name and you cannot override that. See window.name in your console. You can of course use var name = ... inside the function or a block.
Even if you fix the above, you will still submit the form. You can prevent the form submission if you end your checkForm() function with return false;
For clarity I append the partial javascript that should work for you:
function checkForm() {
var name = document.getElementById('contact-name');
if (name.value == '') {
alert('test');
return false;
}
}
EDIT: As Eman Z pointed out, the part 1 of the problem does not really prevent the code from working as there's being retrieved an address of an object (thanks, Eman Z!),