Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to breakout the jquery UI progress bar into different sections as well as support > 100%?

I am looking at using the jquery progress bar but i have two requirements that don't seem supported:

  1. The ability to put different section into the progress bar. For example, instead of just having:

Total 100, Current 50 (so 1/2 the progress bar is filled out). which would look like this:

enter image description here

I would like to be able to show:

Total 100, Current 50 (which is broken out into 20 from Project A, 30 from Project B and 10 from Project C) where A and B sections can have some different visualization like this:

enter image description here

  1. The ability to show a number > 100%. I am using this for tracking a fund raising event so its possible that the $$ earned is greater than the goals so would want the progress indicator to keep going outside the boundaries of the progress bar.

Does jquery ui progress bar support these use cases? Is there another javascript plugin or control that is recommended for this use case?

like image 440
leora Avatar asked Nov 19 '16 02:11

leora


2 Answers

here is a basic and Css Free override for jqueryUi progressbar:

  • multimize gets progressbar id and an Array of favorite colors, this function breaks the original progress bar to a new version with multi bars according colors array length.
  • multiUpdate calling this method for update progress bar, this function gives progressbarId and an Array of bars values.

a short of what I did: just cloning the original bar to many other and using a table to show stats on each Bar. the length of code is because of included styles but you can compress it to at least 30% of this.

Edit:

added support of Numbers > 100


 // this method overrides jqueryUi progress bar
 // the length of <colors> will be number of breakes
 // this method also add a table that presents percentage in position 
function multimize(progressBarId, colors, max) {
	var pbar = $("#"+progressBarId);
	pbar.progressbar({ value: 100 });
	pbar.data('max', max);
	pbar.css("position", "relative");
	$("#"+progressBarId+" div").css({"position": "absolute", "background": colors[colors.length-1],"border":"none"}).attr("id", progressBarId+"_sub"+(colors.length-1));
	var textTable = $('<table></table>').css({"border":"none", "position":"absolute", "color":"white", "width":"100%", "height":"100%"}).attr("id", progressBarId+"_tbl");
	var textRow = textTable.append($('<tr></tr>')).css({"text-align":"center"});
	textRow.append($('<td>d</td>'));
	for (var i=colors.length-2; i>=0; i--) {
		$("#"+progressBarId+" div").clone().appendTo("#"+progressBarId)
			.css({"position": "absolute", "background": colors[i], "border-radius": "0", "width": "1%"})
			.attr("id", progressBarId+"_sub"+i);
			textRow.append($('<td>d</td>')).css({"text-align":"center"});
	}
	pbar.append(textTable);
}
 // this method will be update multimized progressbars
 // this method automatically finalize progressbar
function multiUpdate(progressBarId, values) {
	var pbar = $("#"+progressBarId);
	var i,total = 0;
	var percentes = [];
	for (i=0; i<values.length; i++) total += values[i];
	$("#"+progressBarId+"_tbl").css("width", (total*(100/pbar.data('max')))+"%")
	for (i=0; i<values.length; i++) {
		var perc = values[i]/total*100*(total/100)*(100/pbar.data('max'));
		percentes.push((i==0)?perc:perc+percentes[i-1]);
		$("#"+progressBarId+"_sub"+i).css({"width": percentes[i]+"%"});
		$("#"+progressBarId+"_tbl td:eq("+i+")").text(Math.floor(values[i])).css("width", (values[i]/total)+"%");
	}
	if (total >= pbar.data('max')) {
		finilize(progressBarId);
	}
}

function finilize(progressBarId) {
	// removing demo timer
	clearInterval(timer);
	
	var pbar = $("#"+progressBarId);
	pbar.empty();
	pbar.text("compete "+pbar.data('max')+"%").css({"color":"black", "background":"lightgreen", "text-align":"center"});
}
 
 
// Demo
// here is a demo of progress bar update and finilize
 $(function() {
	multimize("progressbar", ["#06AF8F","#000000","#F94443"], 200);
 });
var classA=0, classB=0, classC=0;
var timer = setInterval(function(){
	classA += (Math.round(Math.random() * (20 - 2) + 2))/30;
	classB += (Math.round(Math.random() * (20 - 1) + 1))/15;
	if (classC<20) classB = Math.min(classB, 15);
	classC += (Math.round(Math.random() * (20 - 7) + 7))/60;
	classC = Math.min(classC, 40);
	multiUpdate("progressbar", [classA,classB,classC]);
}, 100);
<link href = "https://code.jquery.com/ui/1.10.4/themes/ui-lightness/jquery-ui.css"
         rel = "stylesheet">
<script src = "https://code.jquery.com/jquery-1.10.2.js"></script>
<script src = "https://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>

<div id="page">
	<div id = "progressbar"></div> 
</div>
like image 184
payam_sbr Avatar answered Nov 15 '22 08:11

payam_sbr


Here is a way you can accomplish the first part of the question.

Working Example: http://jsfiddle.net/Twisty/03yuc3un/

HTML

<div id="progressbar"></div>
<div class="form">
  Add Funds:
  <input type="" id="funds" />
  <button id="addBtn">Add</button>
</div>

CSS

.form {
  padding: 20px;
}

.ui-progressbar-value {
  float: left;
  text-align: center;
  padding-top: .25em;
}

.form input {
  width: 4em;
}

#progressbar div.ui-progressbar-value.ui-widget-header:first-of-type {
  z-index: -1;
  display: none;
}

.color-1 {
  background: #FF0000;
}

.color-2 {
  background: #FFA500;
}

.color-3 {
  background: #FFFF00;
}

.color-4 {
  background: #00FF00;
}

.color-5 {
  background: #0000FF;
}

.color-6 {
  background: #FF00FF;
}

jQuery

$(function() {
  var $pgbr = $("#progressbar").progressbar({
    value: 0,
    max: 100,
    change: function(e, ui) {
      $(this).find(".ui-progressbar-value").eq(0).css("display", "none");
    }
  });
  $("#addBtn").button().click(function(e) {
    var funds = parseInt($("#funds").val());
    var cValue = $pgbr.progressbar("value");
    var sum = cValue + funds;
    if (sum > $pgbr.progressbar("option", "max")) {
      return false;
    }
    $pgbr.progressbar("value", sum);
    if (funds) {
      var $chunk = $("<div>", {
        class: "ui-progressbar-value ui-widget-header",
        width: ((funds / $pgbr.progressbar("option", "max")) * 100) + "%"
      });
      var count = $("#progressbar .ui-progressbar-value").length;
      if (count == 0) {
        $chunk.addClass("ui-corner-left");
      }
      if (count <= 6) {
        $chunk.addClass("color-" + count);
      } else {
        $chunk.addClass("color-" + count % 6);
      }
      $chunk.html(funds);
      $pgbr.append($chunk);
    }
  });
});

As you can see, there is not a way to make sections naturally with progressbar(). This example allows us to add amounts to the progress bar. If the Goal is 100 or 2000, this can be set as max during initialization. This example is assuming you are adding money collected in a day toward a goal. Example tests: $30 on day 1, $10 on day 2, $20 on day 3.

When funds are added, it adds another div with a width set to a percentage. This will help represent the value properly against the goal. If the goal is $100, the width would be 30%. If the goal is $2000, the width would be 1.5%.

Using CSS, you can assign specific colors. I picked 6 colors and rotate through them based on the number of sections already added. You could do this in a number of different methods.

Now lets say your stretch goal is $5000 and your minimum goal is $2000, this might be a max of 2000 initially. If the amount collected exceeds $2000... there's a bit of a logistical issue here. You could iterate each section and resize it to the proper percentage. Personally, I think it might be best to shrink the width of the progress bar itself, and create a 2nd progress bar that can track the surplus.

Feel free to comment with questions.

like image 44
Twisty Avatar answered Nov 15 '22 09:11

Twisty