mirror of
https://github.com/e107inc/e107.git
synced 2025-01-16 20:28:28 +01:00
699 lines
15 KiB
PHP
699 lines
15 KiB
PHP
<?php
|
|
/*
|
|
* e107 website system
|
|
*
|
|
* Copyright (C) 2008-2013 e107 Inc (e107.org)
|
|
* Released under the terms and conditions of the
|
|
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
|
|
*
|
|
* Chart Class for e107. @see https://github.com/FVANCOP/ChartNew.js for details.
|
|
*/
|
|
|
|
/**
|
|
*
|
|
*
|
|
* Example of Usage:
|
|
*
|
|
* $data = array();
|
|
|
|
$data['labels'] = array("January","February","March","April","May","June","July");
|
|
|
|
|
|
$data['datasets'][] = array(
|
|
'fillColor' => "rgba(220,220,220,0.5)",
|
|
'strokeColor' => "rgba(220,220,220,1)",
|
|
'pointColor ' => "rgba(220,220,220,1)",
|
|
'pointStrokeColor' => "#fff",
|
|
'data' => array(65,59,90,81,56,55,40)
|
|
|
|
);
|
|
|
|
$data['datasets'][] = array(
|
|
'fillColor' => "rgba(151,187,205,0.5)",
|
|
'strokeColor' => "rgba(151,187,205,1)",
|
|
'pointColor ' => "rgba(151,187,205,1)",
|
|
'pointStrokeColor' => "#fff",
|
|
'data' => array(28,48,40,19,96,27,100)
|
|
);
|
|
|
|
$options = array('bezierCurve' => false);
|
|
'
|
|
|
|
$cht = e107::getChart();
|
|
$cht->setType('line');
|
|
$cht->setOptions($options);
|
|
$cht->setData($data,'canvas');
|
|
echo $cht->render('canvas');
|
|
*/
|
|
|
|
/*
|
|
* var allopts = {
|
|
//Boolean - If we show the scale above the chart data -> Default value Changed
|
|
scaleOverlay : true,
|
|
//Boolean - If we want to override with a hard coded scale
|
|
scaleOverride : false,
|
|
//** Required if scaleOverride is true **
|
|
//Number - The number of steps in a hard coded scale
|
|
scaleSteps : null,
|
|
//Number - The value jump in the hard coded scale
|
|
scaleStepWidth : null,
|
|
//Number - The scale starting value
|
|
scaleStartValue : null,
|
|
//String - Colour of the scale line
|
|
scaleLineColor : "rgba(0,0,0,.1)",
|
|
//Number - Pixel width of the scale line
|
|
scaleLineWidth : 1,
|
|
//Boolean - Whether to show labels on the scale
|
|
scaleShowLabels : true,
|
|
//Interpolated JS string - can access value
|
|
scaleLabel : "<%=value%>",
|
|
//String - Scale label font declaration for the scale label
|
|
scaleFontFamily : "'Arial'",
|
|
//Number - Scale label font size in pixels
|
|
scaleFontSize : 12,
|
|
//String - Scale label font weight style
|
|
scaleFontStyle : "normal",
|
|
//String - Scale label font colour
|
|
scaleFontColor : "#666",
|
|
///Boolean - Whether grid lines are shown across the chart
|
|
scaleShowGridLines : true,
|
|
//String - Colour of the grid lines
|
|
scaleGridLineColor : "rgba(0,0,0,.05)",
|
|
//Number - Width of the grid lines
|
|
scaleGridLineWidth : 1,
|
|
//Boolean - Whether the line is curved between points -> Default value Changed
|
|
bezierCurve : false,
|
|
//Boolean - Whether to show a dot for each point -> Default value Changed
|
|
pointDot : false,
|
|
//Number - Radius of each point dot in pixels
|
|
pointDotRadius : 3,
|
|
//Number - Pixel width of point dot stroke
|
|
pointDotStrokeWidth : 1,
|
|
//Boolean - Whether to show a stroke for datasets
|
|
datasetStroke : true,
|
|
//Number - Pixel width of dataset stroke
|
|
datasetStrokeWidth : 2,
|
|
//Boolean - Whether to fill the dataset with a colour
|
|
datasetFill : true,
|
|
//Boolean - Whether to animate the chart -> Default value changed
|
|
animation : false,
|
|
//Number - Number of animation steps
|
|
animationSteps : 60,
|
|
//String - Animation easing effect
|
|
animationEasing : "easeOutQuart",
|
|
//Function - Fires when the animation is complete
|
|
onAnimationComplete : null,
|
|
canvasBorders : true,
|
|
canvasBordersWidth : 30,
|
|
canvasBordersColor : "black",
|
|
yAxisLeft : true,
|
|
yAxisRight : true,
|
|
yAxisLabel : "Y axis",
|
|
yAxisFontFamily : "'Arial'",
|
|
yAxisFontSize : 50,
|
|
yAxisFontStyle : "normal",
|
|
yAxisFontColor : "#666",
|
|
xAxisLabel : "",
|
|
xAxisFontFamily : "'Arial'",
|
|
xAxisFontSize : 16,
|
|
xAxisFontStyle : "normal",
|
|
xAxisFontColor : "#666",
|
|
yAxisUnit : "UNIT",
|
|
yAxisUnitFontFamily : "'Arial'",
|
|
yAxisUnitFontSize : 12,
|
|
yAxisUnitFontStyle : "normal",
|
|
yAxisUnitFontColor : "#666",
|
|
graphTitle : "",
|
|
graphTitleFontFamily : "'Arial'",
|
|
graphTitleFontSize : 24,
|
|
graphTitleFontStyle : "bold",
|
|
graphTitleFontColor : "#666",
|
|
graphSubTitle : "",
|
|
graphSubTitleFontFamily : "'Arial'",
|
|
graphSubTitleFontSize : 18,
|
|
graphSubTitleFontStyle : "normal",
|
|
graphSubTitleFontColor : "#666",
|
|
footNote : "Footnote",
|
|
footNoteFontFamily : "'Arial'",
|
|
footNoteFontSize : 50,
|
|
footNoteFontStyle : "bold",
|
|
footNoteFontColor : "#666",
|
|
legend : true,
|
|
legendFontFamily : "'Arial'",
|
|
legendFontSize : 18,
|
|
legendFontStyle : "normal",
|
|
legendFontColor : "#666",
|
|
legendBlockSize : 30,
|
|
legendBorders : true,
|
|
legendBordersWidth : 30,
|
|
legendBordersColor : "#666",
|
|
// ADDED PARAMETERS
|
|
graphMin : "DEFAULT",
|
|
graphMax : "DEFAULT"
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
* Using with Google Charts:
|
|
* $cht = e107::getChart();
|
|
$cht->setProvider('google');
|
|
$cht->setType('line');
|
|
$cht->setOptions('demo');
|
|
$cht->setData('demo','canvas');
|
|
$text = $cht->render('canvas');
|
|
*/
|
|
class e_chart
|
|
{
|
|
protected $id;
|
|
protected $data = null;
|
|
protected $type = 'line';
|
|
protected $options = array('scaleFontSize' => 14, 'annotateDisplay' => true, 'bezierCurve' => true, 'inGraphDataShow'=>false);
|
|
protected $provider = null;
|
|
|
|
|
|
function __construct()
|
|
{
|
|
// e107::js('core','chart/Chart.min.js','jquery');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// e107::css('inline','canvas.e-graph { width: 100% !important; max-width: 800px; height: auto !important; }');
|
|
}
|
|
|
|
/**
|
|
* @param $type
|
|
* @return $this
|
|
*/
|
|
public function setProvider($type = null)
|
|
{
|
|
if(!empty($type))
|
|
{
|
|
$this->provider = $type;
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @return null
|
|
*/
|
|
public function getProvider()
|
|
{
|
|
return $this->provider;
|
|
}
|
|
|
|
|
|
/**
|
|
* @return false|string
|
|
*/
|
|
private function getData()
|
|
{
|
|
return json_encode($this->data);
|
|
}
|
|
|
|
/**
|
|
* @return false|string
|
|
*/
|
|
private function getOptions()
|
|
{
|
|
return json_encode($this->options);
|
|
}
|
|
|
|
/**
|
|
* @param $flag
|
|
* @return $this
|
|
*/
|
|
public function debug($flag=false)
|
|
{
|
|
if($flag === true)
|
|
{
|
|
e107::getDebug()->log($this->data);
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function renderTable()
|
|
{
|
|
|
|
$head = array();
|
|
$body = array();
|
|
|
|
foreach($this->data as $k=>$v)
|
|
{
|
|
if($k == 0)
|
|
{
|
|
foreach($v as $key=> $val)
|
|
{
|
|
$head[] = $val;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
foreach($v as $key=> $val)
|
|
{
|
|
$body[$k][$key] = $val;
|
|
}
|
|
|
|
}
|
|
|
|
$text = "<table class='table table-condensed table-striped table-bordered'>";
|
|
$text .= "<colgroup>";
|
|
|
|
foreach($head as $th)
|
|
{
|
|
$text .= "<col class='".eHelper::secureIdAttr($th)."' />";
|
|
}
|
|
|
|
$text .= "</colgroup>";
|
|
|
|
|
|
|
|
$text .= "<tr>";
|
|
foreach($head as $th)
|
|
{
|
|
$text .= "<th>".$th."</th>";
|
|
}
|
|
|
|
$text .= "</tr>";
|
|
|
|
foreach($body as $tr)
|
|
{
|
|
$text .= "<tr>";
|
|
|
|
foreach($tr as $td)
|
|
{
|
|
$text .= "<td>".$td."</td>";
|
|
}
|
|
|
|
$text .= "</tr>";
|
|
}
|
|
|
|
$text .= "</table>";
|
|
|
|
return $text;
|
|
|
|
}
|
|
|
|
/**
|
|
* Set the type of graph
|
|
* @param string $type - line | bar | pie | radar | doughnut | polar
|
|
* @return $this
|
|
*/
|
|
public function setType($type)
|
|
{
|
|
$this->type = $type;
|
|
return $this;
|
|
}
|
|
|
|
|
|
/**
|
|
* Set the data values
|
|
* @param array $data
|
|
* @return $this
|
|
*/
|
|
public function setData($data)
|
|
{
|
|
// $this->id = $id;
|
|
if($data == 'demo')
|
|
{
|
|
$this->data = $this->getDemoData();
|
|
}
|
|
else
|
|
{
|
|
$this->data = $data;
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
private function getDemoData()
|
|
{
|
|
$data = array();
|
|
|
|
if($this->provider == 'google')
|
|
{
|
|
|
|
$data = array(
|
|
array('Year', 'Sales', 'Expenses'),
|
|
array('2013', 1000, 400),
|
|
array('2014', 1170, 460),
|
|
array('2015', 660, 1120),
|
|
array('2016', 1030, 540)
|
|
);
|
|
|
|
return $data;
|
|
}
|
|
|
|
|
|
|
|
$data['labels'] = array("January","February","March","April","May","June","July");
|
|
|
|
$data['datasets'][] = array(
|
|
'fillColor' => "rgba(220,220,220,0.5)",
|
|
'strokeColor' => "rgba(220,220,220,1)",
|
|
'pointColor ' => "rgba(220,220,220,1)",
|
|
'pointStrokeColor' => "#fff",
|
|
'data' => array(65,59,90,81,56,55,40),
|
|
'title' => "Visits"
|
|
|
|
);
|
|
|
|
$data['datasets'][] = array(
|
|
'fillColor' => "rgba(151,187,205,0.5)",
|
|
'strokeColor' => "rgba(151,187,205,1)",
|
|
'pointColor ' => "rgba(151,187,205,1)",
|
|
'pointStrokeColor' => "#fff",
|
|
'data' => array(28,48,40,19,96,27,100),
|
|
'title' => "Unique Visits"
|
|
);
|
|
|
|
return $data;
|
|
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* @param $data
|
|
* @return $this
|
|
*/
|
|
public function setOptions($data)
|
|
{
|
|
|
|
if($this->provider == 'google' && $data == 'demo')
|
|
{
|
|
$this->options = array(
|
|
'title' => 'Company Performance',
|
|
'hAxis' => array('title'=>'Year', 'titleTextStyle'=>array('color'=>'#333')),
|
|
'vAxis' => array('minValue'=>0)
|
|
);
|
|
|
|
}
|
|
else
|
|
{
|
|
$this->options = $data;
|
|
}
|
|
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Render Graph
|
|
* @param string $id of canvas
|
|
* @param integer $width
|
|
* @param integer $height
|
|
* @return null
|
|
*/
|
|
public function render($id, $width='100%',$height=300)
|
|
{
|
|
|
|
|
|
if($this->data == null)
|
|
{
|
|
return "<div class='alert alert-info alert-block'>No chart data provided</div>";
|
|
}
|
|
|
|
|
|
if($this->provider == 'google')
|
|
{
|
|
$this->options['width'] = $width;
|
|
$this->options['height']= $height;
|
|
|
|
$fName = 'draw'.ucfirst($id);
|
|
|
|
$js = " google.load('visualization', '1', {packages:['corechart']});
|
|
google.setOnLoadCallback(".$fName.");
|
|
function ".$fName."() {
|
|
var data = google.visualization.arrayToDataTable(".$this->getData().");
|
|
|
|
var options = ".$this->getOptions()." ;
|
|
";
|
|
|
|
|
|
switch ($this->type)
|
|
{
|
|
|
|
case 'bar':
|
|
$js .= "var chart = new google.visualization.BarChart(document.getElementById('".$id."')); ";
|
|
break;
|
|
|
|
case 'column':
|
|
$js .= "var chart = new google.visualization.ColumnChart(document.getElementById('".$id."')); ";
|
|
|
|
break;
|
|
|
|
case 'geo':
|
|
$js .= "var chart = new google.visualization.GeoChart(document.getElementById('".$id."')); ";
|
|
break;
|
|
|
|
case 'polar':
|
|
//TODO
|
|
break;
|
|
|
|
case 'doughnut':
|
|
//
|
|
break;
|
|
|
|
case 'pie':
|
|
$js .= "var chart = new google.visualization.PieChart(document.getElementById('".$id."')); ";
|
|
break;
|
|
|
|
default:
|
|
case 'line':
|
|
case 'area':
|
|
|
|
$js .= "var chart = new google.visualization.AreaChart(document.getElementById('".$id."')); ";
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
// Toggle Data from clicking on Legend. //FIXME
|
|
/* $js .= "
|
|
|
|
|
|
// create columns array
|
|
var columns".$id." = [];
|
|
// display these data series by default
|
|
var defaultSeries = [1, 3];
|
|
var series".$id." = {};
|
|
for (var i = 0; i < data.getNumberOfColumns(); i++) {
|
|
if (i == 0 || defaultSeries.indexOf(i) > -1) {
|
|
// if the column is the domain column or in the default list, display the series
|
|
columns".$id.".push(i);
|
|
}
|
|
else {
|
|
// otherwise, hide it
|
|
columns".$id.".push({
|
|
label: data.getColumnLabel(i),
|
|
type: data.getColumnType(i),
|
|
sourceColumn: i,
|
|
calc: function () {
|
|
return null;
|
|
}
|
|
});
|
|
}
|
|
if (i > 0) {
|
|
columns".$id.".push({
|
|
calc: 'stringify',
|
|
sourceColumn: i,
|
|
type: 'string',
|
|
role: 'annotation'
|
|
});
|
|
// set the default series option
|
|
series".$id."[i - 1] = {};
|
|
if (defaultSeries.indexOf(i) == -1) {
|
|
// backup the default color (if set)
|
|
if (typeof(series".$id."[i - 1].color) !== 'undefined') {
|
|
series".$id."[i - 1].backupColor = series".$id."[i - 1].color;
|
|
}
|
|
series".$id."[i - 1].color = '#CCCCCC';
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function showHideSeries".$id." () {
|
|
var sel = chart.getSelection();
|
|
// if selection length is 0, we deselected an element
|
|
if (sel.length > 0) {
|
|
// if row is undefined, we clicked on the legend
|
|
if (sel[0].row == null) {
|
|
var col = sel[0].column;
|
|
if (typeof(columns".$id."[col]) == 'number') {
|
|
var src = columns".$id."[col];
|
|
|
|
// hide the data series
|
|
columns".$id."[col] = {
|
|
label: data.getColumnLabel(src),
|
|
type: data.getColumnType(src),
|
|
sourceColumn: src,
|
|
calc: function () {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
// grey out the legend entry
|
|
series".$id."[src - 1].color = '#CCCCCC';
|
|
}
|
|
else {
|
|
var src = columns".$id."[col].sourceColumn;
|
|
|
|
// show the data series
|
|
columns".$id."[col] = src;
|
|
series".$id."[src - 1].color = null;
|
|
}
|
|
var view = new google.visualization.DataView(data);
|
|
view.setColumns(columns".$id.");
|
|
chart.draw(view, options);
|
|
}
|
|
}
|
|
}
|
|
|
|
google.visualization.events.addListener(chart, 'select', showHideSeries".$id.");
|
|
";
|
|
*/
|
|
|
|
$js .= "
|
|
chart.draw(data, options);
|
|
}
|
|
|
|
$(window).resize(function(){
|
|
".$fName."();
|
|
|
|
});
|
|
|
|
$('a[data-toggle=\"tab\"]').on('shown.bs.tab', function (e) {
|
|
".$fName."();
|
|
});
|
|
|
|
";
|
|
|
|
e107::js('footer','https://www.google.com/jsapi');
|
|
e107::js('footer-inline', $js);
|
|
|
|
|
|
return "<div class='e-graph e-chart' id='".$id."' style='width: ".$width."; height: ".$height."px;'></div>";
|
|
|
|
}
|
|
|
|
|
|
e107::js('core','chart/ChartNew.js','jquery');
|
|
|
|
$js = "var ChartData = ".$this->getData()."\n";
|
|
$js .= 'var ChartOptions = '.$this->getOptions();
|
|
$js .= ";\n";
|
|
|
|
switch ($this->type)
|
|
{
|
|
|
|
case 'bar':
|
|
|
|
$js .= 'var myLine = new Chart(document.getElementById("'.$id.'").getContext("2d")).Bar(ChartData, ChartOptions);';
|
|
break;
|
|
|
|
case 'polar':
|
|
case 'pie':
|
|
case 'radar':
|
|
//TODO
|
|
break;
|
|
|
|
case 'doughnut':
|
|
$js .= 'var myDoughnut = new Chart(document.getElementById("'.$id.'").getContext("2d")).Doughnut(ChartData, ChartOptions);';
|
|
break;
|
|
|
|
default:
|
|
case 'line':
|
|
|
|
$js .= '
|
|
|
|
var myLine = new Chart(document.getElementById("'.$id.'").getContext("2d")).Line(ChartData, ChartOptions);
|
|
|
|
';
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
|
|
// Auto-resize the canvas. //TODO Get it working with multiple instances.
|
|
e107::js('footer-inline', "
|
|
var c = $('#".$id."');
|
|
var ct = c.get(0).getContext('2d');
|
|
var container = $(c).parent();
|
|
|
|
//Run function when browser resizes
|
|
$(window).resize( respondCanvas );
|
|
|
|
function respondCanvas(){
|
|
c.attr('width', $(container).width() ); //max width
|
|
c.attr('height', $(container).height() ); //max height
|
|
|
|
//Call a function to redraw other content (texts, images etc)
|
|
}
|
|
|
|
//Initial call
|
|
respondCanvas();
|
|
");
|
|
|
|
|
|
e107::js('footer-inline',$js);
|
|
|
|
return '<canvas class="e-graph e-chart" id="'.$id.'" height="'.$height.'" width="'.$width.'" >HTML5 Canvas not supported.</canvas>';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|