I have written some code to get the value of an input (number or slider, doesn't matter)and set the "step" attribute to the current value.
const invite = document.getElementById("invite")
const output = document.querySelector(".invite-out")
const steps = invite.getAttribute("step");
output.textContent = invite.value;
invite.addEventListener("input", () => {
output.textContent = invite.value;
invite.setAttribute("step", invite.value)
})
<body>
<form action="post">
<ul>
<li>
<label for="invite">
Number of invites
</label>
<input type="number" name="invite" id="invite" min="8" max="128" value="8" step="8">
<output class="invite-out" for="invite"></output>
</li>
</ul>
</form>
</body>
The DOM is updating the attribute, whenever I decrement the value it works as expected (sets 'step =[current value]' and set value to min). But when i increment one step it keeps the original step value. It's not throwing any or errors and I'm finding it hard to find results omn google.
Related
i am trying to do simple multiply and divide using javascript and dom here are the codes
javascript
"use strict";
console.groupCollapsed("exDom1");
const fnum = document.getElementById("first-number").value;
const snum = document.getElementById("second-number").value;
function multiplyBy(number1, number2) {
document.getElementById("result").innerHTML = number1 * number2;
}
function divideBy(number1, number2) {
document.getElementById("result").innerHTML = number1 / number2;
}
console.groupEnd("exDom1");
for some reason i keep getting Nan for everything i try ,thanks in advance
this is the html
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JavaScript: DOM </title>
<script defer src="ex1.js"></script>
</head>
<body>
<h1>JavaScript</h1>
<p>In this exercise you have to define two functions in JavaScript to calculate multiplication and division of two
numbers. </p>
<ul>
<li>The result has to be written below the buttons in the section which id is "result".</li>
<li>Ues document.getElementById("result").innerHTML to set the value in the result section. </li>
<li>Use document.getElementById("first-number").value to get the value of the first number. </li>
<li>Use document.getElementById("second-number").value to get the value of the second number.</li>
</ul>
<div>
<p>1st Number :
<input type="text" id="first-number">
</p>
<p> 2nd Number:
<input type="text" id="second-number">
</p>
</div>
<input type="button" onClick="multiplyBy()" value="Multiply" />
<input type="button" onClick="divideBy()" value="Divide" />
<p>The Result is :
<span id="result"></span>
</p>
</body>
</html>
thanks in advance <3
You are calling the functions 'multiplyBy' and 'divideBy' without any parameters assigned. What you want to do is get 'first-number' and 'second-numbers' values in the function and then use the values.
Something like this:
"use strict";
console.groupCollapsed("exDom1");
function multiplyBy() {
const fnum = document.getElementById("first-number").value;
const snum = document.getElementById("second-number").value;
document.getElementById("result").innerHTML = fnum * snum;
}
function divideBy() {
const fnum = document.getElementById("first-number").value;
const snum = document.getElementById("second-number").value;
document.getElementById("result").innerHTML = fnum / snum;
}
console.groupEnd("exDom1");
You get the values of the input fields when the page first loads, and at that point, they are empty (NaN: Not a Number). You must get the values at the time that the button is clicked. Also, your functions use arguments that are never passed (again, not numbers). Instead, you can forego the parameters and just use the values at button click time.
Additionally, avoid .innerHTML whenever you can as there are security and performance implications to using it. And, since you aren't processing any HTML strings, you certainly have no need for it. Instead, use .textContent.
const fnum = document.getElementById("first-number");
const snum = document.getElementById("second-number");
const result = document.getElementById("result");
function multiplyBy() {
result.textContent = fnum.value * snum.value;
}
function divideBy() {
result.textContent = fnum.value / snum.value;
}
console.groupEnd("exDom1");
<div>
<p>1st Number:<input type="text" id="first-number"></p>
<p>2nd Number:<input type="text" id="second-number"></p>
</div>
<input type="button" onClick="multiplyBy()" value="Multiply">
<input type="button" onClick="divideBy()" value="Divide">
<p>The Result is : <span id="result"></span></p>
Lastly, you should not be using inline HTML event attributes like onclick. This is a 25+ year old technique that we used in the earliest days of web scripting when we didn't have any standards and using this technique in 2021 has real implications for the execution of your code. Instead, follow modern standards and separate your JavaScript from your HTML and use .addEventListener() to wire up events.
const fnum = document.getElementById("first-number");
const snum = document.getElementById("second-number");
const result = document.getElementById("result");
// The same event handler can be used for both buttons
document.querySelector("input[value='Multiply']").addEventListener("click", doMath);
document.querySelector("input[value='Divide']").addEventListener("click", doMath);
// All DOM event handlers are automatically passed a
// reference to the event that triggered them
function doMath(event) {
// We can get a reference to the actual element that
// triggered the event with event.target. So, depending
// on which event.target was clicked, do the right math
if(event.target.value === "Multiply"){
result.textContent = fnum.value * snum.value;
} else if(event.target.value === "Divide"){
result.textContent = fnum.value / snum.value;
}
}
<div>
<p>1st Number:<input type="text" id="first-number"></p>
<p>2nd Number:<input type="text" id="second-number"></p>
</div>
<input type="button" value="Multiply">
<input type="button" value="Divide">
<p>The Result is : <span id="result"></span></p>
Here's how it's supposed to work. By default there are two sets of input fields where the percentage fields have a value of 50% each. Now whenever a new input field is added, the percentage field value should be divided between all of them, for example, if there are 3 sets then percentage fields should have 33.33% each. If there are 4 then 25% each. Now this part works perfectly fine.
Now I'm trying to add more features on top of it. I'll just explain the features in brief and the problem associated with it.
When a user clicks on percentage input field, the previous value disappears and the user types a new percentage value and it gets divided between the two input fields. But the issue with this is it adds two "%" signs at the end of the value which the user just typed in.
The second issue is, suppose the user types in a new percentage value in the first or second percentage field and then adds a new input field through Add Field button, the percentages doesn't divide between all the input values. The new input field doesn't take into consideration the new percentage value. One reason I could think of is the percInput variable doesn't get updated somehow.
The third issue is similar to the second one. If the user adds a new input field first and then types in a percentage value in that new input field, then percentage values are not divided at all. This could also be because of percInput variable not being updated. Another issue associated with this is, clicking on the new percentage input field doesn't remove the previous value, like it does on the default fields.
This is a weird one. If the user clicks on the percentage input field but doesn't adds a value and moves on to adding a new field, then the percentage values just divide between all of them.
All of these issues are somewhat related to each other and I have feeling a that they are all because of one variable, which is, percInput. I guess it doesn't get updated when new input fields are added. Previously I used calculatePercentage function to update the percInput variable, where it worked. But it doesn't work when I tried to use it in the situations above.
Here's the code I tried so far:
const form = document.querySelector("form");
const span = document.querySelector("span");
const addBtn = document.querySelector("#addField");
const html = `
<div class="url-pair">
<input type="url" placeholder="3">
<input type="text" class="perc">
<button class="delete-btn" type="button">Delete</button>
</div>
`;
// percentage variable and percentage calculation for the first time
let percInput = document.querySelectorAll('.urls-container .perc');
let percentage = (100 / percInput.length).toFixed(0).toString() + "%";
percInput.forEach((item) => {
item.setAttribute("value", percentage);
});
const removeField = (e) => {
if (!e.target.classList.contains('delete-btn')) return;
e.target.parentElement.remove();
calculatePercentage();
}
// percentage input variable update and percentage calculation
const calculatePercentage = () => {
percInput = document.querySelectorAll('.urls-container .perc');
percentage = (100 / percInput.length).toFixed(0).toString() + "%";
percInput.forEach((item) => {
item.setAttribute("value", percentage);
});
}
// remove a field
form.addEventListener('click', removeField);
// add input field
addBtn.addEventListener('click', () => {
span.insertAdjacentHTML("beforeBegin", html);
calculatePercentage();
});
const percInputChange = function() {
let val = this.value,
$allInputs = $(percInput);
if(val > 100) {
$allInputs.val((100 / $allInputs.length) + "%");
calculatePercentage();
}else {
$(percInput).not(this).val( (100 - val) / ($allInputs.length - 1) + "%");
setTimeout(() => {
this.value = this.value + "%";
}, 500);
calculatePercentage();
return;
}
};
// event listener when user types in a new percentage value
$( percInput ).on('keyup', percInputChange);
// event listener to hide previous input value
$( percInput ).focus(function() {
this.value = "";
});
// event listener to divide the percetange values when the user clicks away
$( percInput ).blur(function() {
if(this.value === ""){
percInput.forEach(item => {
item.value = ( 100 / percInput.length ).toFixed(0).toString() + "%";
return;
});
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form action="#" method="POST">
<div class="urls-container">
<div class="url-pair">
<input type="url" placeholder="1">
<input type="text" class="perc">
<button class="delete-btn" type="button">Delete</button>
</div>
<div class="url-pair">
<input type="url" placeholder="2">
<input type="text" class="perc">
<button class="delete-btn" type="button">Delete</button>
</div>
<span></span>
</div>
<div>
<div>
<button type="button" id="addField">Add Field</button>
</div>
<div>
<button type="submit">Create</button>
</div>
</div>
</form>
I know this post is a weird one with so many problems. But please bear with me as I am still learning and I won't be able to learn if I don't push myself into these complex coding problems and get stuck. I've spent the whole day yesterday trying different methods based on the knowledge I have. The post would be really big if I put all the methods I tried. So please bear with me. Please help a fellow coder in need. Thanks
PS. I used jQuery and JS together which is not the right thing to do. But I will refactor and change them once I fix the issues.
PS.
I am not quite sure what exactly you want to achieve with your script. But I had a go at making a fresh start by removing redundant bits. The following snippet will allow you to add or remove input lines and it will adjust the percentages accordingly.
Maybe you can specifiy how you want the script to react on any user input?
// add flields:
function addfields(){
let all=$('.urls-container'), r=$('div:last',all).clone(),
url=r.find('input[type=url]')[0];
url.placeholder=+url.placeholder+1;
$('.perc',r).removeAttr('data-manual');
all.append(r); calcperc();
}
// even distribution:
function calcperc(){
let fix=$('.perc[data-manual]'),sum=0;
fix.each(function(){sum+=parseFloat(this.value)});
let rest= $('.perc').not(fix);
rest.val(((100-sum)/rest.length).toFixed(2)+'%')
}
// manual distribution:
function recalc(){let inps=$('.perc'),cur=parseFloat(this.value);
if (inps.length>1){
this.value=cur.toFixed(2)+'%'; this.dataset.manual=1;
calcperc();
} else this.value="100%"
}
// delegated event management:
$('form')
.on('submit',function(e){e.preventDefault()}) // de-activate submit for testing
.on('change','.perc',recalc)
.on('click','.delete-btn',function(){$(this).parent().remove();calcperc()})
.on('click','#addField',addfields);
// initial distribution:
calcperc();
<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<form action="#" method="POST">
<div class="urls-container">
<div class="url-pair">
<input type="url" placeholder="1">
<input type="text" class="perc">
<button class="delete-btn" type="button">Delete</button>
</div>
<div class="url-pair">
<input type="url" placeholder="2">
<input type="text" class="perc">
<button class="delete-btn" type="button">Delete</button>
</div>
<span></span>
</div>
<div>
<div>
<button type="button" id="addField">Add Field</button>
</div>
<div>
<button type="submit">Create</button>
</div>
</div>
</form>
My curent version of recalc() allows you to overwrite one of the percentage values. All other values will then be adjusted, so the total is 100% again.
Please also note that in my version the recalc() gets fired on the input event and not the keyup event, otherwise the action of adding the percentage sign would seriously interfere with any input attempt by the user.
Edit
The lastet edit involves "marking" manually changed percentages with a data-manual attribute in the input field. This will protect that field from future recalculations. The remaining percentages will be distributed evenly among the non-fixed fields.
I’m looking for a way to automate a form.
Here are the details:
Extract a certain number (displayed in its html)
Do some calculations on the extracted number (percentage of that number)
Then automatically fill the remaining input fields with the result instead of typing it out.
This is a common occurrence in forms. The solution depends on what framework / libraries you're using. Assuming you're using none, here is how you might go about it:
https://jsfiddle.net/f52h1smj/1/
rough HTML:
<form>
<label for="number">Number: </label>
<input id="number" type="number" />
<br /> <br />
<label for="calculatedNumber">Calculated Number (50%): </label>
<input id="calculatedNumber" type="number" disabled="true" />
</form>
JS:
(() => {
//get the form element nodes
const $number = document.getElementById("number");
const $calculatedNumber = document.getElementById("calculatedNumber");
//add an event listen to the value you're going to use to pre calculate the other fields
$number.addEventListener("keyup", (e) => {
//it's value is available like so
const value = e.target.value;
//do some validation so that you're calculations don't throw exceptions
if (Number(value) !== 0 && !Number.isNaN(value)) {
//set the value of the other inputs to whatever you like by setting the 'value' property of the node.
$calculatedNumber.value = value / 2;
} else {
$calculatedNumber.value = null;
}
});
})();
These things become a lot simpler in frameworks like React and Angular.
I want to add two zeros to any number entered in a textbox when submitted.
For instance, if i enter 34 in a textbox and click on submit, it should be saved as 3400.
Could this be done on the fly too?
Depends on what you want to do after the submit. Especially: Do you want to interpret this as a number and simply multiply by 100 (34 * 100) or do you want to simply append something to the value? ("34" + "00")?
In the first case you would do this:
<input id="value" type="number" value="34"/>
<br>
<button onclick="submit()">Submit</button>
<script>
function submit() {
const input = document.getElementById("value");
const value = input.attributes.value;
input.value = parseInt(input.value) * 100;
}
</script>
In the second case this:
<input id="value" type="number" value="34"/>
<br>
<button onclick="submit()">Submit</button>
<script>
function submit() {
const input = document.getElementById("value");
const value = input.attributes.value;
input.value = input.value.toString() + '00';
}
</script>
A bit vague, but it sounds like you're looking for something like the following.
// Gather each element from the HTML, so you can access its input or update its display:
const input = document.getElementById('numberInput');
const button = document.getElementById('submit');
const display1 = document.getElementById('display1');
const display2 = document.getElementById('display2');
// Add a click event to the button, which gathers the text field value, ensures it's a number, and updates the display as requested:
button.addEventListener('click',() => {
const value = input.value;
// This if statement ensures that only numbers will be suffixed with be suffixed with two zeros:
if (isNaN(value)) {
alert('Please enter a valid number');
return;
}
// Update the display span's contents as requested. There are many ways of doing this. Here are a few;
// Here I'm taking the submitted value, and nesting it inside a string, alongside the two zeros. In cases of Infinity or .100, the result will still be the input suffixed with two zeros:
display1.innerHTML = `${value}00`;
// This method, on the other hand, will simply move the decimal to columns:
display2.innerHTML = value * 100;
});
<p>
Display 1: <span id="display1"></span>
</p>
<p>
Display 2: <span id="display2"></span>
</p>
<input type="text" id="numberInput">
<button id="submit">Submit</button>
You could always set an event listener that changes the number on exit of the form element, so something like this:
document.addEventListener('DOMContentLoaded', watchNums);
function watchNums() {
document.removeEventListener('DOMContentLoaded', watchNums);
Array.from(document.getElementsByClassName('number')).map(
number => {
number.addEventListener('blur', _ => {
number.value = parseInt(number.value) * 100;
})
}
)
}
<body>
<form action="/endpoint.htm" method="POST">
<input type="number" name="number-input" class="number">
<input type="number" name="other-number-input" class="number">
<button type="submit">Submit Numbers</button>
</form>
</body>
I have a function where I'm trying to add the total number of checkboxes ticked to a value that is already displayed in the textbox. The solution I have works but it doesn't update properly if I uncheck the boxes and click total again.
Is there a way I can fix this so that the textbox updates accordingly?
HTML
<td><input type="text" name="Yeses" id="NumberofRisks" class = "form-control" value ="<?php echo $row['Total-Score'];?> " style = "width:50px"></td>
Javascript
function sum()
{
sumField = document.getElementById("NumberofRisks");
var sum = sumField.value;
$("input[name^='yanswer']:checked").each(function(){
sum++;
});
sumField.value = sum;
}
You are updating the value of the input after every call to function sum().
Instead have the initial sum value.
Then every time use this value.
var initial = $("#NumberofRisks").val();
function sum()
{
$("#NumberofRisks").val(initial + $("input[name^='yanswer']:checked").length);
displayRating($("#NumberofRisks").val());
}
Keep the original value of the textbox in a variable. Add an event listener to the checkboxes that count the number of checked boxes and adds that number to the original value, then updates the textbox.
Something like this:
HTML:
<input type="checkbox" class="check" />
<input type="checkbox" class="check" />
<input type="checkbox" class="check" />
<input type="textbox" class="text" />
JS:
//Store the original value. The 5 here should be whatever was supposed to be in the textbox.
var originalValue = 5;
$('.text').val(originalValue);
$('.check').on('change', function() {
//Count the number of checked boxes and add it to the original value for display.
var checked = $('.check:checked').length;
$('.text').val(originalValue+checked);
});
Here's a fiddle.