Reputation: 512
I am trying to create a list of progress bars.
The values will be between 15 and 30.
The idea is that 15 is 50% and 30 is 100%. What I'm having trouble with is using jquery to set the width of each element/progress bar to the correct width percentage according to the value provided in the data attribute.
If the value is 15 then the bar width should be 50%. If the vaule is 30 then the bar width should be 100%.
I cannot work out what the calculation would be to make this happen?
I don't have any jQuery to show as i've not had any success so it would just be non-sense i'm afraid.
My HTML is as follows though:
.Progress {
width: 100%;
background-color: #ddd;
height: 30px;
margin-bottom: 10px;
}
.Bar {
width: 45%;
height: 30px;
background-color: #4CAF50;
padding-left: 10px;
padding-right: 10px;
line-height: 30px;
color: white;
display: block;
}
.name {
float: left;
}
.pct {
float: right;
}
<div class="Progress">
<div class="Bar" data-value="15">
<div class="name">NAME</div>
<div class="pct">15%</div>
</div>
</div>
<div class="Progress">
<div class="Bar" data-value="20">
<div class="name">NAME</div>
<div class="pct">20%</div>
</div>
</div>
<div class="Progress">
<div class="Bar" data-value="25">
<div class="name">NAME</div>
<div class="pct">25%</div>
</div>
</div>
<div class="Progress">
<div class="Bar" data-value="30">
<div class="name">NAME</div>
<div class="pct">30%</div>
</div>
</div>
I realised I needed to acheive a slightly different outcome in the end.
My goal was to have a min and max value. If the value was <= the min value the width of the progress bar would be set to 50% and if the value was >= the max value it would be set to 100% and then automatically calculated in between these values.
Using the below 2 functions I was able to acheive this
function range(start, end, step = 1) {
const len = Math.floor((end - start) / step) + 1
return Array(len).fill().map((_, idx) => start + (idx * step))
}
function trust15width(value) {
var lowEnd = 15; // This is the minimum value to be calculated
var highEnd = 18; // this is the maximum value to be calculated
if(value > highEnd) {
// if the value is bigger than the maximum value, force the percentage to be 100
var newWidth = 100;
} else if(value < lowEnd) {
// if the value is smaller than the minimum value, force the percentage to be 50
var newWidth = 50;
} else {
var result = range(lowEnd, highEnd, 0.1); // Change these variables for the start and end of the range.
var increments = result.length;
var percentageIncrease = 50 / result.length;
var position = result.indexOf(value)+1; // change this number according to the market share
var newWidth = 50 + (position * percentageIncrease);
}
return newWidth;
}
console.log(trust15width(14.7));
Upvotes: 0
Views: 6820
Reputation: 3819
Here's a full proof solution with corresponding mathematics -
data-value < 1
, shows 0%
data-value > Max
, shows 100%
function findPercentagePer30(x, max) {
return ((x / max) * 100).toFixed(2).replace(/[.,]00$/, "");
}
$(function() {
$('.Bar').each(function() {
var dataVal = $(this).attr("data-value");
var percentage = findPercentagePer30(dataVal, 30); // max = 30 here
if(percentage > 0) {
percentage = percentage <= 100 ? percentage : 100;
$(this).css("width", percentage + '%');
$(this).find(".pct:first").text(percentage + '%');
} else {
$(this).css("background-color", 'transparent');
$(this).find(".pct:first").text('0%');
}
});
});
.Progress {
width: 100%;
background-color: #ddd;
height: 30px;
margin-bottom: 10px;
}
.Bar {
width: 45%;
height: 30px;
background-color: #4CAF50;
padding-left: 10px;
padding-right: 10px;
line-height: 30px;
color: white;
display: block;
box-sizing: border-box; /* <-- added this */
}
.name {
float: left;
}
.pct {
float: right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="Progress">
<div class="Bar" data-value="15"><div class="name">NAME</div><div class="pct">15%</div></div>
</div>
<div class="Progress">
<div class="Bar" data-value="20"><div class="name">NAME</div><div class="pct">20%</div></div>
</div>
<div class="Progress">
<div class="Bar" data-value="25"><div class="name">NAME</div><div class="pct">25%</div></div>
</div>
<div class="Progress">
<div class="Bar" data-value="30"><div class="name">NAME</div><div class="pct">30%</div></div>
</div>
<div class="Progress">
<div class="Bar" data-value="0"><div class="name">WORST CASE (data-value < 1)</div><div class="pct">0%</div></div>
</div>
<div class="Progress">
<div class="Bar" data-value="35"><div class="name">WORST CASE (data-value > Max)</div><div class="pct">35%</div></div>
</div>
box-sizing: border-box;
to your .Bar
, so that all bars will look uniform.Upvotes: 1
Reputation: 324
this is the jQuery code you need :D
edit: oh no seems like i was to slow :(
edit2: alright, now dynamic and right numbers
$( document ).ready(function() {
var max = 0;
$('.Bar').each(function(i, obj) {
if ($(this).data("value") > max){
max = $(this).data("value");
}
});
$('.Bar').each(function(i, obj) {
$(this).css("width", (100/max)*$(this).data("value")+"%");
$(this).find(".pct").html(Math.round((100/max)*$(this).data("value"))+"%");
});
});
.Progress {
width: 100%;
background-color: #ddd;
height:30px;
margin-bottom:10px;
}
.Bar {
width: 45%;
height: 30px;
background-color: #4CAF50;
padding-left:10px;
padding-right:10px;
line-height: 30px;
color: white;
display:block;
}
.name {
float:left;
}
.pct {
float:right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="Progress">
<div class="Bar" data-value="15"><div class="name">NAME</div><div class="pct">15%</div></div>
</div>
<div class="Progress">
<div class="Bar" data-value="20"><div class="name">NAME</div><div class="pct">20%</div></div>
</div>
<div class="Progress">
<div class="Bar" data-value="25"><div class="name">NAME</div><div class="pct">25%</div></div>
</div>
<div class="Progress">
<div class="Bar" data-value="30"><div class="name">NAME</div><div class="pct">30%</div></div>
</div>
Upvotes: 1
Reputation: 1319
Using JQuery .each()
on your Bar and setting the CSS width attribute by getting the data-value
and doing some simple Math percentages would do the trick
$( ".Bar" ).each(function() {
let percent = $(this).attr('data-value');
percent = percent * 100 / 30;
//For too high values :
if(percent > 100){
percent = 100;
}
//$(this).css('width', percent+'%' );
//With animation as asked :
$(this).animate({width: percent+'%' }, 2000);
});
.Progress {
width: 100%;
background-color: #ddd;
height:30px;
margin-bottom:10px;
}
.Bar {
width: 45%;
height: 30px;
background-color: #4CAF50;
padding-left:10px;
padding-right:10px;
line-height: 30px;
color: white;
display:block;
}
.name {
float:left;
}
.pct {
float:right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="Progress">
<div class="Bar" data-value="15"><div class="name">NAME</div><div class="pct">15%</div></div>
</div>
<div class="Progress">
<div class="Bar" data-value="20"><div class="name">NAME</div><div class="pct">20%</div></div>
</div>
<div class="Progress">
<div class="Bar" data-value="25"><div class="name">NAME</div><div class="pct">25%</div></div>
</div>
<div class="Progress">
<div class="Bar" data-value="30"><div class="name">NAME</div><div class="pct">30%</div></div>
</div>
Upvotes: 2
Reputation: 36594
You need to divide 30
by the value of .Bar
and then multiply it with 100
also. Set box-sizing:border-box
/*$('.Progress').each(function(){
let value = $(this).find('.Bar').css('width', '30')
console.log(value);
let parentWidth = getComputedStyle(this).width;
})*/
let total = 30;
$('.Bar').each(function(){
let value = (parseInt($(this).data().value)/total) * 100;
$(this).css('width',value + '%')
})
.Progress {
width: 100%;
background-color: #ddd;
height:30px;
margin-bottom:10px;
}
.Bar {
box-sizing:border-box;
height: 30px;
background-color: #4CAF50;
padding-left:10px;
padding-right:10px;
line-height: 30px;
color: white;
display:block;
}
.name {
float:left;
}
.pct {
float:right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="Progress">
<div class="Bar" data-value="15"><div class="name">NAME</div><div class="pct">15%</div></div>
</div>
<div class="Progress">
<div class="Bar" data-value="20"><div class="name">NAME</div><div class="pct">20%</div></div>
</div>
<div class="Progress">
<div class="Bar" data-value="25"><div class="name">NAME</div><div class="pct">25%</div></div>
</div>
<div class="Progress">
<div class="Bar" data-value="30"><div class="name">NAME</div><div class="pct">30%</div></div>
</div>
Upvotes: 1
Reputation: 27531
I set the widths according to data-value
let bar = document.querySelectorAll(".Bar");
let biggest_value = 0;
bar.forEach(function(par){
if(Number(par.getAttribute("data-value")) > biggest_value){
biggest_value = Number(par.getAttribute("data-value"));
}
});
let rate = 100 / biggest_value;
bar.forEach(function(par){
par.style.width = (par.getAttribute("data-value")*rate) + "%";
});
* {
box-sizing:border-box;
}
.Progress {
width: 100%;
background-color: #ddd;
height:30px;
margin-bottom:10px;
}
.Bar {
width: 45%;
height: 30px;
background-color: #4CAF50;
padding-left:10px;
padding-right:10px;
line-height: 30px;
color: white;
display:block;
}
.name {
float:left;
}
.pct {
float:right;
}
<div class="Progress">
<div class="Bar" data-value="15"><div class="name">NAME</div><div class="pct">15%</div></div>
</div>
<div class="Progress">
<div class="Bar" data-value="20"><div class="name">NAME</div><div class="pct">20%</div></div>
</div>
<div class="Progress">
<div class="Bar" data-value="25"><div class="name">NAME</div><div class="pct">25%</div></div>
</div>
<div class="Progress">
<div class="Bar" data-value="30"><div class="name">NAME</div><div class="pct">30%</div></div>
</div>
Upvotes: 1