From 78eb4049a1496f60d3f17f88d42112d4398752aa Mon Sep 17 00:00:00 2001 From: Daniel Cothran <daniel@andile.co> Date: Sat, 14 Oct 2017 17:25:19 -0500 Subject: [PATCH] Google Charts redraw charts after resize event --- modules/charts_google/js/charts_google.js | 152 ++++++++++++++++------ 1 file changed, 111 insertions(+), 41 deletions(-) diff --git a/modules/charts_google/js/charts_google.js b/modules/charts_google/js/charts_google.js index 20413e2..b7d7f23 100644 --- a/modules/charts_google/js/charts_google.js +++ b/modules/charts_google/js/charts_google.js @@ -2,58 +2,128 @@ * @file * JavaScript integration between Google and Drupal. */ + (function ($) { 'use strict'; + Drupal.googleCharts = Drupal.googleCharts || {'charts': []}; + + /** + * Behavior to initialize Google Charts. + * + * @type {{attach: Drupal.behaviors.chartsGooglecharts.attach}} + */ Drupal.behaviors.chartsGooglecharts = { attach: function (context, settings) { + // Load Google Charts API. google.charts.load('current', {packages: ['corechart']}); - $('.charts-google').each(function (param) { - var chartId = $(this).attr('id'); - $('#' + chartId).once().each(function () { - if ($(this).attr('data-chart')) { - var dataTable = $(this).attr('data-chart'); - var googleChartOptions = $(this).attr('google-options'); - var googleChartType = $(this).attr('google-chart-type'); - google.charts.setOnLoadCallback(draw(googleChartType, dataTable, googleChartOptions)); - } + $(context).find('body').once('load-google-charts').each(function () { + // Re-draw charts if viewport size has been changed. + $(window).on('resize', function () { + Drupal.googleCharts.waitForFinalEvent(function () { + // Re-draw Google Charts. + Drupal.googleCharts.drawCharts(true); + }, 200, 'reload-google-charts'); }); - function draw(chartType, dataTable, googleChartOptions) { - - return function () { - var data = google.visualization.arrayToDataTable(JSON.parse(dataTable)); - var googleChartTypeObject = JSON.parse(chartType); - var googleChartTypeFormatted = googleChartTypeObject.type; - var chart; - switch (googleChartTypeFormatted) { - case 'BarChart': - chart = new google.visualization.BarChart(document.getElementById(chartId)); - break; - case 'ColumnChart': - chart = new google.visualization.ColumnChart(document.getElementById(chartId)); - break; - case 'DonutChart': - chart = new google.visualization.PieChart(document.getElementById(chartId)); - break; - case 'PieChart': - chart = new google.visualization.PieChart(document.getElementById(chartId)); - break; - case 'ScatterChart': - chart = new google.visualization.ScatterChart(document.getElementById(chartId)); - break; - case 'AreaChart': - chart = new google.visualization.AreaChart(document.getElementById(chartId)); - break; - case 'LineChart': - chart = new google.visualization.LineChart(document.getElementById(chartId)); - } - chart.draw(data, JSON.parse(googleChartOptions)); - }; + }); + + // Draw Google Charts. + Drupal.googleCharts.drawCharts(); + } + }; + + /** + * Helper function to draw Google Charts. + */ + Drupal.googleCharts.drawCharts = function (reload) { + $('.charts-google').each(function () { + var chartId = $(this).attr('id'); + var $charts; + + if (reload === true) { + $charts = $('#' + chartId); + } + else { + $charts = $('#' + chartId).once('draw-google-charts'); + } + + $charts.each(function () { + var $chart = $(this); + + if ($chart.attr('data-chart')) { + var data = $chart.attr('data-chart'); + var options = $chart.attr('google-options'); + var type = $chart.attr('google-chart-type'); + + google.charts.setOnLoadCallback(Drupal.googleCharts.drawChart(chartId, type, data, options)); } }); + }); + }; + /** + * Helper function to draw a Google Chart. + */ + Drupal.googleCharts.drawChart = function (chartId, chartType, dataTable, googleChartOptions) { + return function () { + var data = google.visualization.arrayToDataTable(JSON.parse(dataTable)); + var options = JSON.parse(googleChartOptions); + var googleChartTypeObject = JSON.parse(chartType); + var googleChartTypeFormatted = googleChartTypeObject.type; + var chart; - } + switch (googleChartTypeFormatted) { + case 'BarChart': + chart = new google.visualization.BarChart(document.getElementById(chartId)); + break; + case 'ColumnChart': + chart = new google.visualization.ColumnChart(document.getElementById(chartId)); + break; + case 'DonutChart': + chart = new google.visualization.PieChart(document.getElementById(chartId)); + break; + case 'PieChart': + chart = new google.visualization.PieChart(document.getElementById(chartId)); + break; + case 'ScatterChart': + chart = new google.visualization.ScatterChart(document.getElementById(chartId)); + break; + case 'AreaChart': + chart = new google.visualization.AreaChart(document.getElementById(chartId)); + break; + case 'LineChart': + chart = new google.visualization.LineChart(document.getElementById(chartId)); + } + + chart.draw(data, options); + }; }; + + /** + * Helper function to run a callback function once when triggering an event + * multiple times. + * + * Example usage: + * @code + * $(window).resize(function () { + * Drupal.googleCharts.waitForFinalEvent(function(){ + * alert('Resize...'); + * }, 500, "some unique string"); + * }); + * @endcode + */ + Drupal.googleCharts.waitForFinalEvent = (function () { + var timers = {}; + return function (callback, ms, uniqueId) { + if (!uniqueId) { + uniqueId = "Don't call this twice without a uniqueId"; + } + if (timers[uniqueId]) { + clearTimeout(timers[uniqueId]); + } + timers[uniqueId] = setTimeout(callback, ms); + }; + })(); + }(jQuery)); -- GitLab