title: redraw google charts on hidden bootstrap tab pane
body: <p>I am using google scatter chart in my web app and it loads on document ready. I recently did some restructuring and trying to divide the page content in different bootstrap tabs. </p>
  
  <p>If I load the graph on the active tab pane it work fine and the width, height parameters of the graph is correct. However if I shift the graph to a hidden tab the graph doesn't load properly with the parameters passed on the function (specially width and height). At the moment I am calling the graph on document ready. </p>
  
  <p>Here is my code</p>
  
  <p>HTML</p>
  
  <pre><code>&lt;div class="layout layout-stack-sm layout-main-right"&gt;
      &lt;div class="col-sm-3 layout-sidebar"&gt;
          &lt;div class="col-sm-12"&gt;
              &lt;ul id="myTab" class="nav nav-layout-sidebar nav-stacked"&gt;
                  &lt;li class="active"&gt;
                      &lt;a href="#quick-stats" data-toggle="tab"&gt;
                          &lt;i class="fa fa-th"&gt;&lt;/i&gt;
                          &amp;nbsp;&amp;nbsp;Quick Stats
                      &lt;/a&gt;
                  &lt;/li&gt;
                  &lt;li&gt;
                      &lt;a href="#engagement-graph" data-toggle="tab"&gt;
                          &lt;i class="fa fa-bar-chart-o"&gt;&lt;/i&gt;
                          &amp;nbsp;&amp;nbsp;Engagement graph
                      &lt;/a&gt;
                  &lt;/li&gt;
              &lt;/ul&gt;
          &lt;/div&gt;
      &lt;/div&gt;  &lt;!-- layout sidebar --&gt;
  
      &lt;div class="col-sm-9 layout-main"&gt;
          &lt;div class="tab-content stacked-content"&gt;
              &lt;div class="tab-pane fade in active" id="quick-stats"&gt;
                  Some content   
              &lt;/div&gt;
              &lt;div class="tab-pane fade" id="engagement-graph"&gt;
                  &lt;div id="myMoodPage"&gt;
                  &lt;div class="graph" id="graph"&gt;
                  &lt;/div&gt;
              &lt;/div&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>Loading graph on document ready</p>
  
  <pre><code>&lt;script type="text/javascript" src="https://www.google.com/jsapi"&gt;
  &lt;/script&gt;
  &lt;script type="text/javascript"&gt;
      google.load("visualization", "1", {packages: ["corechart"]});
  
      $(document).ready(function () {
          $('#myMoodPage').myMood({
              graphDataUrl: '&lt;?php echo $this-&gt;url('my_mood/mood_graph_data'); ?&gt;',
              graphData: &lt;?php echo $graphData; ?&gt;,
              titles: ['&lt;?php echo $this-&gt;translate('time'); ?&gt;', '&lt;?php echo $this-&gt;translate('mood'); ?&gt;', '&lt;?php echo $this-&gt;translate('avg'); ?&gt;']
          });
      });
  
      function updatePageCharts() {
          $('#myMoodPage').myMood('loadGraph');
      }
  
      $("a[href='#engagement-graph']").on('shown.bs.tab', function (e) {
          google.load('visualization', '1', {
              packages: ['corechart'],
              callback: drawChart
          });
      });
  
  &lt;/script&gt;
  </code></pre>
  
  <p>This is my main JS file where I am defining the graph parameters and other things (which are not actually relevant for this question, but just for the sake of completeness I am posting the whole function)</p>
  
  <pre><code>(function ($) {
      $.widget("ui.myMood", {
          options: {
              graphDataUrl: "",
              graphData: {},
              titles: ["time", "mood", "avg"]
          },
          _create: function () {
              var self = this;
              this.periodSelect = this.element.find('select[name="period"]');
              this.questionSelect = this.element.find('select[name="question"]');
              this.graphContainer = this.element.find(".statistics");
              this.atStart = this.element.find("#atStart .value");
              this.highest = this.element.find("#highest .value");
              this.lowest = this.element.find("#lowest .value");
              this.current = this.element.find("#current .value");
              this.last30 = this.element.find("#last30 .value");
              this.last30Trend = this.element.find("#last30");
              this.week = this.element.find("#week .value");
              this.weekTrend = this.element.find("#week");
              this.graphId = "graph";
              this.selectedFilterName = this.options.titles[2];
              this.periodSelect.change(function () {
                  self.loadGraph()
              });
              this.questionSelect.change(function () {
                  self.loadGraph();
                  self.selectedFilterName = self.questionSelect.find("option:selected").text()
              });
              this.setGraphData(this.options.graphData);
              return this
          },
          loadGraph: function () {
              var self = this;
              var data = {
                  period: self.periodSelect.val(),
                  question: self.questionSelect.val()
              };
              var success = function (data) {
                  self.setGraphData(data)
              };
              $.ajax({
                  type: "POST",
                  url: self.options.graphDataUrl,
                  data: data,
                  success: success
              })
          },
          setGraphData: function (data) {
              var self = this;
              this.atStart.text(data.atStart);
              this.highest.text(data.highest);
              this.lowest.text(data.lowest);
              this.current.text(data.current);
              this.last30.text(data.last30.val);
              this.last30Trend.find(".up, .down").hide();
              this.last30Trend.removeClass("incr");
              this.last30Trend.removeClass("decr");
              if (Number(data.last30.trend) &gt; 0) {
                  this.last30Trend.find(".up").show();
                  this.last30Trend.addClass("incr")
              }
              if (Number(data.last30.trend) &lt; 0) {
                  this.last30Trend.find(".down").show();
                  this.last30Trend.addClass("decr")
              }
              this.week.text(data.week.val);
              this.weekTrend.find(".up, .down").hide();
              this.weekTrend.removeClass("incr");
              this.weekTrend.removeClass("decr");
              if (Number(data.week.trend) &gt; 0) {
                  this.weekTrend.find(".up").show();
                  this.weekTrend.addClass("incr")
              }
              if (Number(data.week.trend) &lt; 0) {
                  this.weekTrend.find(".down").show();
                  this.weekTrend.addClass("decr")
              }
              var moodData = data.mood;
              var dataArray = new Array();
              for (i in moodData) {
                  if (moodData[i].avg == null) {
                      moodData[i].avg = undefined
                  }
                  if (moodData[i].mood == null) {
                      moodData[i].mood = undefined
                  }
                  if (moodData[i].team == null) {
                      moodData[i].team = undefined
                  }
                  var moodText = '&lt;div style="border-radius: 2px; padding: 10px; color: #ffffff; font-weight: bold; background-color: #9c3b8a;"&gt;';
                  if (moodData[i].event != null) {
                      moodText += moodData[i].event + " "
                  }
                  moodText += moodData[i].mood;
                  if (moodData[i].comment) {
                      moodText += "&lt;br&gt;" + moodData[i].comment
                  }
                  moodText += "&lt;/div&gt;";
                  var avgText = '&lt;div style="border-radius: 2px; padding: 10px; color: #ffffff; font-weight: bold; background-color: #15426c;"&gt;';
                  if (moodData[i].event != null) {
                      avgText += moodData[i].event + " "
                  }
                  avgText += moodData[i].avg;
                  if (moodData[i].publicComment) {
                      avgText += "&lt;br&gt;" + moodData[i].publicComment
                  }
                  avgText += "&lt;/div&gt;";
                  var row = [new Date(moodData[i].time * 1000), Number(moodData[i].mood), moodText, Number(moodData[i].avg), avgText, false];
                  dataArray.push(row)
              }
              if (google) {
                  drawChart()
              } else {
                  google.setOnLoadCallback(drawChart)
              }
  
              function drawChart() {
                  var dataTable = new google.visualization.DataTable();
                  dataTable.addColumn("date", self.options.titles[0]);
                  dataTable.addColumn("number", self.options.titles[1]);
                  dataTable.addColumn({
                      type: "string",
                      role: "tooltip",
                      p: {
                          html: true
                      }
                  });
                  dataTable.addColumn("number", self.selectedFilterName);
                  dataTable.addColumn({
                      type: "string",
                      role: "tooltip",
                      p: {
                          html: true
                      }
                  });
                  dataTable.addColumn({
                      type: "boolean",
                      role: "certainty"
                  });
                  dataTable.addRows(dataArray);
                  var dataView = new google.visualization.DataView(dataTable);
                  var chart = new google.visualization.ScatterChart(document.getElementById(self.graphId));
                  var options = {
                      legend: {
                          position: "bottom"
                      },
                      interpolateNulls: true,
                      chartArea: {
                          left: 25,
                          top: 25,
                          width: '92%',
                          height: '80%'
                      },
                      backgroundColor: "#ffffff",
                      vAxis: {
                          minValue: 0,
                          maxValue: 6,
                          viewWindow: {
                              min: 0,
                              max: 6
                          }
                      },
                      tooltip: {
                          isHtml: true
                      },
                      series: {
                          0: {
                              color: "#9c3b8a",
                              lineWidth: 2,
                              pointSize: 6
                          },
                          1: {
                              color: "#15426c",
                              lineWidth: 1,
                              pointSize: 3
                          }
                      }
                  };
                  chart.draw(dataView, options)
              }
          }
      })
  })(jQuery);
  </code></pre>
  
  <p>I tried reloading the graph like this, but it didn't work</p>
  
  <pre><code>$("a[href='#engagement-graph']").on('shown.bs.tab', function (e) {
          google.load('visualization', '1', {
              packages: ['corechart'],
              callback: drawChart
          });
      });  
  </code></pre>
  
  <p>Screenshot in 2 different situation</p>
  
  <p>Loading on active tab pane
  <img src="https://i.stack.imgur.com/ddUTT.png" alt="enter image description here"></p>
  
  <p>Loading on hidden tab pane
  <img src="https://i.stack.imgur.com/YSXF4.png" alt="enter image description here"></p>