views:

86

answers:

3

Hi,

I am still learning jQuery and have come up against something I just can't get my head around? (I'm not great at math!). I know that there is probably a graph type plug-in out there I could use but I don't know if I need something so bulky/code-heavy. Any help would be greatly appreciated. This website is the best learning source on the web!

I'm trying to figure out of how I could look through a list of comments that have a 'rating' of excellent/good/okay/poor contained in a DIV within the li comment. Then work out the percentage of the excellent/good/okay/poor comments based on however many comments there are eg: If there are 4 comments in total, and there are 3 goods and 1 poor, then it would be 75% good and 25% poor.

Then to display those percentages using the width property for each of the corresponding 'percentage-bar' DIV's.

Sorry if this is not clear, I thought it would be so simple, but I'm stumped. Please see the markup below to get an understanding of what I am trying to do.

Any help would be awesome! :)

COMMENT // These would be the li comments with the excellent/good/okay/poor ratings within them. These would be wrapped in a UL with id 'comments'

<li>
   <p>blah blah blah...</p>
   <div class="user-image"></div>
   <div class="okay">It's okay</div>
</li>
<li>
   <p>blah blah blah...</p>
   <div class="user-image"></div>
   <div class="excellent">It's okay</div>
</li>
<li>
   <p>blah blah blah...</p>
   <div class="user-image"></div>
   <div class="okay">It's okay</div>
</li>
<li>
   <p>blah blah blah...</p>
   <div class="user-image"></div>
   <div class="poor">It's okay</div>
</li>
<li>
   <p>blah blah blah...</p>
   <div class="user-image"></div>
   <div class="poor">It's okay</div>
</li>
<li>
   <p>blah blah blah...</p>
   <div class="user-image"></div>
   <div class="good">It's okay</div>
</li>
<li>
   <p>blah blah blah...</p>
   <div class="user-image"></div>
   <div class="good">It's okay</div>
</li>
<li>
   <p>blah blah blah...</p>
   <div class="user-image"></div>
   <div class="good">It's okay</div>
</li>
<li>
   <p>blah blah blah...</p>
   <div class="user-image"></div>
   <div class="good">It's okay</div>
</li>
<li>
   <p>blah blah blah...</p>
   <div class="user-image"></div>
   <div class="okay">It's okay</div>
</li>

COMMENT // These would be the results, each percentage bar is contained by a DIV that corresponds to a rating excellent/good/okay/poor. These would be wrapped in a UL with id 'results'.

<li>
    <div class="excellent">
        <div class="percentage-bar"></div>
    </div>
</li>
<li>
   <div class="good">
        <div class="percentage-bar"></div>
    </div>
</li>
<li>
    <div class="okay">
        <div class="percentage-bar"></div>
    </div>
</li>
<li>
    <div class="poor">
        <div class="percentage-bar"></div>
    </div>
</li>
A: 

jQuery isn't well suited to image processing. Also, there is a fair bit of math involved when you try to scale the graph based on the data so it displays correctly. Instead of making the charts yourself, try the Google Chart API: http://code.google.com/apis/chart/.

You don't have to worry about crunching the numbers or creating the graphics; just supply the API with your data. You are not going to get a result in HTML format with divs, but instead as an image. This is better because it is much more portable and also the API has a ton of configuration options and different types of graphs that it supports.

SimpleCoder
+1  A: 

I highly recommend using the jQuery plugin HighCharts. It is very easy to use and works extremely well in older browsers (IE 6).

http://highcharts.com/

jhanifen
+4  A: 

Here's a start: alt text

I tried to keep it as simple as possible, so the bars aren't that pretty.

jsFiddle example

    // Add a sum function to the Array
Array.prototype.sum = function(){
    var sum = 0;
    for(var i = 0; i < this.length; sum += this[i++]);
    return sum;
}

$(function() {
      // set the "size" of the chart
    var size = 400;

      // store the rating names
    var ratings = ["excellent", "good", "okay", "poor"];

      // zeroed out array for number of votes for each
    var votes   = [0, 0, 0, 0];

      // through the `LI`s and I add each vote to the appropriate 
      //   index of the votes array
    $("ul li").each(function(){
        ++votes[ $.inArray($("div:last", this).attr("class"), ratings) ];
    });

      // Get the total votes cast
    var total = votes.sum();

    $("#chart").attr("height", size);

      // Go though each of the votes array elements
      //   and create a bar for each type of vote cast
    $(votes).each(function(index, value) {
          // Calculate length of this one bar.
          // could use something like $("#chart").height() instead of size
        var howTall = (value / total) * size;
        var bar = $("<div>");        
        bar.attr("class", "bar");
        bar.height(howTall);
        bar.width(20); 
        bar.attr("bottom", size);
        var result = $("<div>");
          // Add label of type vote displayed
        result.append(ratings[index]);
        result.attr("class", "result");
          // Add the bar
        result.append(bar);
          // Add the percent shown
        result.append((100*value/total) + "%");
        $("#chart").append(result);        
    })
});

Of course this can be greatly polished. The bottom of the bars could all be at the same level with the tops varying. Animations could be added as each bar is being added. Gradients could be thrown in... etc etc,

But the heart of the code is to count up all the votes, store them in an array, and then use the array to calculate the percents and heights of the DIVs.

Peter Ajtai
WOW!, Mate this is exactly what I was talking about, you sir are a gentleman :). Thank you so much, I will update everybody on how the implementation went, after I've picked apart the code and got my head around it. Thanks!
@user446550 - You're welcome ;)
Peter Ajtai