Reputation: 61
I wanted to make something that changed when I pressed enter in a input number variable for the value of the progress bar, and another input variable for the max of the progress bar, kinda like this:
But, these values won't always be the same, so, that's why I wanted to know how to sync the input vars with the progress bar.
I'm really new to coding and I don't know JavaScript yet. I am still going to check it out, but I don't wanna learn everything about it just for one thing.
The code for the HTML I made is this:
<div id="lifepog">
<input type="number" class="currentlife" max="20" min="0" value="0">
<div id="lifeslash" contenteditable="false">
<p>/</p>
</div>
<input type="number" class="totallife" max="20" min="0" value="0">
</div>
<div id="lifebar">
<progress value="10" max="20" class="barlife"></progress>
</div>
Upvotes: 5
Views: 1828
Reputation: 8378
You could listen for the input
event and update the progress bar's attributes based off the value of each number input:
// Select the progress bar by its class
const progress = document.querySelector('.barlife');
// Set the progress bar's value based off the top input
const numerator = (e) => {
progress.value = e.target.value;
}
// Set the progress bars max value based off the bottom input
const denominator = (e) => {
progress.max = e.target.value;
}
<div id="lifepog">
<input oninput="numerator(event)" type="number" class="currentlife" max="20" min="0" value="10">
<div id="lifeslash" contenteditable="false">
<p>/</p>
</div>
<input oninput="denominator(event)" type="number" class="totallife" max="20" min="0" value="20">
</div>
<div id="lifebar">
<progress value="10" max="20" class="barlife"></progress>
</div>
For multiple progress bars you could pass an index to each function:
// Select the progress bar by its class
const progressBars = document.querySelectorAll('.barlife');
// Set the progress bar's value based off the top input
const numerator = (e, index) => {
progressBars[index].value = e.target.value;
}
// Set the progress bars max value based off the bottom input
const denominator = (e, index) => {
progressBars[index].max = e.target.value;
}
<div id="lifepog">
<input oninput="numerator(event, 0)" type="number" class="currentlife" max="20" min="0" value="10">
<div id="lifeslash" contenteditable="false">
<p>/</p>
</div>
<input oninput="denominator(event, 0)" type="number" class="totallife" max="20" min="0" value="20">
</div>
<div id="lifebar">
<progress value="10" max="20" class="barlife"></progress>
</div>
<div id="lifepog">
<input oninput="numerator(event, 1)" type="number" class="currentlife" max="20" min="0" value="10">
<div id="lifeslash" contenteditable="false">
<p>/</p>
</div>
<input oninput="denominator(event, 1)" type="number" class="totallife" max="20" min="0" value="20">
</div>
<div id="lifebar">
<progress value="10" max="20" class="barlife"></progress>
</div>
<div id="lifepog">
<input oninput="numerator(event, 2)" type="number" class="currentlife" max="20" min="0" value="10">
<div id="lifeslash" contenteditable="false">
<p>/</p>
</div>
<input oninput="denominator(event, 2)" type="number" class="totallife" max="20" min="0" value="20">
</div>
<div id="lifebar">
<progress value="10" max="20" class="barlife"></progress>
</div>
Now, for animation, you'll have to change things up a bit. You can't animate the progress element as it's a native element of the browser.
What you'll need is a div to mimic the behaviour of a progress bar:
const progress = document.getElementById('lifebar-inner');
const numeratorInput = document.querySelector('.currentlife');
const denominatorInput = document.querySelector('.totallife');
/* Set the max-width by calculating what percentage
the top input is of the bottom input */
const setProgress = () => {
progress.style.maxWidth = `
${(numeratorInput.value / denominatorInput.value) * 100}%
`;
}
#lifebar {
margin: 10px;
height: 10px;
width: 200px;
border: 1px solid grey;
border-radius: 10px;
overflow: hidden;
}
#lifebar-inner {
background-color: lightblue;
height: 100%;
width: 100%;
max-width: 50%;
/* Transition the max-width property,
as it's smoother than transitioning the width property */
transition: max-width 0.35s cubic-bezier(0.9, 0.4, 0.6, 0.7);
}
<div id="lifepog">
<input oninput="setProgress()" type="number" class="currentlife" max="20" min="0" value="10">
<div id="lifeslash" contenteditable="false">
<p>/</p>
</div>
<input oninput="setProgress()" type="number" class="totallife" max="20" min="0" value="20">
</div>
<div id="lifebar">
<div id="lifebar-inner" />
</div>
Upvotes: 3