jQuery UI Tabs and Highcharts display/rendering issue
Asked Answered
L

13

17

Anyone ever used the tabs (jquery-ui-1.8.9) and pie charts from Highcharts 2.1.4 together? To put it simply, I have multiple tabs, where each tab shows a pie chart with different data. The charts DO render to the divs, but when I click on the 2nd tab, the chart somehow shows up 300px to the right of where it's suppose to be. Whenever I zoom in or out of the browser window, the chart goes back to the correction position.

My code:

//Suppose the number tabs are generated based on variable $count, and there are 2 tabs

<script type="text/javascript">

var chart_tab_<?=count?>;

$(document).ready(function() {
    chart_tab_<?=count?> = new Highcharts.Chart({
      chart: {
         renderTo: 'chart_tab_<?=count?>',
         // blah blah
      }

<body>
    <div id="chart_tab_<?=count?>"></div>
</body>

Again, the chart renders, but on the 2nd tab the display is bugged.

Update: I know that this KIND OF fixes the problem:

<script type="text/javascript"> 
   $(document).ready(function() {
      $( "#tabs" ).tabs({
          cookie: { expires: 1 }
      });
      $( "#tabs" ).tabs({
          select: function(event, ui) { window.location.reload(); }
      });
   });

But it's really crappy because the page has to be reloaded every time a user clicks on the tab. Any ideas would be great.

Lorenz answered 16/4, 2011 at 16:54 Comment(2)
Have you seend simple example: docs.highcharts.com/#faq$jquery-ui-tab ?Inexpiable
see https://mcmap.net/q/328824/-why-are-bootstrap-tabs-displaying-tab-pane-divs-with-incorrect-widths-when-using-highchartsRogatory
A
12

This is my solution (only tested in Safari and Firefox). It works great if you want to load the chart into a hidden tab on a page with flexible width. The chart resize if the browser window is resized.

In the chart settings, set the width of the chart from the tab that opens on page load (using jQuery to get the width):

   var chart = new Highcharts.Chart({
     chart: {
       renderTo: 'container',
       type: 'column',
       width: $('#tab-1').width()
     },
     ....

The following function adjusts width if the browser window is resized. 500 is the height. This is done automatically if the width is not specified in the chart options.

$(window).resize(function() {
   chart.setSize($('#chart_tab').width(),500);       
});
Adrenaline answered 9/12, 2012 at 17:59 Comment(0)
A
6

Modification needed in order to make Highcharts work in hidden jQuery tabs. By default, jQuery sets display: none to hidden tabs, but with this approach Highcharts is unable to get the true width and height of the element. So instead, we position it absolutely and move it away from the viewport.

 <style type="text/css">
.ui-tabs .ui-tabs-hide {
     position: absolute;
     top: -10000px;
     display: block !important;
}           
 </style>

adding example: http://www.highcharts.com/studies/jquery-ui-tabs.htm

Alainealair answered 7/4, 2012 at 18:26 Comment(3)
Does this work with J-Query 1.81 or later? I can't find the class .ui-tabs-hide being used from FireBug.Susi
It doesn't appear to. In version 1.9 the tab widget appears to output an inline style display: none. I'm not yet sure how to overcome that.Christianize
Doesn't work in 1.11. The .ui-tabs-hide class doesn't exist.Frech
G
4

The second chart may be off because it sounds like it is hidden when you draw it. Try to draw the chart upon selection.

Here is some pseudo code to give you an idea of what I imagine. This is not tested.

$("#tabs").tabs({
  select: function(event, ui) {
     var chart = new Highcharts.Chart({
      chart: {
       renderTo: ui.panel.id,
       // blah blah
      }
     });

  }
});
Gellman answered 27/4, 2011 at 15:19 Comment(1)
Warning. This solution is a good idea but needs to be improved to not rebuild the chart whenever the tab is clicked.Avalokitesvara
R
3

You should manually trigger resize event

$(window).trigger('resize');
Raseta answered 10/2, 2014 at 20:50 Comment(1)
#16217222Mendelssohn
S
2

The best solution is in callback function of tabs or when click on each tab, reflow highchart. Look at it:

Chart.reflow and this link jsfiddle and also this code that you have add in tab callback:

$('#chart-1').highcharts().reflow();
Suffice answered 16/5, 2014 at 18:53 Comment(1)
Reflow works fine, but i have datalabels on my pie and that gets messed up because that does not get adjusted.Capricorn
Q
1

Smaller workaround is using a static width for your charts (if you know what it should be) in CSS-

.tab-pane { width: 1200px; }
Quantic answered 21/8, 2012 at 20:3 Comment(0)
S
0

I had a jQuery accordion that was opening with garbled charts... this was my solution:

first is stuffed the charts in a global: window.myNamespace.charts.#{container_id}, and then in my accordion i do this:

$('#my-accordion').accordion
  ...,
  change: () ->
    chartId = ui.newContent.find('.highcharts-container').parent().attr('id')
    window.myNamespace.charts[chartId].setSize(248,220) if chartId?

the above is coffeescript, but it should be easy enough to translate...

basically i'm calling setSize on the chart to set it to the size it already is... this has the effect of cleaning up the chart after it opens... which i'll admit is just a workaround... ideally highcharts fixes the bug and uses the size i'm giving them instead of trying to calculate the size from a hidden element

Scorpius answered 11/4, 2012 at 14:33 Comment(0)
Q
0

Hi see my fiddle jsfiddle

...
$("#tabs").tabs();
var ids = ['chart-1', 'chart-2', 'chart-3'];
for (var i = 0, j = ids.length; i < j; i++) {
    if ((container = $('#'+ids[i])).size()) {
        if (container.width()==0) {
            container.width(container.actual('width'));   
        }

        oclone = $.extend({}, options);
        oclone.chart.renderTo = ids[i];
        new Highcharts.Chart(oclone);
    }

}
...
Quinnquinol answered 1/2, 2013 at 9:39 Comment(0)
C
0

I had a similar issue in that my charts were rendering on the client with zero width whenever the chart was on a tab that was not activated by default. This answer was inspired by ojreadmore's answer. Instead of using the document ready event of jQuery to initialize your highchart, you should instead use the activate event of your the tab your chart is on. This has the added benefit of doing the snazzy chart animation each time the user clicks the tab.

Instead of:

$(document).ready(function() { 
    var chart1 = new Highcharts.Chart({
        chart: {
            renderTo: 'container',
            type: 'bar'
        },
        title: {
            text: 'Fruit Consumption'
        },
        xAxis: {
            categories: ['Apples', 'Bananas', 'Oranges']
        },
        yAxis: {
            title: {
                text: 'Fruit eaten'
            }
        },
        series: [{
            name: 'Jane',
            data: [1, 0, 4]
        }, {
            name: 'John',
            data: [5, 7, 3]
        }]
    });
});​

Use:

$('#tabcontainer').on('tabsactivate', function (event, ui) { 
    var chart1 = new Highcharts.Chart({
        chart: {
            renderTo: 'container',
            type: 'bar'
        },
        title: {
            text: 'Fruit Consumption'
        },
        xAxis: {
            categories: ['Apples', 'Bananas', 'Oranges']
        },
        yAxis: {
            title: {
                text: 'Fruit eaten'
            }
        },
        series: [{
            name: 'Jane',
            data: [1, 0, 4]
        }, {
            name: 'John',
            data: [5, 7, 3]
        }]
    });
});​
Christianize answered 6/2, 2013 at 3:56 Comment(0)
S
0

jQuery UI 1.9+ changed the way tabs are hidden, you should set your own classes when activating tabs this way:

$('#tabs').tabs({
  beforeActivate: function (event, ui) {
    $(ui.oldPanel).addClass('ui-tabs-hide');
    $(ui.newPanel).removeClass('ui-tabs-hide');
  }
});

combined with the following CSS:

.ui-tabs-hide { 
  display: block !important; 
  height: 0!important; 
  width: 0!important; 
  border:none!important; 
}

This will also fix any Flash embedded object not loading properly in hidden tabs.

Sidelight answered 8/2, 2013 at 17:51 Comment(0)
J
0

I ran into same problem, the reflow() method works for me. I grasp the corresponding chart by access the global Highcharts variable. Here the order of charts is order of tabs.

<script type="text/javascript">
    $(function () {
        $("#tabs").tabs({
            show: function (event, ui) {
                var chart = Highcharts.charts[ui.index];
                if (chart != null) {
                    chart.reflow();
                }
            }
        });
    });
</script>
Jocularity answered 1/7, 2014 at 8:45 Comment(0)
S
0

add class="chart" to all highcharts containers inside tabs.

add this jQuery code:

jQuery(document).on( 'shown.bs.tab', 'a[data-toggle="tab"]', function () { 
    $( '.chart' ).each(function() { 
        $(this).highcharts().reflow();
    });
})
Smolt answered 3/6, 2016 at 21:3 Comment(0)
V
0

This worked for me after adding the class name (contains-chart) in the tabs

jQuery(document).on('shown.bs.tab', 'a[data-toggle="tab"]', function (e) { // on tab selection event
            jQuery(".contains-chart").each(function () { // target each element with the .contains-chart class
                var chart = jQuery(this).highcharts(); // target the chart itself
                chart.reflow() // reflow that chart
            }
Veal answered 29/7, 2017 at 2:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.