### as-diagrams: Pure HTML (no GD) bar chart drawing class

Russian version

If You need adding some business graphics presentation to Your WEB site, you use diagrams (charts). The question is what kind of diagrams you need and what engine is optimal for you. When I came to this situation, I decided to write small PHP engine that doesn't use graphics library (GD) at all, because all I needed was a bar charts. Generated HTML code does not contain any java or javascript code, so it must be compatible with almost any version of browser. This engine implemented in OOP manner, as PHP class.
It tested and works well under PHP 4.3.x.

Here is an instruction of how to embed "as-diagrams" engine into your intranet or internet site.

#### Installing as-diagrams on your site

There is no much revolutionary in installing process:

1. Download distributive zip file and unzip it into temporary folder. If you will use diagram engine from more than one page, place as-diagrams.php file into one of folders listed in your PHP.ini "include_path" variable. Otherwise, just place it in the folder with your main script.
2. Move or copy img folder contents into your common pictures folder (You'll set relative path to this folder in the $imgpath variable)
3. Open script file as-diagrams.php in text editor and adjust some lines :

          var $bt_total = 'Totals'; // localize here or include into separate file
          var $imgpath = '/img/'; // place all 'diagram' images in this "folder"

   $bt_total = ... - localize 'Totals' title text if needed.
   $imgpath = ... - set your 'relative' path to the pictures folder.
4. for better look find stylesheet section in as-diagrams.php and adjust it to meet your web-site common design

That's it, if Your site already supports PHP 4.x, script is ready to go. Now we'll make it breathe.

### Using CAsBarDiagram class

You can draw bar charts for pre-calculated data arrays, or pass SQL queries to CAsBarDiagram object variable.

1. Do not forget to include engine module into your script file : require_once('as-diagrams.php');
2. Define object var of CAsBarDiagram class, and set some non-default values if needed:

            $graph = new CAsBarDiagram;
            $graph->bwidth = 15; // one bar width in pixels
            $graph->showdigits = 0; // hide "digit presentation" part under bars (turned ON by default)
            $graph->bt_total = 'Some totals'; // title for totals column on the right side
            $graph->precision = 0;  // how much digits after decimal point
            $graph->showtotals = 0;  // hide totals column, (turned ON by default)

3. Make one- or two-dimensional arrays for "legends" - one for X axis ($legend_x), and one for Y axis (Y is a number of bars in on X-th "group")
   One-dimensional legend array holds just a "keys" for every column, it's used as a key while gathering data and as a legend title on the var chart (in case You use one-dim legends). If You prepare two-dimensional array, the first element ($legend_x[$row][0]) in a row will be treated as a key value, and the second one, $legend_x[$row][1] - as a legend title. In that case there is no need in additional "key" array legendx_id. Note that 'keys' only needed if Uou'll collect data from a SQL database, where your entities have "digital" unique ID's (primary keys in SQL tables) and "text" representation.

            $legend_x = array('Yanuary','February','March','April','May','June');
            $legend_y = array(array(1,'pens'),array(2,'pensils'),array(3,'staplers'),array(4,'paper'));

4. Now You can choose from 2 methods:
   1) gather data for drawing by Yourself, placing them into $data[x][y], and pass $data to the bar drawing method of CAsBarDiagram class:

              $data = array( array(200,300,120), array(450,500,100), array(650,200,300),
                             array(380,200,90), array(750,340,200));
              $graph->DiagramBar($legend_x, $legend_y, $data, 1, 'Sales results');

   2) call GatherData method, passing a SQL-query to it, so all data can be gathered for You (don't forget to connect MySQL base before this !):

              $graph->InitData($legend_x, $legend_y); // reset internal data array if needed
              $graph->GatherData($SQLqry, $legend_x, $legend_y);
              // ... GatherData can be called more than once
              $graph->DiagramBar($legend_x, $legend_y, 0, $data_title);

   Please note, in the second case You pass scalar value (0) to DiagramBar() method instead of data array, so engine can choose internal data array, assembled by GatherData calls.

### CAsBarDiagram methods and variables

InitData($legend_x, $legend_y) - this method clens up inetrnal data array from all the data. It is nesessary if You use on CAsBarDiagram object var for multiple bar drawing, before collecting data for second (, third, etc.) graphs. Internal data dimension becomes equal to count($legend_x), count(legend_y).

GatherData($sqltext, $legend_x, $legend_y [,$position_y]) - executes passed SQL query on currently open MySQL connection and fills internal array with result data. You can fill all array rows if Your query returns three fields :
the first one is a "key" for X-axis, second one - for Y axis, and third field is a value we are going to render.
Quary sample (MySQL)

        SELECT MONTH(sale_date) AS mnt, product, SUM(sales_val) FROM sales
           WHERE YEAR(sale_date)=2005 GROUP BY mnt,product

If You want to fill just one row in data array, You just design and pass two-field SQL query, and an optional 4-th parameter, $position_y, defining Y-position of data column beeing filled.

DiagramBar($legend_x, $legend_y, [$data|0, [$data_title]]) - the main method, it draws bar chart. If 3-rd paraveter is omitted or scalar value, internal data array will be rendered. In case of array passed, CAsBarDiagram uses it instead of internal data even if You've called GatherData() before.

$data - two-dimensional data array. $data[x][y] - value for bar 'Y' in Y-th section in the bar chart.

$showdigits - turns On/Off rendering of "digit" part under bars (the table with number presentation of rendered data array)

$ShowPercents - by assigning some non-empty string to this array var You turn on "percents" drawing:
additional rows will be rendered in the "digit" area under the bars. This row[s] will contain 'percent' values for two previous rows - $data[n-1]/$data[n] * 100. This feature was introduced, when my boss asked me to show fact/plan in percent, knowing that the one row was a 'fact' and the next - planned values. How to use it:
Suppose, there is a data row with 'fact' values, that has a corresponding title 'Year 2005' in the $legend_y array. The next row is a 'plan' data, having title 'Plan 2005' in the $legend_y. So, when we need to draw "Fact/plan * 100%" values right after the 'plan' row, we just put this code before calling DiagramBar() method:

        $graph->ShowPercents['Plan 2005'] = 'Percents';

If this var set to one short letter or digit (say, '1' or '*'), the title for this row will be computed from two last rows in legend_y : 'Legend_y_for_fact/Legend_y_for_plan, %'. If You set a longer string, it will be used as a row title.
Sample:

         $graph->ShowPercents[Plan 2004'] = 'Plan 2004 reaching, percents';
         $graph->ShowPercents[Plan 2005'] = 'Plan 2005 reaching, percents';
         // two "percent" rows will be shown
         $graph->DiagramBar($legend_x, $legend_y, 0, $data_title);

If you set $graph->ShowPercents array element to non-empty value, "digit" part will be rendered regardless of $graph->showdigits value. (as if $showdigits was 1)

$drawempty_x, $drawempty_y - this varū defines "to draw OR NOT to draw" for empty columns/columns in the barchart. They are equal 1 by default, i.e. all columns and rows (even with all zeroes) will be drawn. You have to set it before calling DiagramBar(). The method HideEmptyX($Hide=1) can be used to hide empty columns, and HideEmptyX() to hide empty rows in the digit part. HideEmptyXY($val=true) can be called to set both (x and y) values.

         $grarh->drawempty_x = 0;
         $graph->HideEmptyX(); // both operators has an equal result.

The next three variables used for converting Your legend titles to URL links.

- legendx_url - this is a class variable, that can be set if You want legend titles to become URL links (anchors). Just set the desired "URL" value to this var:

           $grarh = new CAsBarDiagram;
           $graph->legendx_url = 'detailedinfo.php?info_id={ID}';

  After that all legend titles will become a <A HREF...>'s to Your URL. Macro "{ID}" will be substituted with ID value or with N-th element value of legendx_id array, it it's set.
- legendx_onClick - this var holds "onClick" event value, so if You want to run some JavaScript instead of opening new URL, set Your event here. For example, to open popup window with some detailed data, You may fill the variable like this:

           $graph->legendx_onClick = "window.open('details.php?id={ID}', '_blank','height=300,width=400');";

- legendx_id - {ID} values array that will be used for creating "legend anchors". If it's not set, legend X title texts will substitute {ID} values in hrefs and "onClick" event definitions.

Here's working example.

    require_once('as-diagrams.php');
    //... include other needed libs

    $data_title = 'as-diagrams demo barchart'; // title for the diagram

    $data = array();
    $data[] = array(900, 1300,1600);
    $data[] = array(1200,1800,2500);
    $data[] = array(1400,2000,2800);
    $data[] = array(1900,2900,3900);
    $data[] = array(2500,3500,4500);

    $legend_x = array('Yan','Feb','March','April','May');
    $legend_y = array('pens','pensils','staplers');

    $graph = new CAsBarDiagram;
    $graph->bwidth = 10; // set one bar width, pixels
    $graph->bt_total = 'Summary'; // 'totals' column title, if other than 'Totals'
    // $graph->showtotals = 0;  // uncomment it if You don't need 'totals' column
    $graph->precision = 0;  // decimal precision
    // call drawing function
    $graph->DiagramBar($legend_x, $legend_y, $data, $data_title);

As a result of calling this script You will see something like this:
Here are some comments about using engine.

- Data can contain negative values - in that case the second (negative) part of a data will be drawn.
- You can set the bar width by setting $bwidth variable before calling DiagramBar();
- If data array contains too much lines, leading to draw very wide page, one bar width will be automatically adjusted ($bwidth variable). The maximum graph width is 1024 pixels (for "standard" monitor resolution 1024 x 768).
If You want to disable this behavior, just find in as-diagrams.php the code line :

      "var $autoshrink = 1024;"

and comment it. Or, yes, You can change the maximum screen width here.
- As You might notice, Y axis is alwais divided into four parts, and each part has a height of 60 pixels (so, maximum full Y axis height is 240 px). Image file "bar-bg240.png" is used as a background for the main graphics area. If You want to change a background, just modify this file. If you want to change this "base" height, You will have to draw a new backgound image, name it bar-bgNNNN.png (image height 1/4 of desired "full" height), and pass the new height into engine: to do this, just add a line somewhere in your code, before calling DiagramBar():
  $graf_height = NNNN;
  where NNNN - your height for Y axis.
  Remember, if Your data contains positive and negative values, diagrams may be up to two times higher, because of drawing two parts.
- If You want to change bar colors or their order, just edit code in as-diagrams.php or substitute original files bar-*.png. But when You'll be painting new bars please keep in mind - they will be stretched/shrinked vertically and horizontally on final graphs.
- By default bars filled by stretched images bar-xxxxx.png. If You want "tiled" images, just set non-empty value for variable $btilemode before calling DiagramBar(): $btilemode=1;
  In that case You will want to substitute pre-defined pictures with some "tile" looking ones.
- If You plan working with small or non-integer values, decimal precision will count, in that case You can adjust a number of decimal digits in $precision variable - just set it to desired value before calling DiagramBar():
  $precision = 4;
  Default precision is 2.

#### Version History

##### 1.0.11 (16.01.2007)

- New feature: legend arrays for X and Y axis may be two-dimensional ($legend_x[] and $legend_y[] respectively). In that case the first element in legend_x[i] and legend_y[i] row will be treated as "KEY" value, used for gathering data, and second one as "title" in the bar chart. See the details. When You prepare two-dimesional legend arrays, there is no need for additional variable legendx_id.
- Hiding "empty" columns in barchart and empty rows in "digital area" added. See the variable $drawempty_x,$drawempty_y, and HideEmpty...() methods.

##### 1.0.10 (01/17/2006)

- Numeric totals for columns can be drawn (in the digital view area) Variable showtotals now has a "bitwise" meaning: bit 0 is for "per row" totals (on the right), and bit 1 sets showing per-column totals (in the bottom)
- many percent rows can be drawn (in the digital view area)

#### Links

- as-diagrams and other PHP scripts collection on the author's homepage
- LT Diagram Builder - nice diagram and function draw engine, it can draw functions, pie, bar, line diagrams. There are javascript, PHP and ASP versions. PHP version uses GD library.
- w100w.com chart/diagram engine list

Copyright © Alexander Selifonov, as-works.narod.ru