Example of using constructed content, argument handling, hidden views and the Google chart module
I've been fiddling with this for a couple of months and I thought I'd add it to the documentation as an example for other users.
The goal was to replace a the excel spreadsheet and small paper notebook I've been using to track my bicycle riding. You can find a working example here: Michael's Bike Log
First, I installed the CCK and created a bicycle log content type containing the fields ridedate, ridedist, and ridespeed in addition to the standard title and body fields. It also has a computed field called blink which is set to
Computed Field: $node_field[0]['value'] = l($node->name . "'s Bike Log", "view/bikelog/$node->uid");
This allows each Bicycle Log entry to have a link to the view of all bike logs by the user.
Next, I created basic view, called bikelog, is a standard table view. It takes one argument (the uid of the user whose log we want) and lists the fields and reverse sorted by date - which needs no explanation.
The interesting part was when I wanted to add a chart displaying a summary of my progress. To do this, first I installed the Google Charts API. Next, I created a second table view. This view is identical to the first, but it takes a second argument that limits how many weeks to view:
Argument Handling Code: $view->filter[1]['options'] = $args[1] * -604800;
With the filter set to:
Filter: Date: Date-Date (field_ridedate) greater than or equal to now -9676800
Note that the value -9676800 gets overwritten by the argument handling code.
So, now comes the fun part. This second view is never intended to be used directly. Instead, it gets fed into the header for the first view. The header looks like this:
<?php
// This is how we find the arguments to the view.
global $current_view;
$uid = $current_view->args[0];
// Length of chart in weeks.
$maxweeks = 16;
// total mileage
$total = 0;
//load the data from the filtered per-week view.
$view = views_get_view('bikelogchart');
$items = views_build_view('items', $view, array($uid,$maxweeks));
//initialize the chart. Note that Google charts have fixed sizes, if you change the weeks you may have to
//change the chart_size() arguments.
$miles = array(
'#chart_id' => 'bike_log',
'#type' => CHART_TYPE_BAR_V_GROUPED, //CHART_TYPE_LINE,
'#size' => chart_size(540,160),
'#data_colors' => chart_data_colors(array("ff0000")),
'#grid_lines' => chart_grid_lines(0,10),
'#title' => chart_title(t("Miles Per Week"))
);
$l = sizeof($items['items']);
$max = 0;
//Label the slots in our chart
$now = time();
$wday = date("w",$now);
$now = $now + ((7-$wday)*86400);
for ($i=0; $i < $maxweeks; $i++) {
$miles['#data'][$i] = 0;
$miles['#labels'][$i] = date("m/d",$now-604800*($maxweeks-$i));
}
// Traverse the data from the view, summing up each week's total.
for ($i=0; $i < $l; $i++) {
$date = date_make_date($items['items'][$i]->node_data_field_ridedate_field_ridedate_value);
$time = $date->db->timestamp;
$slot = $maxweeks - (int)(($now - $time) / 604800);
if (date("w",$time) != 7) { $slot = $slot - 1; } // hack - otherwise Sunday rides go in the wrong week.
$total = $total + $items['items'][$i]->node_data_field_ridedist_field_ridedist_value;
$miles['#data'][$slot] = $miles['#data'][$slot] + $items['items'][$i]->node_data_field_ridedist_field_ridedist_value;
if ($miles['#data'][$slot] > $max) { $max = $miles['#data'][$slot]; }
}
// Normally Google bar and line charts scale from 0 to 100. Here we tweak that to round up to the
// nearest 20 miles.
$max = ((int)($max /20) + 1) * 20;
$miles['#mixed_axis_labels'][CHART_AXIS_Y_LEFT][0][] = chart_mixed_axis_range_label(0, $max);
$miles['#adjust_resolution'] = array( '#adjust' => true, '#max' => $max );
echo '<div class="bikelogchart">';
echo chart_render($miles);
echo '</div>';
echo '<p align=center>Total miles in the past ', $maxweeks, ' weeks: <strong>', $total, '</strong><br/><a href=/?q=node/add/bikelog>Add a new Bike Log entry</a></p>';
?>Seeing how long it took me to dig out little pieces like how to get the view arguments into the header, I hope you find this useful!
