CWIS Developer Documentation
Chart_Base.php
Go to the documentation of this file.
1 <?PHP
2 #
3 # FILE: Chart_Base.php
4 #
5 # Part of the Collection Workflow Integration System (CWIS)
6 # Copyright 2017 Edward Almasy and Internet Scout Research Group
7 # http://scout.wisc.edu/cwis/
8 #
9 
13 abstract class Chart_Base
14 {
15  # ---- PUBLIC INTERFACE --------------------------------------------------
16 
26  public function LegendPosition($Position)
27  {
28  if (!in_array($Position,
29  [self::LEGEND_BOTTOM, self::LEGEND_RIGHT,
30  self::LEGEND_INSET, self::LEGEND_NONE]))
31  {
32  throw new Exception("Unsupported legend position: ".$Position);
33  }
34  $this->LegendPosition = $Position;
35  }
36 
43  public function LegendLabels($LegendLabels)
44  {
45  $this->LegendLabels = $LegendLabels;
46  }
47 
57  public function Labels($NewValue = NULL)
58  {
59  if ($NewValue !== NULL)
60  {
61  if (!is_array($NewValue) && ($NewValue !== FALSE))
62  {
63  throw new InvalidArgumentException("Invalid new value (".$NewValue.").");
64  }
65  $this->Labels = $NewValue;
66  }
67  return $this->Labels;
68  }
69 
76  public function Colors($NewValue=NULL)
77  {
78  if (!is_null($NewValue))
79  {
80  $this->Colors = $NewValue;
81  }
82 
83  return $this->Colors;
84  }
85 
90  public function Height($NewValue)
91  {
92  if (!is_null($NewValue))
93  {
94  $this->Height = $NewValue;
95  }
96 
97  return $this->Height;
98  }
99 
104  public function Width($NewValue)
105  {
106  if (!is_null($NewValue))
107  {
108  $this->Width = $NewValue;
109  }
110 
111  return $this->Width;
112  }
113 
146  public function Display($ContainerId)
147  {
148  self::RequireNeededFiles();
149 
150  # declare the chart data that we will give to c3.generate
151  # for function callbacks, give the function a name ending with
152  # '_fn' and include the function name as a string
153  $this->Chart = [
154  "bindto" => "#".$ContainerId,
155  "size" => [
156  "height" => $this->Height,
157  "width" => $this->Width,
158  ],
159  "tooltip" => [
160  "format" => [
161  "name" => "tooltip_name_fn",
162  ],
163  ],
164  ];
165 
166  # set up legend positioning
167  if ($this->LegendPosition == self::LEGEND_NONE)
168  {
169  $this->Chart["legend"]["show"] = FALSE;
170  }
171  else
172  {
173  $this->Chart["legend"]["position"] = $this->LegendPosition;
174  }
175 
176  # if the user provided a color palette, set that up as will
177  if (!is_null($this->Colors()))
178  {
179  # sort user-provided colors into the correct order
180  $Palette = [];
181  foreach ($this->Data as $Index => $Value)
182  {
183  $Palette[]= isset($this->Colors[$Index]) ?
184  $this->Colors[$Index] :
185  $this->GenerateRgbColorString($Index);
186  }
187 
188  $this->Chart["color"]["pattern"] = $Palette;
189  }
190 
191  static::PrepareData();
192 
193  // @codingStandardsIgnoreStart
194  ?><div id="<?= $ContainerId ?>" class="cw-<?= strtolower(get_called_class()) ?>"></div>
195  <script type="text/javascript">
196  $(document).ready(function(){
197  // define state variables for this chart
198  var label_lut = <?= json_encode($this->TooltipLabels) ?>;
199  <?PHP static::DeclareStateVariables(); ?>
200 
201  // define helper functions for this chart
202  function tooltip_name_fn(name, ratio, id, index) {
203  return name in label_lut ? label_lut[name] : name;
204  }
205  <?PHP static::DeclareHelperFunctions(); ?>
206 
207  // get the chart spec data
208  var chart_spec = <?= json_encode($this->Chart) ?>;
209 
210  // convert any strings that refer to functions into callable function refs
211  function eval_fns(obj){
212  for (var prop in obj) {
213  if (typeof obj[prop] == "object") {
214  eval_fns(obj[prop]);
215  } else if (typeof obj[prop] == "string" && obj[prop].match(/_fn$/)) {
216  obj[prop] = eval(obj[prop]);
217  }
218  }
219  }
220  eval_fns(chart_spec);
221 
222  // generate the chart
223  c3.generate(chart_spec);
224  });
225  </script><?PHP
226  // @codingStandardsIgnoreEnd
227  }
228 
233  public static function PrepForDisplayingCachedVersion()
234  {
235  self::RequireNeededFiles();
236  }
237 
238  # legend position constants
239  const LEGEND_BOTTOM = "bottom";
240  const LEGEND_RIGHT = "right";
241  const LEGEND_INSET = "inset";
242  const LEGEND_NONE = "none";
243 
244  # ---- PRIVATE INTERFACE --------------------------------------------------
245 
249  protected static function RequireNeededFiles()
250  {
251  $GLOBALS["AF"]->RequireUIFile("d3.js");
252  $GLOBALS["AF"]->RequireUIFile("c3.js");
253  $GLOBALS["AF"]->RequireUIFile("c3.css");
254  $GLOBALS["AF"]->RequireUIFile("Chart_Base.css");
255  }
256 
262  abstract protected function PrepareData();
263 
268  protected function DeclareStateVariables()
269  {
270  return;
271  }
272 
279  protected function DeclareHelperFunctions()
280  {
281  return;
282  }
283 
289  protected function GenerateRgbColorString($DataIndex)
290  {
291  return "#".substr(md5($DataIndex), 0, 6);
292  }
293 
298  protected function AddToChart($Data)
299  {
300  $this->AddToArray($this->Chart, $Data);
301  }
302 
308  protected function AddToArray(&$Tgt, $Data)
309  {
310  foreach ($Data as $Key => $Val)
311  {
312  if (isset($Tgt[$Key]) &&
313  is_array($Tgt[$Key]) && is_array($Val))
314  {
315  $this->AddToArray($Tgt[$Key], $Val);
316  }
317  else
318  {
319  $Tgt[$Key] = $Val;
320  }
321  }
322  }
323 
324  # data provided by caller
325  protected $Data = [];
326 
327  # chart parameters that can be changed prior to generation
328  protected $LegendPosition = self::LEGEND_BOTTOM;
329  protected $Colors = NULL;
330  protected $Labels = [];
331  protected $LegendLabels = [];
332  protected $Height = 600;
333  protected $Width = 600;
334 
335  # internal variables used to generate the chart
336 
337  # map legend labels (which C3 uses for item identifiers) to the
338  # labels we want in the tooltip
339  protected $TooltipLabels = [];
340  protected $Chart = NULL;
341 }
Base class for generating and displaying a chart.
Definition: Chart_Base.php:13
const LEGEND_INSET
Definition: Chart_Base.php:241
DeclareStateVariables()
Output var declarations for any js state variables needed in this chart&#39;s display helper functions...
Definition: Chart_Base.php:268
Height($NewValue)
Get/Set height of the chart including the legend.
Definition: Chart_Base.php:90
Labels($NewValue=NULL)
Get/set chart element labels (pie slices, bars, etc).
Definition: Chart_Base.php:57
Width($NewValue)
Get/Set width of the chart including the legend.
Definition: Chart_Base.php:104
LegendLabels($LegendLabels)
Set shortened labels to be used in the legend of the chart.
Definition: Chart_Base.php:43
Display($ContainerId)
Display a chart.
Definition: Chart_Base.php:146
DeclareHelperFunctions()
Output function definitions for any needed javascript display helper functions.
Definition: Chart_Base.php:279
static PrepForDisplayingCachedVersion()
Set up the chart environment so that cached HTML from a previous Display() call will function properl...
Definition: Chart_Base.php:233
AddToArray(&$Tgt, $Data)
Merge elements from a source array into a dest array.
Definition: Chart_Base.php:308
AddToChart($Data)
Merge an array of settings into $this->Chart.
Definition: Chart_Base.php:298
const LEGEND_BOTTOM
Definition: Chart_Base.php:239
static RequireNeededFiles()
Include necessary JS/CSS for chart generation.
Definition: Chart_Base.php:249
Colors($NewValue=NULL)
Get/set color palette.
Definition: Chart_Base.php:76
const LEGEND_NONE
Definition: Chart_Base.php:242
const LEGEND_RIGHT
Definition: Chart_Base.php:240
PrepareData()
Massage data provided by the user into an appropriate format for plotting and do any necessary tweaks...
LegendPosition($Position)
Set legend position.
Definition: Chart_Base.php:26
GenerateRgbColorString($DataIndex)
Get RGB hex color when no color supplied.
Definition: Chart_Base.php:289