0๐
<?php
if( $_SERVER['REQUEST_METHOD']=='POST' ){
/*
Ignore the db connection and the specific SQL queries
- these, obviously, are pertinent to my system and not
the real one.
Use own db connection
*/
set_include_path('c:/wwwroot/dbo/');
require 'db-conn-details.php';
$dbname='movies';
require 'mysqli-conn.php';
/*
To emulate how one MIGHT use a single script to serve ALL
chart data simply by using a parameter in the AJAX request.
Use own SQL queries to query for each button click
$_POST['chart'] is sent by the ajax request and uses the
dataset attribute `id` -> `data-id=1` etc
I used a db of movies to supply suitable data to populate
various charts - the data does not bear any resemblance to
whatever datasets you are using.
*/
switch( intval( $_POST['chart'] ) ){
case 1:$sql='select `title`,`rating` from `vwmovies` where `year`=1970 and `rating` > 0 limit 10';break;
case 2:$sql='select `title`,`rating` from `vwmovies` where `year`=1980 and `rating` > 0 limit 10';break;
case 3:$sql='select `title`,`rating` from `vwmovies` where `year`=1993 and `rating` > 0 limit 10';break;
case 4:$sql='select `title`,`rating` from `vwmovies` where `year`=2005 and `rating` > 0 limit 10';break;
case 5:$sql='select `title`,`rating` from `vwmovies` where `year`=2015 and `rating` > 0 limit 10';break;
}
$res=$db->query( $sql );
$tmp=[];
while( $rs=$res->fetch_object()){
$tmp[]=[
'name' => $rs->title,
'rating' => $rs->rating
];
}
exit( json_encode( $tmp ) );
}
?>
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title>Omid Charts</title>
<style>
:root{
--ptop:0;
--pleft:0;
}
body *{
font-family:monospace;
}
div{
margin:1rem;
}
#tabs{
height:calc( 500px + 4rem );
}
#tabs > div {
border:1px solid black;
background:whitesmoke;
display:none;
}
#tabs > div > div{
width: 75%;
height: 500px;
display: inline-block;
}
canvas{
margin:auto;
float:none;
}
.visible{
display:block!important;
}
.visible:before{/* red rectangle, top left (TL) */
position:absolute;
top:var(--ptop);
left:var(--pleft);
content:'Chart 'attr(data-id)': 'attr(data-label);
padding:0.5rem 1rem;
background:red;
color:white;
border-right:1px solid black;
border-bottom:1px solid black;
border-top:1px solid black;
}
button{
padding:0.5rem;
}
</style>
<script src='//canvasjs.com/assets/script/canvasjs.min.js'></script>
<script src='//cdn.jsdelivr.net/npm/chart.js@2.8.0'></script>
<script src='//cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js'></script>
<script>
document.addEventListener('DOMContentLoaded',function(){
/* The container for the chart tabs */
let box=document.getElementById('tabs').getBoundingClientRect();
/* modify the :root variables to aid positioning of chart identifier ( red-rectangle, TL ) */
let root=document.documentElement;
root.style.setProperty( '--ptop', box.top+'px' );
root.style.setProperty( '--pleft', 'calc( '+box.left+' + 1rem )px' );
/* The url to send ajax requests to */
/*
Rather than separate scripts to handle the request
a single script could be used but use a parameter
in the request to determine which SQL query to run.
See above PHP code...
*/
const URL=location.href;
/* The method used for the AJAX request */
const METHOD='post';
/* className assigned to a DIV/panel to ensure it is visible */
const VIZ='visible';
/* utility to find all chart containers and hide them and then reveal specific chart */
const showhidetabs=function(n){
Array.from( document.querySelectorAll( '#tabs > div' ) ).forEach( div=>{
if( div.classList.contains( VIZ ) )div.classList.remove( VIZ )
});
n.classList.add( VIZ );
};
/* chart builder */
const buildchart=function( canvas, label ){
let ctxt=canvas.getContext('2d');
let div=canvas.parentNode.parentNode;
let id=div.dataset.id;
/* issue query to PHP server */
/* return JSON format data */
$.ajax({
url:URL,
method:METHOD,
data:{
task:'fetch-data',
label:label,
chart:id
},
success:function( data ){
let json=JSON.parse( data );
let labels=[];
let results=[];
if( !div.hasAttribute('data-label') ){
div.dataset.label=label;
}
json.forEach( obj=>{ // names as per column names in db query results
labels.push( obj.name );
results.push( obj.rating );
});
let chartdata = {
labels:labels,
datasets:[
{
label:label,
backgroundColor: 'rgba(200, 200, 200, 0.75)',
borderColor: 'rgba(200, 200, 200, 0.75)',
hoverBackgroundColor: 'rgba(200, 200, 200, 1)',
hoverBorderColor: 'rgba(200, 200, 200, 1)',
data:results
}
]
};
let barGraph=new Chart( ctxt, {
type:'horizontalBar',
data:chartdata
});
},
error:function( err ){
console.info( err )
}
});
};
/* click event handler that hides other charts and fetches data to build new chart */
const bttnclickhandler=function(e){
// find the chart container
let div=document.querySelector('#tabs > div[ data-id="'+this.dataset.id+'" ]');
// find the canvas
let canvas=div.querySelector('canvas');
// find the button text - to be used in the chart as the label
let label=this.innerHTML;
// call the methods above.
showhidetabs.call( this, div );
buildchart.call( this, canvas, label );
};
/* assign event handler to each button */
Array.from( document.querySelectorAll( '#content > button' ) ).forEach( bttn=>{
bttn.addEventListener('click', bttnclickhandler )
})
});
</script>
</head>
<body>
<!--
The HTML markup is basically the same as per the question except that
it now validates correctly as it is properly nested - which I believe
caused many issues in the original.
It has been simplified but retains sufficient attributes to allow
easy targeting via Javascript and also styling via CSS without
unneccessary "bloat"
-->
<div id='content'>
<button data-id=1>Top 15 Caller Employee</button>
<button data-id=2>Top 15 Called Employee</button>
<button data-id=3>Top Called Filiale</button>
<button data-id=4>Most calls outside of Germany</button>
<button data-id=5>Calls outside of Germany</button>
<!-- what does this do? -->
<div id='cover'></div>
<!--
The `data-id` attributes are used by AJAX function
to help determine which SQL query to run.
-->
<div id='tabs'>
<div data-id='1'>
<div>
<canvas></canvas>
</div>
</div>
<div data-id='2'>
<div>
<canvas></canvas>
</div>
</div>
<div data-id='3'>
<div>
<canvas></canvas>
</div>
</div>
<div data-id='4'>
<div>
<canvas></canvas>
</div>
</div>
<div data-id='5'>
<div>
<canvas></canvas>
</div>
</div>
</div>
</div>
</body>
</html>
- Chartjs-How can I show extra data in chart.js tooltip?
- Chartjs-Combine\Merge Same Label in Pie Chart
Source:stackexchange.com