For the divisional dashboards, we only want to show data for the current user's division. Ideally, when someone logs in to the intranet, we would know his or her division. We could then pass that information into our JavaScript. None of that infrastructure is in place currently, so we will mock up the functionality in our static HTML files.
Thinking about each chart, all three of them will be bar charts. To get started, we create a new file and save it and then perform the following steps:
<script src="../js/jqplot.categoryAxisRenderer.min.js"></script> <script src="../js/jqplot.barRenderer.min.js"></script> <script src="../js/jqplot.pointLabels.min.js"></script> <script src="../js/jqplot.canvasTextRenderer.min.js"></script> <script src="../js/jqplot.canvasAxisTickRenderer.min.js"></script> <script src="../js/jqplot.trendline.min.js"></script> <script src="../js/functions.js"></script> <script src="../js/themes.js"></script>
h1
tag so we know which division we are viewing. We perform a replace
method because browsers handle spaces in URLs in varying ways as follows:$(document).ready(function(){ var selDivision = (getQueryStringVar('division')) || "Media-Software"; $("#division_name").html(selDivision.replace("_"," "));
series
options and one to create the trendline
options. We combine all that into one function as follows://****** Individual Categories with Trends *********/ var prodTrendSeriesObj = [], prodTrendTicks = []; function createSeries(name, seriesIndex) { var series = { label: name, trendline: { show: false, label: 'Trend: ' + name } }; if(seriesIndex== $(" #trendline").val() || ($("#trendline").val() == null && index == 0)) { series.trendline.show = true; } return series; }
prodTrendDataPull
, as shown in the following code snippet:function createSelDivision(prod_cat) { var i = 0, data = []; $.each( prod_cat, function( key, value ) { data[i] = prod_cat[key]; prodTrendSeriesObj[i] = createSeries(key,i); $("#trendline").append("<option value=" + i + ">" + key + "</option>"); i++; }); return data; }
prodTrendDataPull
, we loop through each category. If it matches selDivision
, we call createSelDivision
. We finish by looping through remoteData.labels
and pushing these to the prodTrendTicks
array as follows:var prodTrendDataPull = function(remoteData,options) { var data = [], divisions = remoteData.divisions; for (var div in divisions) { if (divisions.hasOwnProperty(div)) { if(selDivision == div) { data = createSelDivision(divisions[div]); } } } $.each(remoteData.labels, function( i, value ) { prodTrendTicks.push(value); }); return data; };
refreshChart
to be called each time the value in the drop-down menu is changed. We set seriesColors
to the selected division_colors
and set the x axis ticks to prodTrendTicks
as follows:function refreshChart() { rev_category.replot( { series: prodTrendSeriesObj, seriesColors: division_colors[selDivision], grid: { backgroundColor: getBgColor(division_colors[selDivision])}, axes: { xaxis: { ticks: prodTrendTicks } } }); }
color_theme
to set the default colors to the company colors as follows:var prodTrendPlotObj = defaultBarObj(prodTrendSeriesObj, $.jqplot.CategoryAxisRenderer, prodTrendDataPull); prodTrendPlotObj.seriesDefaults.trendline = { color: '#000', lineWidth: 4 }; prodTrendPlotObj.legend = { show: true, placement: 'outsideGrid', location: 'ne' } prodTrendPlotObj = color_theme( prodTrendPlotObj, company_colors );
prodTrendPlotObj
. Since jqPlot creates the ticks before it pulls the data, we need to call refreshChart
to update the ticks and the colors. This can be implemented as follows:var rev_category = $.jqplot ('division_rev_category', './data/6_month_prod_categories.json', prodTrendPlotObj); refreshChart();
trendline
options from within our drop-down event handler. Since we did away with that function, we add an if/else statement and set trendline.show
to true
or false
for each series as follows:$("#trendline").change(function() { var trendObj = prodTrendSeriesObj; for(var x=0; x < trendObj.length; x++){ if(x == $(this).val()) { trendObj[x].trendline.show = true; } else { trendObj[x].trendline.show = false; } } refreshChart(); });
1168_10_05.html
, but with the new chart we will only show the current division. In our function to format the remote data, we loop through the labels and push each one to totalDivTicks
as follows://****** Stacked Product Revenue by Month **********/ var totalDivSeriesObj = [], totalDivTicks = []; var totalDivDataPull = function(remoteData,options) { var i = 0, data = [], divisions = remoteData.divisions; $.each(remoteData.labels, function( i, value ) { totalDivTicks.push(value); });
totalDivSeriesObj
array as follows:$.each( divisions, function( div, obj ) { if(selDivision == div) { $.each( obj, function( key, value ) { data[i] = divisions[div][key]; totalDivSeriesObj[i] = { label: key }; i++; }); } }); return data; };
var totalDivPlotObj = defaultBarObj(totalDivSeriesObj, $.jqplot.CategoryAxisRenderer, totalDivDataPull); totalDivPlotObj.stackSeries = true; totalDivPlotObj.axes.xaxis.ticks = totalDivTicks; totalDivPlotObj.legend = { show: true, placement: 'outsideGrid', location: 'ne' } totalDivPlotObj = color_theme(totalDivPlotObj, division_colors[selDivision]); var division_revenue = $.jqplot ('indiv_division_revenue', 'data/12_month_prod_categories.json', totalDivPlotObj);
returnsDataPull
to loop through the labels and the regions to generate our ticks, data, and series data arrays as follows://****** Product Returns by Region **********/ var returnsSeriesObj = [], returnsTicks = []; var returnsDataPull = function(remoteData,options) { var data = []; $.each(remoteData.labels, function(i, value ) { returnsTicks.push(value); }); $.each(remoteData.regions, function(key, value ) { data.push(value); returnsSeriesObj.push( { label: key } ); }); return data; };
defaultBarObj
function to build our options for this bar chart. We make it a stacked bar chart, set our ticks, enable the divisional colors, and then create the chart as follows:var returnsPlotObj = defaultBarObj(returnsSeriesObj, $.jqplot.CategoryAxisRenderer, returnsDataPull); returnsPlotObj.stackSeries = true; returnsPlotObj.axes.xaxis.ticks = returnsTicks; returnsPlotObj = color_theme( returnsPlotObj, company_colors); var product_returns = $.jqplot ('division_product_returns', 'data/returns_by_region.json', returnsPlotObj);
h1
tag, as shown in the following code snippet, that is populated when our JavaScript parses the query string:<a href="1168_11_02.html?division=Media-Software">Media-Software</a> | <a href="1168_11_02.html?division=Electronics">Electronics</a> | <a href="1168_11_02.html?division=Nerd_Corral">Nerd Corral</a> <h1 id="division_name"></h1>
h2
tag in a section
tag and add a class as follows:<section class="division_chart"> <h2>Product Revenue by Month</h2> <div id="indiv_division_revenue" class="w600 h300"></div> </section> <section class=" division_chart "> <h2>Last 12 Months of Product Returns by Region</h2> <div id="division_product_returns"></div> </section> <section class=" division_chart "> <select id="trendline" name="trendline"> </select> <h2><span id="division"></span> Product Revenue with Trends</h2> <div id="division_rev_category" class="w700"></div> </section>
styles.css
. We float each section to the left and set the minimum width and height. We also change the background color of the legends so when they overlap our charts, we can still read them. This can be implemented as follows:section.division_chart { float: left; min-width: 48%; min-height: 425px; } section.division_chart table.jqplot-table-legend { background: #fff; }
We load the newly created dashboard in our browser. The two charts showing product revenue use the division colors and the product return chart has the company colors. We switch between the different divisions and see the data and the chart colors change:
We notice when we select DVD/Blu-ray Players from the Electronics dashboard drop-down menu, the legend ends up covering some of the chart. This is because we are using the outside
placement option for our chart. We remember that this option will place the legend outside the div for our chart.
As each chart is wrapped in a section
tag with a width of 48 percent, this means our legend will move around trying to stay inside the parent container. We could have used outsideGrid
but that would have shrunk the size of our bar chart, so we made a trade-off.
It is close to lunch time so we decide to go grab something to eat knowing that our meeting will likely be this afternoon. Just as we get to the door, our office phone rings. Calvin tells us we have a meeting to present our dashboards at two o'clock. We hang up and walk down to Calvin's favorite sandwich shop.
We arrive back in the office a little before two o'clock so we can get everything together for our presentation. Once we're ready, we make our way to the conference room, where Roshan, Sara, and Calvin are waiting on us. Even Jeff from IT has joined us. We connect our laptop and project the VP dashboard on the screen.
"I love it," Sara says after a few moments, "I like how the colors match the company's brand. Also the revenue and profit line chart stands out." Roshan speaks up, "The waterfall chart is nice and with Sara's data, we can see the Inventory Losses broken out in the chart below it." I tell them, "We didn't intend it that way. I guess it was a happy accident."
"We also have the divisional dashboard to present," I continue. I remind them that we have mocked up the functionality to change divisions on the chart, at which point you pull up the chart on the projector.
Roshan makes the first comment, "This is great. Maybe in the future we can get the product return data broken out by divisions as well. That way Electronics will only see the totals for their division."
Calvin raises his hand. "Is there any way these charts could work as a slideshow? We've got all these TVs around the office we could display them on." Sara jumps in, "I like this idea. It gets relevant information out to more people."
Roshan holds up his hands as if he's trying to slow us down. "We'll need to think it through. We don't want vendors and other non-employees being able to see this data but it's a good idea. However, what we have will work for now."
"Which brings us to the other two items to discuss," says Roshan. "We have taken baby steps in the area of social media and our daily deals website. We have been tracking social media conversions and want to get this information out there.
We want a chart showing the number of conversions each month and also the monthly revenue as a result of those conversions. We'll leave the rest up to you."
I mention that Roshan said there were two other items. "Right, I'll let Jeff tell you," Roshan says. "Thanks," Jeff says, "We like the charts you created for IT. We're in the process of getting final sign-off on an IT dashboard. Before we move forward, is there any way we can change the donut chart you created? I'm talking about the one showing current browser and version percentages (found in 1168_05_05.html
). We like it, but it would be really nice if we could have a tooltip near the cursor. I'm thinking, since you've used it on other charts, it should be an easy fix."
We tell him we'll look into it. Roshan speaks again, "Well, I think that's everything. We'll check back in later this week."
We get back to the office and start thinking through the social media conversion chart. It would be best to render the revenue data as a bar chart and then we can render the conversions as a line. We can also add a trend line for the revenue.
Since this is going to be the next phase of our dashboards, we begin thinking about things we can add to our chart beyond just the data. We begin reading more on how the canvas
element works. We come across the Dive Into HTML5 site, http://diveintohtml5.info/canvas.html. They discuss how to include images into the canvas. That gets us thinking. What if we added the company logo to the actual chart? Not just overlay it with CSS but make it part of the canvas?
18.189.186.109