A Bar Graph Generator


Graphs are excellent ways to display visual information. You can create bar graphs by drawing them in Adobe Photoshop or by calculating them in Microsoft Excel, but for dynamic data that might need to change on a regular basis, why not have JavaScript do it instead on the fly? While we've said throughout this book that JavaScript is object-oriented (and therefore buzzword -compliant), and we've used objects throughout the book, we've only briefly shown you how to create your own custom objects. Here's a more in-depth example of how objects work, as seen in Scripts 14.12 (HTML), 14.13 (CSS), and 14.14 (JavaScript).

Script 14.12. The HTML page for the bar chart generator.
[View full width]
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"> <html xmlns="http://www.w3.org/1999/xhtml"> <head>      <title>Bar Chart Form Input</title>      <link rel="stylesheet" rev="stylesheet" href="script05.css" />      <script language="Javascript" type="text/ javascript" src="script05.js">      </script> </head> <body> <form action="#">      Choose a chart<br />      <input type="radio" name="type" value="browser" checked="checked" /> Browser Usage<br />      <input type="radio" name="type" value="platform" /> JavaScript Usage<br />      <p><br /></p>      Choose a color<br />      <input type="radio" name="color" value="lilRed.gif" checked="checked" />&nbsp;Red<br />      <input type="radio" name="color" value="lilGreen.gif" /> Green<br />      <input type="radio" name="color" value="lilBlue.gif" /> Blue<br />      <p><br /></p>      Choose a direction<br />      <input type="radio" name="direction" value="horizontal" checked="checked" />  Horizontal<br />      <input type="radio" name="direction" value="vertical" /> Vertical </form> <div id="chartArea"">&nbsp;</div> </body> </html> 

Script 14.13. This script contains the styles for the bar chart example.
 body {      background-color: white;      color: black;      font-size: 12px; } form {      float: left;      width: 200px; } .vert {      text-align: center;      vertical-align: bottom; } .horiz {      padding: 5px; } th.vert {      border-left: 1px black solid;      border-bottom: 1px black solid;      vertical-align: middle;      text-align: left;      font-size: 16px; } th.horiz {      border-right: 1px black solid;      vertical-align: middle;      text-align: left;      font-size: 16px; } 

Script 14.14. And here's the code that draws the bar chart.
[View full width]
 window.onload = initAll; function initAll() {  var radioButtons = document. getElementsByTagName("input");   for (var i=0; i<radioButtons.length; i++) {   if (radioButtons[i].type == "radio") {   radioButtons[i].onclick = chgChart;   }   }   chgChart();  } function chgChart() {  var bChart = new Object();   bChart.name = "Browser usage by year";   bChart.years = new Array("1998","1999", "2000","2001","2002","2003","2004", "2005",  "2006");   bChart.fieldnames = new Array("Netscape", "MSIE","Other");   bChart.field1 = new Array(38.9,31.9,21.2, 12.4,6.6,5.1,3,1,6);   bChart.field2 = new Array(60.6,67.4,78.3, 85.6,92.5,94.0,92,89,90);   bChart.field3 = new Array(0.5,0.5,0.5,2.1, 0.9,1.0,4,9,3);   bChart.fields = new Array(bChart.field1, bChart.field2,bChart.field3);   var jsChart = new Object();   jsChart.name = "JavaScript usage by year";   jsChart.years = new Array("1998","1999", "2000","2001","2002","2003","2004", "2005",  "2006");   jsChart.fieldnames = new Array("1.2 or later","1.0 - 1.1","No JavaScript");   jsChart.field1 = new Array(63.4,66.5,78.4, 80.2,88.1,89.1,94,89,96);   jsChart.field2 = new Array(18.7,12.6,2.8, 0.8,0.3,0.3,0,0,0);   jsChart.field3 = new Array(17.9,21.0,18.8, 19.0,11.6,10.6,4,9,3);   jsChart.fields = new Array(jsChart.field1, jsChart.field2,jsChart.field3);   var radioButtons = document. getElementsByTagName("input");   var currDirection = getButton("direction");   var imgSrc = "images/" + getButton ("color");   var thisChart = (getButton("type")== "browser") ? bChart : jsChart;   var chartBody = "<h2>"+thisChart. name+"</h2><table>";   for (var i=0; i<thisChart.years.length; i++) {   if (currDirection=="horizontal") {   chartBody += "<tr><th rowspan='4' class='horiz'>"+thisChart.years[i];   chartBody += "</th><td colspan= '2'></td></tr>";   for (var j=0; j<thisChart. fieldnames.length; j++) {   chartBody += "<tr><td class='horiz'>"+thisChart. fieldnames[j];   chartBody += "</td><td><img src='"+imgSrc+"' height='15' width='";   chartBody += thisChart.fields [j][i]*3 + "' alt='horiz bar' />";   chartBody += "&nbsp;&nbsp;"+ thisChart.fields[j][i]+ "</td></tr>";  }         }         else {  chartBody += "<tr><th rowspan='2' class='vert'>"+thisChart.years[i]+ "</th>";   for (var j=0; j<thisChart. fieldnames.length; j++) {   chartBody += "<td class='vert'> <img src='" + imgSrc;   chartBody += "' alt='vert bar' hspace='10' width='15' height='";   chartBody += thisChart.fields [j][i]*3 +"' /></td>";  }  chartBody += "</tr><tr>";   for (j=0; j<thisChart.fieldnames. length; j++) {   chartBody += "<td class='vert'>" + thisChart.fields[j][i] + "<br />";   chartBody += thisChart. fieldnames[j] + "<br /><br /></td>";  }  chartBody += "</tr>";  }      }  chartBody += "</table>";   document.getElementById("chartArea"). innerHTML = chartBody;  function getButton(buttonSet) {         for (var i=0; i<radioButtons.length; i++) {            if (radioButtons[i].name == buttonSet && radioButtons[i]. checked) {               return radioButtons[i].value;            }         }         return -1;      } } 

To generate a bar graph:

1.
 var radioButtons = document. getElementsByTagName("input"); for (var i=0; i<radioButtons.length; i++) {   if (radioButtons[i].type == "radio") {      radioButtons[i].onclick = chgChart;   } } chgChart(); 



As we've done so many times, the initAll() function starts the ball rolling. Here, we get all the radio buttons and loop through them, setting each to call chgChart() when they're clicked. When that's done, we call chgChart() manually to display the default view of the page.

2.
 var bChart = new Object(); 



Here, inside c hgChart() , is where we create our first custom object, bChart (short for "browser chart"). Yep, that's all there is to it.

3.
 bChart.name = "Browser usage by year"; bChart.years = new Array("1998", "1999","2000","2001","2002", "2003","2004","2005","2006"); bChart.fieldnames = new Array ("Netscape","MSIE","Other"); bChart.field1 = new Array(38.9,31.9, 21.2,12.4,6.6,5.1,3,1,6); bChart.field2 = new Array(60.6,67.4, 78.3,85.6,92.5,94.0,92,89,90); bChart.field3 = new Array(0.5,0.5, 0.5,2.1,0.9,1.0,4,9,3); 



The properties for a custom object are created and initialized simply by assigning values to them. Here, we set up the name , years , fieldnames , field1 , field2 , and field3 properties of bChart . Those fields are, respectively, the name of the chart, the years covered by the chart, the three labels for the chart values, and the sets of values for each year and each label (in this case, each browser).

Note that we're not using the var keyword before each of these; that's because they aren't new variables . Instead, they're new properties that we're adding to an existing variable (albeit one we just created).

4.
 bChart.fields = new Array (bChart.field1,bChart.field2, bChart.field3); 



Here we create the fields property. It's actually an array of arrays and will make it easier to get at the data inside.

5.
 var jsChart = new Object(); jsChart.name = "JavaScript usage by year"; jsChart.years = new Array("1998", "1999","2000","2001","2002", "2003","2004","2005","2006"); jsChart.fieldnames = new Array("1.2 or later","1.0 - 1.1","No JavaScript"); jsChart.field1 = new Array(63.4, 66.5,78.4,80.2,88.1,89.1,94,89, 96); jsChart.field2 = new Array(18.7, 12.6,2.8,0.8,0.3,0.3,0,0,0); jsChart.field3 = new Array(17.9, 21.0,18.8,19.0,11.6,10.6,4,9,3); jsChart.fields = new Array(jsChart. field1,jsChart.field2,jsChart. field3); 



In the same way that we created the bChart object, we now create the jsChart (JavaScript chart) object and assign its properties. For the JavaScript chart, we again have the years, but this time we're measuring what percentage of browsers have JavaScript and which version.

6.
 var radioButtons = document. getElementsByTagName("input"); var currDirection = getButton ("direction"); var imgSrc = "images/" + getButton ("color"); 



Before we draw our chart, we need to know which radio buttons have been selected. The radioButtons array contains all the input elements on the page, and once we've got that, we can call the getButton() function. The getButton() function is passed a string (the name of the radio set), and it returns a string (the current value of that set).

We could have written getButton() to set up radioButtons instead of doing it here, but this way means that it's only initialized once instead of three times (once for every time getButton() is called).

7.
 var thisChart = (getButton("type")== "browser") ? bChart : jsChart; 



When the user clicks any of the radio buttons to change the chart, the chgChart() function is called. When that happens, if the browser chart is the one that's wanted, the entire bChart object gets stored in thisChart . Otherwise, it's the JavaScript chart for us, so thisChart is assigned the jsChart object.

8.
 var chartBody = "<h2>"+thisChart. name+"</h2><table>"; 



Here's the start of the actual drawing code. First, we write out the name of the chart (stored in thisChart.name and displayed inside an <h2> tag), and then we open up a <table> tag. From here on out, we're adding to the chartBody variable, and when we're done, we'll write it out to the page.

9.
 for (var i=0; i<thisChart.years. length; i++) { 



Here's the first of two loops that we'll be going through (remember that pseudo two-dimensional array from step 4?). This external loop uses i as the index variable, and how many times it loops around is based on the number of years covered by the chart.

10.
 if (currDirection=="horizontal") { 



If the user wants to see the horizontal version of the chart ( Figure 14.8 ), run the following code.

Figure 14.8. The initial horizontal version of the bar graph.


11.
 chartBody += "<tr><th rowspan='4' class='horiz'>"+thisChart. years[i]; chartBody += "</th><td colspan= '2'></td></tr>"; 



The first row of each horizontal chart contains the i th year label.

12.
 for (var j=0; j<thisChart. fieldnames.length; j++) { 



Here's the horizontal version of the second of the two loops. This internal loop uses j as its index, and how many times it loops around is based on the number of fieldnames that we stored.

13.
 chartBody += "<tr><td class= 'horiz'>"+thisChart. fieldnames[j]; 



The detail row of the table is started here, and we first write out the value label (either the browser type or the JavaScript version), which is stored in the j th element of fieldnames .

14.
 chartBody += "</td><td><img src= '"+imgSrc+"' height='15' width='"; chartBody += thisChart.fields [j][i]*3 + "' alt='horiz bar' />"; 



Next , we close the previous cell and calculate the bar image. The color of the bar is based on imgSrc , the height is always 15 pixels, and the width is the value of the j th by i th index in the array, multiplied by 3. For example, if imgSrc is lilBlue.gif and thisChart.fields[3][4] is 30, this would write out an image tag to draw a blue rectangle, 15 pixels high by 90 pixels wide.

15.
 chartBody += "&nbsp;&nbsp;"+ thisChart.fields[j][i]+"</td> </tr>"; 



A couple of blank characters (the &nbsp; ) are written out, followed by the actual data value to the right of the bar to finish off this row. This is the end of the interior loop for the horizontal section of the code.

16.
 chartBody += "<tr><th rowspan= '2' class='vert'>"+thisChart. years[i]+"</th>"; 



If the user wants to see the chart drawn vertically ( Figure 14.9 ), we start by writing the initial row of the chart. The vertical version of the chart is somewhat more complex and requires two internal (but separate) j loops. Here we write out the label for the chart.

Figure 14.9. The vertical version of the bar graph.


17.
 for (var j=0; j<thisChart. fieldnames.length; j++) { 



Here's the first internal loop. This one writes out each vertical bar on the graph in a row.

18.
 chartBody = += "<td class='vert'> <img src='" + imgSrc; chartBody += "' alt='vert bar' hspace='10' width='15' height='"; ChartBody += thisChart.fields [j][i]*3 = +"' /></td>"; 



And here's the image tag being written on the fly. This time, the width is fixed at 15 pixels, but the height varies based on the value found in the array of arrays. For example, if imgSrc is lilGreen.gif and thisChart.fields[3][4] is 30, this would write out an image tag to draw a green rectangle, 90 pixels high by 15 pixels wide.

19.
 chartBody += "</tr><tr>"; 



When all the bars on the graph have been written out, close that table row and start the next row.

20.
 for (j=0; j<thisChart.fieldnames. length; j++) { 



Here's the second internal loop. This one writes the value of each data point, under its corresponding bar, followed by the y-axis label.

21.
 chartBody += "<td class='vert'>" + thisChart.fields[j][i] + "<br />"; chartBody += thisChart.fieldnames [j] + "<br /><br /></td>"; 



Here's the information being written out for each bar. The variable thisChart.fields[j][i] is the value of that bar, and thisChart.fieldnames[j] is the data label for that bar.

22.
 chartBody += "</tr>"; 



After the last internal loop is complete, we need to write out a final end row tag.

23.
 chartBody += "</table>"; document.getElementById ("chartArea").innerHTML = chartBody; 



At this point, both the horizontal and vertical sections are done, and the external loop has completed, so we write out the final table tag to end our script and then put the entire thing into the innerHTML property of the chartArea section of the page.

Tips

  • This code uses three images: lilRed.gif , lilBlue.gif , and lilGreen.gif . Each of these is a single-pixel GIF in its corresponding color. HTML allows you to set the height and width regardless of the image's actual physical dimensions, so a single pixel allows us to create bars of any size and shape.

  • This chart can be changed to graph almost anything simply by changing the array values in steps 3 and 5. No matter what you set the arrays to, you shouldn't have to change the loops that create the graphs.

  • The statistics on these charts are based on those found at The Counter's Global Statistics, at http://www. thecounter .com/stats/. Unfortunately, they only started keeping track of these figures in September 1998, so the 1998 figures begin in September. Figures for all other years begin in January.





JavaScript and Ajax for the Web(c) Visual QuickStart Guide
JavaScript and Ajax for the Web, Sixth Edition
ISBN: 0321430328
EAN: 2147483647
Year: 2006
Pages: 203

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net