Building a donut chart to show web browser usage

We find the data feed, and it is composed of nested objects. We'll need to manipulate the remote data quite a bit to get it in the format we need. We achieve this by executing the following steps:

  1. We start by including the donutRenderer plugin file. With donut charts, we can use seriesColors for each ring, so we create arrSeriesColors to store the colors of our outer rings. Then, we create innerRingColors to hold the matching colors for our inner ring wedges:
    <script src="../js/jqplot.donutRenderer.min.js"></script>
    <script src="../js/functions.js"></script>
    <script>
    var arrSeriesColors = "#4bb2c5", "#F4CA4A", "#EAA228", "#E4CAAB", "#00CC55", "#AED8D0", "#F2C185"];
    var innerRingColors = [];
  2. Next, we create our function to parse our remote data. Since we have multiple levels in our JSON, we decide to store the browsers and versions objects in variables to make our code a little easier to read. We pass the browser data to our parseBrowsers function and do the same for our version data with parseVersions. Once all the data is processed, we put it in data and return it to jqPlot:
    function dataPull(remoteData,options) {
      var data = [];
      var b = remoteData.browsers, v = remoteData.versions;
    
      var browser = parseBrowsers(b);
      var version = parseVersions(v,browser);
      data = [browser, version];
      return data;
    }
  3. The parseBrowsers function does the same thing as our other functions that looped through the first level of our JSON object. We grab each name, and we add this and the number of visits to our data array. When we're done, we sort the array, and then pass back the browser data to dataPull:
    function parseBrowsers(b) {
      var browsers = [], i = 0;
      for (var name in b) {
        if (b.hasOwnProperty(name)) {
          browsers[i] = [name, b[name]];
          i++;
        }
      }
      browsers.sort(descendingSort);
      return browsers;
    }
  4. Our parseVersions function is a bit more detailed. First, we pass in both the versions data and the new browser array. We start by looping through our browser array. We then use the name to find the corresponding object in our versions object:
    function parseVersions(v,browser) {
      var versions = [], i = 0;
      for(i=0;i<browser.length;i++){
        var name = browser[i][0];
  5. We create a temporary array to hold all the data points for each browser. Then, we loop through each element in the chosen browser and add them to the innerRing array. We also add the browser name as the third element in our data point array. With this done, we'll be able to add the browser to our tooltip later:
        var innerRing = [];
        if (v.hasOwnProperty(name)) {
          for (var ver in v[name]) {
            innerRing.push([ver, v[name][ver], name]);
  6. Once we add the data, we find the corresponding color in arrSeriesColors and add it to innerRingColors. This way, the version wedge color will match the color of the browser it belongs to:
            innerRingColors.push(arrSeriesColors[i]);
          }
        }
  7. Once we have looped through all the versions for the current browser, we sort innerRing. Then, we loop through innerRing and add the elements to our versions array. This way, all the version wedges will be next to the browser wedge in the outer ring, and they will be arranged in descending order:
        innerRing.sort(descendingSort);
        for(var j=0;j<innerRing.length;j++){
          versions.push(innerRing[j]);
        }
      }
      return versions;
    }
  8. After we complete the data parsing, we move on to setting up our graph. We set renderer to DonutRenderer. For this chart, we add in a couple of other renderer options. We set innerDiameter to 50 so that our inner ring will be wider to accommodate our labels. We also assign our arrSeriesColors array to seriesColors:
    $(document).ready(function(){
      var browser_plot = $.jqplot ('browser_plot', './data/browser_stats.json',
      {
        title: 'Web Browser Usage',
        seriesDefaults: {
          renderer:$.jqplot.DonutRenderer,
          rendererOptions: { 
            showDataLabels: true, 
            sliceMargin: 4, 
            startAngle: -90, 
            innerDiameter: 50,
            dataLabelThreshold: 0
          }
        },
        seriesColors: arrSeriesColors,
  9. The seriesColors option is available within each series, so for our inner ring we assign it innerRingColors so our wedges will match the outer ring. Since our inner ring will not appear on the legend, we will override the series defaults and set dataLabels to label. Also, we move the inner ring labels closer to the outer edge by setting dataLabelPositionFactor to .75. This option takes a percentage as a decimal, whereas dataLabelNudge uses actual pixel values. So, with dataLabelPositionFactor, the position of our labels will scale if we change the size of our chart:
        series: [
          { },
          { 
            seriesColors: innerRingColors,
            rendererOptions: { 
              dataLabels: 'label', 
              dataLabelPositionFactor: .75 
            } 
          }
        ],
  10. We use the same options as our other charts for the data renderer and legend options:
        dataRenderer: remoteDataCallback,
        dataRendererOptions: { dataCallback: dataPull },
        legend: { 
          show: true, 
          placement: 'outside', 
          location: 's',
          rendererOptions: { numberRows: 1 }
        },
      });
  11. Next, we make use of the jqplotDataHighlight event. We want to display the percentage of usage as well as the browser and version names in our tooltip for our inner ring:
      $('#browser_plot').on('jqplotDataHighlight',
        function (ev, seriesIndex, pointIndex, data) {
          var total = 0;
  12. We need to calculate the percentage for the wedge that is highlighted. This means we need to loop through the series data array for the highlighted series to get our total:
          for(var i=0;i<browser_plot.series[seriesIndex].data.length;i++) {
            total += browser_plot.series[seriesIndex].data[i][1];
          }
  13. Next, we calculate the percentage, and then we add the value to our tooltip. Since our outer ring does not have the third element in its data array, we add an if statement to only display the browser and percentage:
          var percent = data[1] / total;
          percent = percent * 100;
          if(seriesIndex == 0) {
            $('#tooltip').html(data[0]+' - '+percent.toFixed(2)+'%'),
          } else {
            $('#tooltip').html(data[2]+': '+data[0]+' - '+percent.toFixed(2)+'%'),
          }
        }
      );
  14. We clear the tooltip with the jqplotDataUnhighlight event:
      $('#browser_plot').on('jqplotDataUnhighlight',
        function (ev, seriesIndex, pointIndex, data) {
          $('#tooltip').html(''),
        }
      );
    });
    </script>
  15. We finish the chart by increasing the width and height so that all the wedges are large enough to hold the labels:
    <div id="browser_plot" style="width:800px;height:600px;margin-left:30px;"></div>
    <div id="tooltip"></div>
    <style>
      .jqplot-table-legend.jqplot-table-legend-label { white-space: nowrap; padding:3px;}
      .jqplot-table-legend { padding: 3px; font-size: 1.25em;}
      .jqplot-donut-series.jqplot-data-label { color: #fff; text-shadow: 2px 2px 2px #000;}
      #tooltip { float:left;position: absolute; top:50px;left:100px;}
    </style>

Once we complete our coding, we load the chart in our browser. We can see the results in the following screenshot. The chart matches what we originally conceived. Jeff should be happy!

Building a donut chart to show web browser usage

We notice that one of the slices is so small that it isn't rendered even with dataLabelThreshold set to 0. Counting all the percentages of the inner ring, we determine that the percentage for Internet Explorer 7.0 is less than 1 percent. For our purposes, missing 1 percent will not make a huge difference.

Calvin stops by a few minutes later and we show him what we have. "Good work, let me call around and try and set up a quick meeting." Calvin steps out of the room, and 20 minutes later, we are sitting in the same conference room as this morning.

We walk them through the charts we created. When we show them the product category chart, Jeff says, "wow, that is a lot of data." After some discussion, everyone agrees that the product category chart is overwhelming. We decide we'll revisit the chart later.

They really like the divisional revenue chart. Someone mentions that the Nerd Corral chart works well, but the others are a bit jumbled. Finally, we show off Jeff's chart. Jeff likes it, especially since it shows that traffic for Internet Explorer 7 and 8 is not very high. We suggest it might work just as well as a bar chart.

Roshan speaks up, "I really like what you two have done. After seeing the charts, we have to agree with you on some of your concerns. I think the next step will be to take the charts you created and make them more interactive. When I move my mouse over a data point, can the data appear near my cursor instead of somewhere else on the page?"

We tell Roshan we should be able to do that. We head back to our office and gather our things to head home. We'll start on making the charts more interactive tomorrow.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.148.105