Chartjs-Second tab doesn't show the chart . Can anybody see why?

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>

Leave a comment