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.
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.
Here is my code
HTML
<div class="layout layout-stack-sm layout-main-right">
<div class="col-sm-3 layout-sidebar">
<div class="col-sm-12">
<ul id="myTab" class="nav nav-layout-sidebar nav-stacked">
<li class="active">
<a href="#quick-stats" data-toggle="tab">
<i class="fa fa-th"></i>
Quick Stats
</a>
</li>
<li>
<a href="#engagement-graph" data-toggle="tab">
<i class="fa fa-bar-chart-o"></i>
Engagement graph
</a>
</li>
</ul>
</div>
</div> <!-- layout sidebar -->
<div class="col-sm-9 layout-main">
<div class="tab-content stacked-content">
<div class="tab-pane fade in active" id="quick-stats">
Some content
</div>
<div class="tab-pane fade" id="engagement-graph">
<div id="myMoodPage">
<div class="graph" id="graph">
</div>
</div>
</div>
</div>
</div>
Loading graph on document ready
<script type="text/javascript" src="https://www.google.com/jsapi">
</script>
<script type="text/javascript">
google.load("visualization", "1", {packages: ["corechart"]});
$(document).ready(function () {
$('#myMoodPage').myMood({
graphDataUrl: '<?php echo $this->url('my_mood/mood_graph_data'); ?>',
graphData: <?php echo $graphData; ?>,
titles: ['<?php echo $this->translate('time'); ?>', '<?php echo $this->translate('mood'); ?>', '<?php echo $this->translate('avg'); ?>']
});
});
function updatePageCharts() {
$('#myMoodPage').myMood('loadGraph');
}
$("a[href='#engagement-graph']").on('shown.bs.tab', function (e) {
google.load('visualization', '1', {
packages: ['corechart'],
callback: drawChart
});
});
</script>
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)
(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) > 0) {
this.last30Trend.find(".up").show();
this.last30Trend.addClass("incr")
}
if (Number(data.last30.trend) < 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) > 0) {
this.weekTrend.find(".up").show();
this.weekTrend.addClass("incr")
}
if (Number(data.week.trend) < 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 = '<div style="border-radius: 2px; padding: 10px; color: #ffffff; font-weight: bold; background-color: #9c3b8a;">';
if (moodData[i].event != null) {
moodText += moodData[i].event + " "
}
moodText += moodData[i].mood;
if (moodData[i].comment) {
moodText += "<br>" + moodData[i].comment
}
moodText += "</div>";
var avgText = '<div style="border-radius: 2px; padding: 10px; color: #ffffff; font-weight: bold; background-color: #15426c;">';
if (moodData[i].event != null) {
avgText += moodData[i].event + " "
}
avgText += moodData[i].avg;
if (moodData[i].publicComment) {
avgText += "<br>" + moodData[i].publicComment
}
avgText += "</div>";
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);
I tried reloading the graph like this, but it didn't work
$("a[href='#engagement-graph']").on('shown.bs.tab', function (e) {
google.load('visualization', '1', {
packages: ['corechart'],
callback: drawChart
});
});
Screenshot in 2 different situation
Loading on active tab pane
Loading on hidden tab pane