Code for a fundraising thermometer

I am looking for code for a fundraising thermometer.

I have looked and looked and looked.

I need it to be html and js

Can point me in the right direction.

How do you plan to populate the percentage? Will it be pulled from a db or manually updated? You could easily make a simple vertical div of x pixels in height, then its just a matter of calculating a file inside of that div based on your goal and current amount.

I was looking for the same thing. Not sure if you found your tool. This one seems very good satisfying your needs:

http://www.flashthermometer.site90.com/index.php

You can thank @quantass; for replying earlier today, made me notice this post :slight_smile:

I thought this sounded like something that would be fun to build, so I just went ahead and built something. I’ll run you through the process :slight_smile:

Ok, first up, since we’re talking something that’s HTML based, we need a little bit of markup

<div id="thermometer">

    <div class="track">
        <div class="goal">
            <div class="amount"> 90000 </div>
        </div>
        <div class="progress">
            <div class="amount">47835 </div>
        </div>
    </div>

</div>

You’ll notice I’ve put some values in there for the goal amount and the progress amount. The reason they are unformatted is so it’s easier to parse them with JavaScript, we can format them later :slight_smile:

These values could have come from a database and inserted on the server side, of course it’s possible to update the progress bar of this “thermometer” dynamically too if you were to get new values via AJAX or something like that.

Now that we have some basic markup, we can add some CSS to make it look all pretty (well, pretty is a relative term, I am definitely no designer!).


/* Base thermometer style, this is the slate */
#thermometer {
    width:70px;
    height:300px;
    position: relative;
    background: #ddd;
    border:1px solid #aaa;
    -webkit-border-radius: 12px;
       -moz-border-radius: 12px;
        -ms-border-radius: 12px;
         -o-border-radius: 12px;
            border-radius: 12px;


    -webkit-box-shadow: 1px 1px 4px #999, 5px 0 20px #999;
       -moz-box-shadow: 1px 1px 4px #999, 5px 0 20px #999;
        -ms-box-shadow: 1px 1px 4px #999, 5px 0 20px #999;
         -o-box-shadow: 1px 1px 4px #999, 5px 0 20px #999;
            box-shadow: 1px 1px 4px #999, 5px 0 20px #999;
}


/* This represents the track of the thermometer, the linear background 
    with a background size set will generate a line every 5% of the track. */
#thermometer .track {
    height:280px;
    top:10px;
    width:20px;
    border: 1px solid #aaa;
    position: relative;
    margin:0 auto;
    background: rgb(255,255,255);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgb(0,0,0)), color-stop(1%,rgb(255,255,255)));
    background: -webkit-linear-gradient(top, rgb(0,0,0) 0%,rgb(255,255,255) 10%);
    background:      -o-linear-gradient(top, rgb(0,0,0) 0%,rgb(255,255,255) 10%);
    background:     -ms-linear-gradient(top, rgb(0,0,0) 0%,rgb(255,255,255) 10%);
    background:    -moz-linear-gradient(top, rgb(0,0,0) 0%,rgb(255,255,255) 10%);
    background:   linear-gradient(to bottom, rgb(0,0,0) 0%,rgb(255,255,255) 10%);
    background-position: 0 -1px;
    background-size: 100% 5%;
}


/* The progress indicator (the mercury, if you will) */
#thermometer .progress {
    height:0%;
    width:100%;
    background: rgb(20,100,20);
    background: rgba(20,100,20,0.6);
    position: absolute;
    bottom:0;
    left:0;
}


/* let's position the goal */
#thermometer .goal {
    position:absolute;
    top:0;
}


/* just style the amounts a little bit */
#thermometer .amount {
    display: inline-block;
    padding:0 5px 0 60px;
    border-top:1px solid black;
    font-family: Trebuchet MS;
    font-weight: bold;
    color:#333;
}


/* make sure the progress amount appears on the left side, 
    this way they progress and goal amounts won't overlap should we reach 100% (or greater) */
#thermometer .progress .amount {
    padding:0 60px 0 5px;
    position: absolute;
    border-top:1px solid #060;
    color:#060;
    right:0;
}

Now, if you were to load this up in your browser right now, we wouldn’t see anything too exciting, just the two amounts on either end of this thermometer.

We’ll need a little bit of JavaScript to spuce things up.

First up, I realised that we need to format the numbers like currency at some point, so I did a quick google search, since I figured there had to have been a lot of people that have written something to format numbers in JavaScript.

I found this little snippet (I’ve adapted it a little) on Stack Overflow


//originally from http://stackoverflow.com/questions/149055/how-can-i-format-numbers-as-money-in-javascript
function formatCurrency(n, c, d, t) {
    "use strict";

    var s, i, j;

    c = isNaN(c = Math.abs(c)) ? 2 : c;
    d = d === undefined ? "." : d;
    t = t === undefined ? "," : t;

    s = n < 0 ? "-" : "";
    i = parseInt(n = Math.abs(+n || 0).toFixed(c), 10) + "";
    j = (j = i.length) > 3 ? j % 3 : 0;

    return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\\d{3})(?=\\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
}

Ok, now that our number formatting is out of the way, we can get on with the good bits.


/**
 * Thermometer Progress meter.
 * This function will update the progress element in the "thermometer"
 * to the updated percentage.
 * If no parameters are passed in it will read them from the DOM
 *
 * @param {Number} goalAmount The Goal amount, this represents the 100% mark
 * @param {Number} progressAmount The progress amount is the current amount
 * @param {Boolean} animate Whether to animate the height or not
 *
 */
function thermometer(goalAmount, progressAmount, animate) {
    "use strict";

    //set up our vars and cache some jQuery objects    
    var $thermo = $("#thermometer"),
        $progress = $(".progress", $thermo),
        $goal = $(".goal", $thermo),
        percentageAmount;

    //work out our numbers        
    goalAmount = goalAmount || parseFloat( $goal.text() ),
    progressAmount = progressAmount || parseFloat( $progress.text() ),
    percentageAmount =  Math.min( Math.round(progressAmount / goalAmount * 1000) / 10, 100); //make sure we have 1 decimal point

    //let's format the numbers and put them back in the DOM
    $goal.find(".amount").text( "$" + formatCurrency( goalAmount ) );
    $progress.find(".amount").text( "$" + formatCurrency( progressAmount ) );

    //let's set the progress indicator

    $progress.find(".amount").hide();

    if (animate !== false) {
        $progress.animate({
            "height": percentageAmount + "%"
        }, 1200, function(){
            $(this).find(".amount").fadeIn(500);
        });
    }
    else { // we don't always want to animate
        $progress.css({
            "height": percentageAmount + "%"
        });
        $progress.find(".amount").fadeIn(500);
    }
}


$(document).ready(function(){

    //call without the parameters to have it read from the DOM
    thermometer();

    // or with parameters if you want to update it using JavaScript.
    // you can update it live, and choose whether to show the animation
    // (which you might not if the updates are relatively small)
    //thermometer( 1000000, 425610, false );

});

A fully working example on JS Fiddle: http://jsfiddle.net/GeekyJohn/vQ4Xn/

I realize the helpfulness of this post to the OP is completely negated by the lateness of the response, but who knows, maybe someone finds this helpful :slight_smile:

Wonderful work @AussieJohn ; I’ll be diving in to this later to see if I can’t learn a ting or two!

Is there a way to convert this script to £ GBP ?

Yeah, absolutely. The only thing you need to do is replace the “$” symbol in the following section:


    //let's format the numbers and put them back in the DOM
    $goal.find(".amount").text( "$" + formatCurrency( goalAmount ) );
    $progress.find(".amount").text( "$" + formatCurrency( progressAmount ) );
 

great… il try that if i ever get it working… i got the html in place… but the javascript does not seem to work

ok got it working… now can i have 2 of these graphs running on the same page but displaying diff ammounts…

You could but you’d have to change a few things around. I’m at work at the moment but I’ll take a look at it when I get home.

well im in the UK so am a bit ahead of you in time… so ill check back tomorrow and see if we got any developements… thx for the help as this is the best script i have found in a long night of searching and trying of scripts

I’ve created a new JS Fiddle for this http://jsfiddle.net/GeekyJohn/UpnKF/

Basically I’ve just changed the CSS/Markup to use classes for “thermometers” and have given the function the ability to take an ID to use as the identifier for a thermometer.

The signature has changed slightly:


function thermometer[COLOR=#ff0000](id,[/COLOR] goalAmount, progressAmount, animate) {
    "use strict";


    var $thermo = [COLOR=#ff0000]$("#"+id),[/COLOR]

The only real difference is that you now call the function with an id as the first parameter.

//call without the parameters to have it read from the DOM
thermometer("thermo1");

// or with parameters if you want to update it using JavaScript.
// you can update it live, and choose whether to show the animation
// (which you might not if the updates are relatively small)
thermometer("thermo2", 1000000, 425610, false);

Great job my friend… its turned out better than i though of…

thx very much

Awesome :slight_smile:

It’s always nice to see the end result of stuff that happens in the forums. Thanks for sharing!

Hi

Im back lol…

I have another question for a slight mod on this script…

just now the meters are in a vertical state… could it be designed so the meters are horisontal

Yeah, it was actually quite trivial to do this, mostly there were some CSS changes involved.

I’ve updated the previously mentioned fiddle: http://jsfiddle.net/GeekyJohn/UpnKF/

Here’s the approach for anyone that’s interested.

Added a class to one of the thermometers to indicate that it should be horizontal.

<div id="thermo2" class="thermometer horizontal">

Referencing the original JS code for the thermometer function, we add 2 more variables:


        isHorizontal = $thermo.hasClass("horizontal"),
        newCSS = {};

isHorizontal’s purpose is pretty obvious, the newCSS object will allow us to specify the new CSS for the progress part of the thermometer since we now need to change the property that is changed dynamically.

Right before we need the new CSS, we set its value:


    //decide if we need to affect height or width
    newCSS[ isHorizontal ? "width" : "height" ] = percentageAmount + "%";


    if (animate !== false) { 
        $progress.animate( newCSS, 1200, function(){
            $(this).find(".amount").fadeIn(500);
        });
    }
    else {
        $progress.css( newCSS );
        $progress.find(".amount").fadeIn(500);
    }

And those are all the JavaScript changes that are required. The rest is all overriding CSS rules.

The new rules are:


.thermometer.horizontal {
    margin:100px auto;
}

.thermometer.horizontal {
    width:350px;
    height:70px;
}

.thermometer.horizontal .track {
    width:90%;
    left:0;
    height:20px;
    margin:14px auto;

    /* Need to make sure our "track" has the indicators going in the right direction*/ 
    background: -webkit-gradient(linear, left top, right top, color-stop(0%,rgb(0,0,0)), color-stop(1%,rgb(255,255,255)));
    background: -webkit-linear-gradient(left, rgb(0,0,0) 0%,rgb(255,255,255) 10%);
    background:      -o-linear-gradient(left, rgb(0,0,0) 0%,rgb(255,255,255) 10%);
    background:     -ms-linear-gradient(left, rgb(0,0,0) 0%,rgb(255,255,255) 10%);
    background:    -moz-linear-gradient(left, rgb(0,0,0) 0%,rgb(255,255,255) 10%);
    background:   linear-gradient(to right, rgb(0,0,0) 0%,rgb(255,255,255) 10%);
    background-size: 5% 100%;
}

.thermometer.horizontal .progress {
    height:100%;
    width:0%;
}

.thermometer.horizontal .goal {
    left:100%;
    height:100%;
}

.thermometer.horizontal .amount {
    bottom:0;
    position: absolute;
    padding:0 5px 50px 5px;
    border-top:0;
    border-left:1px solid black;
}

.thermometer.horizontal .progress .amount {
    border-left:0;
    border-top:0;
    border-right:1px solid #060;
}

Again… thx for your work… ill give the code a testing soon… works crazy just now but soon as its done ill drop a link… thx

As mentioned in my last post… here is the meter in its final placing on my site…

Thank you again for some top class work…

This is an awasome bit of coding… thx

I just found this code and it’s just what I’ve been looking for. And it’s a very elegant-looking thermometer, so I’d like to use it on my site. Sorry for asking such a dumb question, but I really just have a basic understanding of coding. How do I set this up on my server? Does the html and javascript code go into the same file? And does the CSS code go into its own file? And, if so, what should the .css file be named? Again, sorry for asking such rudimentary questions. I wasn’t able to figure it out on my own when I tried to use the code. Thanks for any help you can provide to a true novice!

You can put all the JavaScript and CSS in the same document - helpful if you’re only going to implement this on 1 page.

A common solution is to place all CSS and JavaScript in external files so that if you want to reuse it on multiple pages it is easy to keep the code in sync and makes sure the files are cached between pages (which means less bytes to download for users)

Let’s take the latter approach :slight_smile: - Here is a sample HTML file - we’ll assume that the CSS is in thermo.css and the JavaScript is in thermo.js


<!DOCTYPE html>
<html xml:lang="en-au" lang="en-au">
<head>
  <meta charset="utf-8">
  <title>Thermometer</title>
  <link rel="stylesheet" type="text/css" href="thermo.css" />


  <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

  <script type="text/javascript" src="thermo.js"></script>
</head>
<body>
  <div id="content">

    <div id="thermo1" class="thermometer">

        <div class="track">
            <div class="goal">
                <div class="amount"> 90000 </div>
            </div>
            <div class="progress">
                <div class="amount">47835 </div>
            </div>
        </div>

    </div>

    <div id="thermo2" class="thermometer horizontal">

        <div class="track">
            <div class="goal">
                <div class="amount"> 1000000 </div>
            </div>
            <div class="progress">
                <div class="amount">354680 </div>
            </div>
        </div>

    </div>

  </div>
</body>
</html>

You might need to make some changes to the CSS to make sure the thermometer is positioned correctly on your site - but it should be fairly minimal I imagine.

Hope this helps you implement it :slight_smile: