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