Why is parseInt not working for me? - javascript

No matter what I try I get NAN when I try to parse an input value into a variable. I am trying to make a calculator to determine fuel economy.
<!DOCTYPE html>
<html>
<head>
<title>Fuel Calculator</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="description" content="Demo project">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
<link rel="stylesheet" href="style.css">
<style type="text/css"></style>
</head>
<body>
<div class="wrapper">
<h1>Fuel Usage</h1>
<div class="row">
<div class="col-md-12">
<form>
<div class="form-group">
<label>Miles Driven Per Year</label>
<input type="text" class="form-control" id="mpy">
</div>
<div class="form-group">
<label>MPG</label>
<input type="text" class="form-control" id="mpg">
</div>
<p>Gallons Used: <span id="used"></span</p>
<div class="form-group">
</div>
<button id="submit" type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="main.js" type="text/javascript"></script>
</body>
</html>
js file
var mpy = parseInt($('#mpy').val(), 10);
var mpg = parseInt($('#mpg').val(), 10);
var gallonsUsed = mpy/mpg;
$('#submit').click(function(){
$('#used').text(gallonsUsed);
});

Since you have the input fields declared globally, the initial value in the text value is empty. So the result of parseInt would give you a NAN value.
You need to calculate the parsed values once you invoke the click event.
$('#submit').click(function(e){
var mpy = parseInt($('#mpy').val(), 10);
var mpg = parseInt($('#mpg').val(), 10);
var gallonsUsed = mpy/mpg;
$('#used').text(gallonsUsed);
});
Working example : https://jsfiddle.net/DinoMyte/b9bhs4s3/

The way you have your code, mpy/mpg/gallonsUsed are all calculated when the page is loaded (before any user input can even take place)
Your code would make more sense like this
$('#submit').click(function(){
var mpy = parseInt($('#mpy').val(), 10);
var mpg = parseInt($('#mpg').val(), 10);
var gallonsUsed = mpy/mpg;
$('#used').text(gallonsUsed);
});
So that the calculation is done once user has entered data and hit submit

Related

Webpage eventlistener and script section not running

Trying to make a basic webpage where you can type a message for it to be displayed on the website. However, the script section of my website does not seem to work.
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<script>
document.addEventListener('DOMContentLoaded', function()
{
let submit = document.querySelector('#submit');
submit.addEventListener('click',function()
{
let questions = document.querySelectorAll('.question');
let input = document.querySelector('input');
for (let i =0; i< questions.length; i++)
{
if questions[i].innerHTML == ""
{
questions[i].innerHTML = 'a';
}
else
{
continue;
}
}
});
function myfunction()
{
alert('test');
}
});
</script>
<title>Write A Message!</title>
</head>
<body class="p-3 mb-2 bg-secondary text-white">
<h1>How to write a message</h1>
<hr>
<p>Type a Message into the textbox below to display a public letter!</p>
<div>
<input type = 'text'>
<button id = 'submit'>Type a message!</button>
</div>
<div>
<h1>Message 1!</h1>
<hr>
<p class = 'question'></p>
<h2>Message 2!</h2>
<hr>
<p class = 'question'></p>
<h3>Message 3!</h3>
<hr>
<p class = 'question'></p>
<button onclick = 'myfunction()'>test</button>
</div>
</body>
</html>
I tried adding a button that would display an alert as well but it does not run as well when clicked.
First, javscript that contains listener/reference to DOM elements is better to include in the end on body, avoid putting in head.
Second, myfunction() is not accessible bebcause you included it under DOMContentLoaded. It should be outside of the listener (global scope).
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<title>Write A Message!</title>
</head>
<body class="p-3 mb-2 bg-secondary text-white">
<h1>How to write a message</h1>
<hr>
<p>Type a Message into the textbox below to display a public letter!</p>
<div>
<input type='text'>
<button id='submit'>Type a message!</button>
</div>
<div>
<h1>Message 1!</h1>
<hr>
<p class='question'></p>
<h2>Message 2!</h2>
<hr>
<p class='question'></p>
<h3>Message 3!</h3>
<hr>
<p class='question'></p>
<button onclick='myfunction()'>test</button>
</div>
<script>
document.addEventListener('DOMContentLoaded', function(){
let submit = document.querySelector('#submit');
submit.addEventListener('click',function(){
let questions = document.querySelectorAll('.question');
let input = document.querySelector('input');
for (let i =0; i< questions.length; i++){
if (questions[i].innerHTML == ""){
questions[i].innerHTML = 'a';
} else {
continue;
}
}
});
});
function myfunction() {
alert('test');
}
</script>
</body>
</html>

If you add HTML Elements to the DOM using Javascript's innerHTML is there a way to access those elements with Javascript?

I am trying to add more HTML elements to the DOM with a button's onclick using "innerHTML" and template literals. That much is working, but when I try to get access to the elements via a "getElementBy" or "querySelector", I can't; and I don't know why not. Any help is appreciated, thank you.
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Adding and grabbing HTML Elements</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<button id="add-character">Add</button>
<div id="grid"></div>
</body>
<script src="main.js"></script>
</html>
** Javascript**
let grid=document.getElementById("grid")
console.log(grid)
const addCharacter=document.getElementById("add-character")
console.log(addCharacter)
let Hp=0;
let num=0;
addCharacter.addEventListener("click",()=>{
grid.innerHTML+=`
<div id="subgrid" class="subgrid">
<br>
<div id="status" class="status">Status</div>
<br>
<div id="iniative" class="iniative">Iniative</div>
<input id="iniativeel" id="iniativeel" type="number">
<button id="inativebtn" class="inativebtn">Submit</button>
<br>
<div id="character" class="character">Character</div>
<br>
<div id="healthpoints" class="healthpoints">Healthpoints</div>
<br>
<input id="initalHp" class="initalHp" type="number">
<br>
<Button id="initalhp" class="initalhp">Submit</button>
<br>
<input id="damage" class="damage" type="number">
<br>
<button id ="damagebtn" class="damagebtn">Submit</button>
<br>
<div id="weapons" class="weapons">Weapons</div>
</div>`
})
btn()
function btn(){
let iniativeBtn=document.querySelector("#iniativebtn").textContent
console.log(iniativeBtn)
}

list in View does not update when the Model changes

I am trying to build a MVVM using knockout.js. The idea is that the script in $(document).ready(function() {...} adds a new item model.addElement("value"); - "value" to the model every 3 seconds and that should be shown in HTML. Alhough in console output you can see that model is changing and elements are pushed to the items list, the HTML stays the same.
At the same time if I uncomment self.items.push($('#new_item').val()); line - the HTML page will be changing every time the element is added to the model.
Please, help me to understand what am I doing wrong, why cannot i pass this "value" string through the model.addElement("value"); line?
// Overall viewmodel for this screen, along with initial state
var ListsViewModel = function(item) {
var self = this;
self.item = item;
self.items = ko.observableArray(["First", "Second", "Third"]);
self.addElement = function(item) {
self.items().push(item);
//self.items.push($('#new_item').val()); //--> uncomment for adding element with a button click
}
};
var model = new ListsViewModel()
ko.applyBindings(model, document.getElementById("one"));
$(document).ready(function() {
//comment this if you want add elements only when you click on button
setInterval(function() {
model.addElement("value");
console.log(model.items());
}, 3000);
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<title>Updating list to the server (automatically)</title>
</head>
<body>
<div id="one">
<h1>Records:</h1>
<div class="list-group" data-bind="foreach: items">
</div>
<div class="form-group">
<label for="new_item">Item name:</label>
<input type="text" class="form-control" id="new_item">
</div>
<form>
<input type="button" class="btn btn-info" value="Add element" data-bind="click: addElement">
</form>
</div>
</body>
<script src="static/js/viewModel.js"></script>
<script src="static/js/main.js"></script>
</html>
UPD:
Maybe I have made it unclear, what I wanted was that every 3 seconds new values are added to the model and this change is shown on view (HTML).
I achieved it changing self.items().push(item); to self.items.push(item);, as #user3297291 suggested.
Here is the final version of the code which works exactly as I wanted:
// Overall viewmodel for this screen, along with initial state
var ListsViewModel = function() {
var self = this;
self.items = ko.observableArray(["First", "Second", "Third"]);
//self.item = ko.observable("");
self.addElement = function(item) {
self.items.push(item);
}
};
var model = new ListsViewModel()
ko.applyBindings(model, document.getElementById("one"));
$(document).ready(function() {
//comment this if you want add elements only when you click on button
setInterval(function() {
model.addElement("value");
console.log(model.items());
}, 3000);
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<title>Updating list to the server (automatically)</title>
</head>
<body>
<div id="one">
<h1>Records:</h1>
<div class="list-group" data-bind="foreach: items">
</div>
</div>
</body>
<script src="static/js/viewModel.js"></script>
<script src="static/js/main.js"></script>
</html>
Some minor error fixes that make your snippet work:
Don't push to the array inside self.items, since knockout won't be able to notice its contents changed. Push to the observableArray directly: self.items.push instead of self.items().push
Make self.item observable so you can bind its value to the text input: self.item = ko.observable("")
Use the value binding to sync self.item and <input/>.value: <input data-bind="value: item">
addElement doesn't receive an item, it receives an event and the current binding context. Instead, you can retrieve the text box' value using self.item(), push it, and clear it using self.item("")
When working with knockout, you set the rule to not touch the DOM any other ways except via knockout bindings. Whenever you use jQuery to set or retrieve values, the first question you should ask is "what knockout binding can I use instead".
The fixed version:
// Overall viewmodel for this screen, along with initial state
var ListsViewModel = function(item) {
var self = this;
self.item = ko.observable("");
self.items = ko.observableArray(["First", "Second", "Third"]);
self.addElement = function() {
self.items.push(self.item());
self.item("");
}
};
var model = new ListsViewModel()
ko.applyBindings(model, document.getElementById("one"));
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<title>Updating list to the server (automatically)</title>
</head>
<body>
<div id="one">
<h1>Records:</h1>
<div class="list-group" data-bind="foreach: items">
</div>
<div class="form-group">
<label for="new_item">Item name:</label>
<input type="text" class="form-control" id="new_item" data-bind="value: item">
</div>
<form>
<input type="button" class="btn btn-info" value="Add element" data-bind="click: addElement">
</form>
</div>
</body>
<script src="static/js/viewModel.js"></script>
<script src="static/js/main.js"></script>
</html>

Add and remove rows in a form with unique id's that returns an object as an array

I already have my own solution for this problem, but then I don't know if I'm using the best techniques/practices to solve this particular scenario, which involves removing and adding DOM elements with unique id's.
I have just used jQuery, the requirements where only a button to add any amount of rows, once another row is added be able to delete that row too, the first row is always mandatory, here is my code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"> <title>Simple form</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<style type="text/css">
label{
display: block;
}
</style>
</head>
<body>
<div class="container">
<div class="row inputRows">
<div class="col-sm-12" id="newRow-1">
<label>Some label over input</label>
<input type="text" name="txt">
</div>
</div>
<div class="row">
<div class="col-sm-12">
<button id="addRow"><span class="fa fa-plus"></span> Add </button>
<button id="viewInfo"><span class="fa fa-plus"></span> Info </button>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<p id="result">
</p>
</div>
</div>
</div>
<script src="https://npmcdn.com/tether#1.2.4/dist/js/tether.min.js"></script>
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
<script type="text/javascript">
$('.inputRows').on('click', 'button' ,function(){
$(this).parent().remove();
});
$('#addRow').click(function(){
var $newRow = $('div[id^="newRow"]:first').clone(),
newId = Number($('div[id^="newRow"]:last').attr('id').split('-')[1]) + 1;
$newRow.append('<button><span class="fa fa-trash-o"></span></button>');
$newRow.find('input').val('');
$newRow.attr('id','newRow-' + newId);
$('.inputRows').append($newRow);
});
$('#viewInfo').click(function(){
$('#result').text(JSON.stringify(objectifyForm($('div[id^="newRow"]'))));
});
function objectifyForm(formArray) {
var resultArray = {},
inputValue = '';
for (var i = 0; i < formArray.length; i++){
inputValue = $(formArray[i]).find('input').val();
if(inputValue){
resultArray[$(formArray[i]).attr('id')] = inputValue;
}
}
return resultArray;
}
</script>
</body>
</html>
So the code works, the only problem I see is that the numeration of the id's, can sometimes be 1,5,8,7,6,12 depending on which ones you delete, but then it's fine because in the end, it doesn't even matter (joke, RIP Chester, but kind of true). My main concern or question is, is there any other way of achieving this more efficiently using jQuery? Am I doing something wrong by cloning the first element multiple times? If you can share some knowledge on DOM manipulation that would be great.
Thanks in advance,
Leo.

Input text value into a multiple data list and have option to remove them?

I have an input text box where user enter model number and the model number must be displayed in multiple data lists when user click add button. The user has must also have the option to remove the selected model number in the multiple data lists. I have created the HTML code and Javascript code, but the javascript is not adding.
What is is the best approach to my problem? I'm very newbie to javascript.
Hey is my code:
<html lang=en>
<head>
<title>Add To Datalist</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="bootstrap_3.3.7/css/bootstrap.min.css" rel="stylesheet">
<link href="bootstrap_3.3.7/fonts/font-awesome.min.css" rel="stylesheet" >
</head>
<body>
<div class="container">
<div class="content">
<br/>
<div class="col-sm-6">
<legend>Compatible Devices </legend>
<input type="text" class="form-control" id="modelNo" name="modelNo" placeholder="Enter Name Here"><br/>
<button class="btn btn-info">Add </button>
<button class="btn btn-danger">Remove</button>
</div>
<div class="col-sm-6">
<div class="listfromPopulatedModelNumber" id="listfromPopulatedModelNumber">
<select id="listfromPopulatedModelNo" multiple="multiple" col=10 rows=10>
<option></option>
<option></option>
<option></option>
</select>
</div>
</div>
</div>
</div>
</body>
JavaScript Code:
<script type="text/javascript">
$(document)
.ready(
function() {
var count = 2;
$("#addModNo")
.click(
function() {
$('#listfromPopulatedModelNo')
.last()
.after(
'#modelNo');
count++;
});
$("#removeModNo").click(function() {
$('#modelNumber > option:selected').remove();
count--;
});
});
</script>
All help will be appreciated.
This should work for you. I have updated solution for you here Updated Solution
$(document).ready(function(){
$('#addModNo').click( function(){
var input = $("input[name='modelNo']").val();
console.log(input);
$('#listfromPopulatedModelNo').append("<option value='"+$(this).val()+"'>"+ input +"</option>");
});
$('#removeModNo').click(function(){
$('option:selected').each( function() {
var input = $("input[name='modelNo']").val();
$('#listfromPopulatedModelNo').append("<option value='"+$(this).val()+"'>"+ input +"</option>");
$(this).remove();
});
});
});

Categories