Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Charts and Twitter Bootstrap tabs

I am creating charts through Google Chart Tools, in a webpage using the Twitter Bootstrap framework. There are three types of charts shown - pie, line and column charts, each in individual tab. The chart data is received through Ajax.

Immediately on receiving the data through Ajax, the chart is displayed fine. But if i move to another tab, i.e., another chart, and return back to the first one, the labels in the chart get re-aligned incorrectly.

Included herein are the images that show the problem, before and after tab change: Chart before Tab ChangeChart after Tab Change

This problem occurs for the line and column charts too.

But the problem does not occur if i change the window and then get back, or if i hide and then re-show the charts. It occurs only if i change the tabs.

The mark-up for the tabs is like this:

    <div class="charts-div" style="text-align: center">
            <ul class="nav nav-tabs">
                <li class="active"><a href="#tab-pie" data-toggle="tab">Pie</a></li>
                <li><a href="#tab-line" data-toggle="tab">Line</a></li>
                <li><a href="#tab-column" data-toggle="tab">Columns</a></li>
            </ul>
            <div class="tab-content">
                <div class="tab-pane active" id="tab-pie">
                    <div class="chart pie-chart" id="pie-prt"></div>
                </div>
                <div class="tab-pane" id="tab-line">
                    <div class="chart line-chart" id="line-prt"></div>
                </div>
                <div class="tab-pane" id="tab-column">
                    <div class="chart column-chart" id="column-prt"></div>
                </div>
            </div>

    </div>

Checked in Chrome 22, IE9 and Firefox 12. The result is the same. There is no additional code/event programmed at my end for tab change or tab focus events.

like image 623
mohitp Avatar asked Oct 18 '12 14:10

mohitp


2 Answers

As mohitp has pointed out there are some downsides to davidkonrad's solution. If you still want the charts to remain functional after drawing them, (i.e., tooltips) then you'll have to use Javascript to re-draw the chart.

Given David's example (minus the dummy displacement code) simply move the the chart variable with it's options & datatable intact to a global scope and call the draw method again, you can see an example of this in action here: redraw-google-chart

With David's example, once you have your chart and charting information on a global scope you need to bind the following to the shown event of your tab as so:

$('a[data-toggle="tab"]').on('shown', function (e) {
    chart.draw(data, options);
  })

In my own application I draw my charts based on server-side json requests & there would be instances where I might have many charts on a single page so instead I appended my charts & charting information to global-scoped arrays that could be re-processed client-side as many times as needed.

like image 123
Noz Avatar answered Nov 10 '22 12:11

Noz


Yes, that is very easy reproduceable (nix/various browsers) using your markup and the piechart example at https://google-developers.appspot.com/chart/interactive/docs/quick_start

It seems that the API expands the middle center of the SVG when drawing text to hidden tabs. But I've found a workaround to this : draw the chart/line/bar to a dummy element and move them immediately to the tab container.

altered chart example from above :

function drawChart(id) {
    var data = new google.visualization.DataTable();
    data.addColumn('string', 'Topping');
    data.addColumn('number', 'Slices');
    data.addRows([
      ['Mushrooms', 3],
      ['Onions', 1],
      ['Olives', 2],
      ['Zucchini', 1],
      ['Pepperoni', 2]
    ]);
    var options = {'title':'How Much Pizza I Ate Last Night',
                   'width':400,
                   'height':300};

    var chart = new google.visualization.PieChart(document.getElementById('dummy'));
    chart.draw(data, options);
    $('#dummy').children().remove().appendTo('#'+id);
  }

somewhere in the code add

<div id="dummy"></div>

draw the charts (via dummy to your .. class="chart xxx" id="xxx-prt" )

<script type="text/javascript">
$(document).ready(function() {
    drawChart('pie-prt');
    drawChart('line-prt');
    drawChart('column-prt');
});
</script>

then the charts is rendered the same way on different tabs, here is a fiddle http://jsfiddle.net/sjW6Z/ demonstrating that it actually works :)

like image 1
davidkonrad Avatar answered Nov 10 '22 14:11

davidkonrad