Creating a “Thermometer” Style Fundraising Counter with Bootstrap

Christopher Dent
4 min readAug 6, 2021

Happy Thursday! It has been a pretty intense week for me in code-land and at my day job, but I’ve been having a lot of fun all the while. I received a code challenge from a company that works with nonprofits to build a counter widget with CSS, HTML and jQuery. I honestly did not know a ton about jQuery — my bootcamp actively advised against using it and we were forbidden from doing so in our projects. So aside from getting some fun CSS practice, I learned some new methods along the way too. In the end I had a nice little counter app that I have to say I was quite pleased with!

How I Did It

When I started the challenge I started Googling “make incremental thermometer” or “make fundraising thermometer” and things like that and got all sorts of overly complicated ideas from Stack Overflow and other blogs. Not only were they unnecessarily complicated, they were also not exactly what I needed for this challenge. So I thought, what could I use to make something like this from scratch? I could create divs of certain sizes and use Javascript to modify those divs. And in a nutshell that is exactly what I did, but with the help of the all-powerful Bootstrap library.

I visited getbootstrap.com and saw they already had a ‘progress bar’ component. It was not exactly what I needed, but it was close enough that I could modify it for my needs.

The challenge was in CodePen so I couldn’t physically install Bootstrap as I usually do, but CodePen did accept the bootstrap CDN so as per Bootstrap’s docs I added this code to the top of my HTML window in the pen:

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

CodePen wasn’t thrilled about this since their HTML pen is really just meant to represent the <body> of an HTML doc, not the <head>, but it let me off with a minor warning and no major errors so I went with it.

From there, I utilized the Bootstrap “card” component that I am very familiar with from my own projects; that formed the body of the widget. I added placeholders for a card image, card title, and card body, all of which would be auto-populated via JavaScript fetch requests. A also threw in a button that would be used to increment the counter and progress bar, as well as a reset button. After all of that is where my thermometer came into play.

To add the progress bar, I used the following code:

<div class="progress">
<div class="progress-bar" role="progressbar" style="width: 25%" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100">
</div></div>

Straight out of bootstrap. Out of the box, their progress bar was far too tall for my uses. So I added some custom CSS to fix that:

.progress{height: .4em !important}

I used the !important flag here to override Bootstrap’s own programming (perhaps not always best practice, but a handy tool to have when custom CSS isn’t behaving as it should).

The “width” attribute controlled how long the inner div, the actual progress bar, would be. So, that was the attribute I’d have to modify with JavaScript every time the button was clicked. To make that happen I wrote the following function:

function updateWidget(){
fetch('http://mybackendexample.com/1')
.then(r => r.json())
.then(json => {
$pb.css('width', json.amount + '%')
$tally.text(`$ ${json.amount}`)
})
.catch(function(error) {
console.log('error');
});
}

Something important to note here — I initially had put most of the code above in with another function I wrote, the fetch/patch request that actually updates the backend. This led to some very strange behavior simply because I wrote that function as synchronous code bloc — it was one click did nothing to the CSS, but it did update the backend. Two clicks would show the proper progress on the CSS. This was fixed by writing the above function — a get fetch — and using it as a callback in the function with the patch request. That way, I could be sure that the widget was being updated with the very latest data from the backend. Always important to keep async issues in mind when using fetch!

So on click, the initial patch request was fired off to the backend and did the work it needed to do. My program then ran the updateWidget() function above, which did the work of visually updating the widget — both the amount shown (variable $tally) and the progress bar (variable $pb). The progress bar was modified by using jQuery (OK, it was a mishmash of vanilla JS and jQuery — there is only so much I can teach myself in one weekend!) to increment its width by one percent per click (the amount n the backend, plus 1%) and the actual amount was incremented simply with the backend data, which will have been updated by the patch request. My end result looked something like this:

I connected it to a rudimentary Rails API backend and bam! My own fundraising thermometer widget was born.

Conclusion

I have done a bunch of these take-home challenges recently, but this one really got me thinking and allowed me to be pretty creative. I had a lot of fun with it and it’s just gotten me more interested in front-end work than ever before.

--

--

Christopher Dent

student of code. var my_homes = [‘NY’, ‘MTL’, ‘DC’, ‘EDI’, ‘FL’, ‘?’]