Skip to content

Commit 7f1dc5c

Browse files
committed
Create tablepress_chartjs.php
Initual commit. Need Documentation
1 parent 21b8626 commit 7f1dc5c

1 file changed

Lines changed: 356 additions & 0 deletions

File tree

tablepress_chartjs.php

Lines changed: 356 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,356 @@
1+
<?php
2+
/*
3+
Plugin Name: TablePress Extension: Chart.js
4+
Plugin URI: https://github.com/developarts/tablepress_chartjs
5+
Description: Extension for TablePress to create a responsive chart based on the data in a TablePress table.
6+
Version: 0.1
7+
Author: Alejandro García
8+
Author URI: https://developarts.com
9+
License: GPL
10+
*/
11+
12+
// Prohibit direct script loading.
13+
defined('ABSPATH') || die('No direct script access allowed!');
14+
15+
/*
16+
* Initialize the TablePress chartjs Extension.
17+
*/
18+
add_action('tablepress_run', ['TablePress_Chartjs', 'init']);
19+
20+
/**
21+
* Class that contains the TablePress chartjs Extension functionality.
22+
*
23+
* @author Per Soderlind, Tobias Bäthge
24+
*
25+
* @since 0.1
26+
*/
27+
class TablePress_Chartjs
28+
{
29+
/**
30+
* Version number of the Extension.
31+
*
32+
* @since 0.1
33+
*
34+
* @var string
35+
*/
36+
protected static $version = '0.1';
37+
38+
/**
39+
* Available Shortcode attributes, without the `chartjs_` prefix.
40+
*
41+
* @since 0.2
42+
*
43+
* @var array
44+
*/
45+
protected static $shortcode_attributes = [
46+
'low' => null,
47+
'high' => null,
48+
'width' => '',
49+
'height' => '',
50+
'chart' => 'line',
51+
'showline' => true,
52+
'showarea' => false,
53+
'showpoint' => true,
54+
'linesmooth' => true,
55+
'aspect_ratio' => '3:4',
56+
'horizontal' => false,
57+
'stack' => false,
58+
'animation' => false,
59+
'label_offset' => false,
60+
'chart_padding' => false,
61+
'donut_width' => false,
62+
'label' => 1,
63+
'data' => ''
64+
];
65+
66+
/**
67+
* Mapping of some Shortcode parameters to their chartjsJS equivalent.
68+
*
69+
* @since 0.2
70+
*
71+
* @var array
72+
*/
73+
protected static $attribute_to_js_mapping = [
74+
'low' => 'low',
75+
'high' => 'high',
76+
'showline' => 'showLine',
77+
'showarea' => 'showArea',
78+
'showpoint' => 'showPoint',
79+
'linesmooth' => 'lineSmooth',
80+
'horizontal' => 'horizontalBars',
81+
'stack' => 'stackBars',
82+
'label_offset' => 'labelOffset',
83+
'chart_padding' => 'chartPadding',
84+
'donut_width' => 'donutWidth',
85+
'label' => 'label',
86+
'data' => 'data'
87+
];
88+
89+
90+
/**
91+
* Register necessary plugin filter hooks and the [table-chart] Shortcode.
92+
*
93+
* @since 0.1
94+
*/
95+
public static function init()
96+
{
97+
add_action('wp_enqueue_scripts', [__CLASS__, 'enqueue_scripts_styles']);
98+
add_filter('tablepress_shortcode_table_default_shortcode_atts', [__CLASS__, 'register_shortcode_attributes']);
99+
add_filter('tablepress_table_output', [__CLASS__, 'generate_chart'], 10, 3);
100+
add_shortcode('table-chart', [__CLASS__, 'handle_table_chart_shortcode']);
101+
}
102+
103+
/**
104+
* Handle Shortcode [table-chart id=<ID> /] in `the_content()`.
105+
*
106+
* @since 0.6
107+
*
108+
* @param array $shortcode_atts List of attributes that where included in the Shortcode.
109+
*
110+
* @return string Generated HTML code for the chart with the ID <ID>.
111+
*/
112+
public static function handle_table_chart_shortcode($shortcode_atts)
113+
{
114+
// Generate the attribute query array for the template tag function.
115+
//print_r($shortcode_atts);
116+
$table_query = [
117+
'chartjs' => true,
118+
];
119+
// Pass all parameters to the template tag parameters.
120+
foreach ((array) $shortcode_atts as $attribute => $value) {
121+
// Prepend 'chartjs_' to all Shortcode attributes that the Extension understands.
122+
if (isset(self::$shortcode_attributes[$attribute])) {
123+
$attribute = 'chartjs_'.$attribute;
124+
}
125+
$table_query[$attribute] = $value;
126+
}
127+
128+
//print_r($attribute);
129+
130+
if (function_exists('tablepress_get_table')) {
131+
return tablepress_get_table($table_query);
132+
}
133+
}
134+
135+
/**
136+
* Load chartjs JavaScript and CSS files.
137+
*
138+
* @since 0.1
139+
*/
140+
public static function enqueue_scripts_styles()
141+
{
142+
global $post;
143+
if (is_a($post, 'WP_Post') && has_shortcode($post->post_content, 'tp-chartjs')) {
144+
$dir = plugin_dir_url(__FILE__);
145+
wp_enqueue_script('chartjs', 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js', ['jquery'], '', true);
146+
}
147+
}
148+
149+
/**
150+
* Add the Extension's parameters as valid [table /] Shortcode attributes.
151+
*
152+
* @since 0.1
153+
*
154+
* @param array $default_atts Default attributes for the TablePress [table /] Shortcode.
155+
*
156+
* @return array Extended attributes for the Shortcode.
157+
*/
158+
public static function register_shortcode_attributes($default_atts)
159+
{
160+
//print_r($default_atts);
161+
$default_atts['chartjs'] = false;
162+
foreach (self::$shortcode_attributes as $attribute => $value) {
163+
$default_atts['chartjs_'.$attribute] = $value;
164+
}
165+
return $default_atts;
166+
}
167+
168+
/**
169+
* Generate the HTML and JavaScript code for a chartjs chart, based on the data of the given table.
170+
*
171+
* @since 0.1
172+
*
173+
* @param string $output The generated HTML for the table.
174+
* @param array $table The current table.
175+
* @param array $render_options The render options for the table.
176+
*
177+
* @return string The generated HTML and JavaScript code for the chart.
178+
*/
179+
public static function generate_chart($output, $table, $render_options)
180+
{
181+
182+
if (!$render_options['chartjs']) {
183+
return $output;
184+
}
185+
186+
187+
// Determine/sanitize the chart type and add JS calculation functions.
188+
switch (strtolower($render_options['chartjs_chart'])) {
189+
case 'hbar':
190+
$chart = 'horizontalBar';
191+
break;
192+
case 'line':
193+
default:
194+
$chart = 'line';
195+
break;
196+
}
197+
198+
199+
// Colors
200+
$colors = array(
201+
'rgb(54, 162, 235)', // blue
202+
'rgb(255, 99, 132)', // red
203+
'rgb(255, 159, 64)', // orange
204+
'rgb(255, 205, 86)', // yellow
205+
'rgb(75, 192, 192)', // green
206+
'rgb(153, 102, 255)', // purple
207+
'rgb(201, 203, 207)', // grey
208+
);
209+
210+
// Declare
211+
$datasets = [];
212+
213+
// Labels
214+
$datasets['label']['data'] = array_column($table['data'], $render_options['chartjs_label'] - 1);
215+
$datasets['label']['name'] = $datasets['label']['data'][0];
216+
array_shift($datasets['label']['data']);
217+
$datasets['label']['json'] = json_encode($datasets['label']['data']);
218+
219+
// Data Sets
220+
$sdata = explode(',', $render_options['chartjs_data']);
221+
foreach ($sdata as $key => $value) {
222+
$datasets['sets'][$key]['data'] = array_column($table['data'], $value - 1);
223+
$datasets['sets'][$key]['name'] = $datasets['sets'][$key]['data'][0];
224+
array_shift($datasets['sets'][$key]['data']);
225+
foreach ($datasets['sets'][$key]['data'] as $ckey => $cvalue) {
226+
$datasets['sets'][$key]['data'][$ckey] = self::_maybe_string_to_number($cvalue);
227+
}
228+
$datasets['sets'][$key]['json'] = json_encode($datasets['sets'][$key]['data']);
229+
}
230+
231+
$ckey = str_ireplace('-', '_', $render_options['html_id']);
232+
233+
234+
// DataSets
235+
foreach ($datasets['sets'] as $dkey => $dvalue) {
236+
$datasets['ds'][] = "{
237+
label: '{$dvalue['name']}',
238+
fill: false,
239+
backgroundColor: '{$colors[$dkey]}',
240+
borderColor: '{$colors[$dkey]}',
241+
pointRadius: .1,
242+
pointHoverRadius: 5,
243+
data: {$datasets['sets'][$dkey]['json']},
244+
}";
245+
}
246+
$datasets['rend'] = implode(',', $datasets['ds']);
247+
248+
249+
250+
251+
//print_r($datasets['rend']); die();
252+
253+
$json_chart_options = [];
254+
255+
$chartjs_divtag = "<div style=\"width:100%;\"><canvas id=\"canv_{$ckey}\"></canvas></div>\n";
256+
257+
$chartjs_script = <<<JS
258+
<script type="text/javascript">
259+
jQuery(document).ready(function(){
260+
var config_{$ckey} = {
261+
type: '{$chart}',
262+
data: {
263+
labels: {$datasets['label']['json']},
264+
datasets: [{$datasets['rend']}]
265+
},
266+
options: {
267+
responsive: true,
268+
title: {
269+
display: false,
270+
text: 'Title'
271+
},
272+
tooltips: {
273+
mode: 'index',
274+
intersect: false,
275+
276+
},
277+
hover: {
278+
mode: 'nearest',
279+
intersect: true
280+
},
281+
scales: {
282+
xAxes: [{
283+
display: true,
284+
scaleLabel: {
285+
display: false,
286+
labelString: ''
287+
},
288+
ticks: {
289+
callback: function(value, index, values) {
290+
if (isNaN(value)) {
291+
return value;
292+
} else {
293+
return Intl.NumberFormat().format((value));
294+
}
295+
}
296+
}
297+
}],
298+
yAxes: [{
299+
display: true,
300+
scaleLabel: {
301+
display: false,
302+
labelString: ''
303+
},
304+
ticks: {
305+
callback: function(value, index, values) {
306+
if (isNaN(value)) {
307+
return value;
308+
} else {
309+
return Intl.NumberFormat().format((value));
310+
}
311+
}
312+
}
313+
}]
314+
}
315+
}
316+
};
317+
318+
319+
320+
var cjs_{$ckey} = document.getElementById('canv_{$ckey}').getContext('2d');
321+
window.myLine = new Chart(cjs_{$ckey}, config_{$ckey});
322+
323+
324+
});
325+
</script>
326+
JS;
327+
328+
return $chartjs_divtag.$chartjs_script;
329+
}
330+
331+
/**
332+
* Convert a string to int or float, if it's a numeric string.
333+
*
334+
* @since 0.6
335+
*
336+
* @param string $string String that shall be converted to a number.
337+
*
338+
* @return mixed Possibly converted string.
339+
*/
340+
protected static function _maybe_string_to_number($string)
341+
{
342+
if (empty($string)) {
343+
return 0;
344+
}
345+
346+
if (!is_numeric($string)) {
347+
return $string;
348+
}
349+
350+
if ($string == (int) $string) { // Don't do explicit === check here!
351+
return (int) $string;
352+
} else {
353+
return (float) $string;
354+
}
355+
}
356+
} // class TablePress_Chartjs

0 commit comments

Comments
 (0)