0

I have a google chart timeline that is dynamically updated from a google sheet. I created a custom module 'jsblock' to manage the script, styling and layout of the chart.

To begin with, first I need to get the chart to actually print in the block, which it does not.

jsblock/js/custom.js:

(function ($) {
Drupal.behaviors.jsblock = {

    attach: function (context, settings) {

    google.charts.load('current', {'packages':['corechart', 'controls', 'timeline']});
google.charts.setOnLoadCallback(drawStuff);

function drawStuff() {
  // query against spreadsheet
  var queryString = encodeURIComponent('SELECT A, B, D, E');
  // Test that the variables are added to the queryString as the strings contained within the variables - which they do.
  //alert(queryString);
  // below grabs just data, not header rows
  var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/[chartstrid/gviz/tq?gid=0&headers=1&tq=' + queryString);
  query.send(handleQueryResponse);
}

// handler for query response from spreadsheet
function handleQueryResponse(response) {
  if (response.isError()) {
  alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
    return;
  }
  var data = response.getDataTable();
  // control for date filter
  var datepicker = new google.visualization.ControlWrapper({
    'controlType': 'DateRangeFilter',
    'containerId': 'control4',
    'options': {
      'filterColumnLabel': 'Start',
      'labelStacking': 'horizontal',
      'ui': {
        'cssClass': 'slider'
       }
    }
  });

  var changeTimeline = new google.visualization.ChartWrapper({
     'chartType': 'Timeline',
     'containerId': 'timeline',
     'chartArea': {'left': 55, 'top': 15, 'right': 0, 'bottom': 0},
  });
}

function drawChart(dataTable) {
  var container = document.getElementById('timeline');
  var chart = new google.visualization.Timeline(container);
  var dataTable = new google.visualization.DataTable();
  var options = {
    timeline: { showRowLabels: false, singleColor: '#8d8' }
  };   
  chart.draw(dataTable, options);
      // data and options to be used in drawing the regular table
  var programmaticChart1 = new google.visualization.ChartWrapper({
    'chartType': 'Timeline',
    'containerId': 'programmatic_chart1_div',
    'chartArea': {'left': 55, 'top': 15, 'right': 0, 'bottom': 0}
           //'view': {'columns':[0,2,]}
  });
  // start up the dashboard
  var dashboard = new google.visualization.Dashboard(document.getElementById('programmatic_dashboard_div'));
  //bind the control and the chart to the dashboard
  dashboard.bind(datepicker, programmaticChart1, changeTimeline);
  // Draw the dashboard.
  dashboard.draw(data);  
}

function createCustomHTMLContent(flagURL) {
  console.log('inside custom');
       //
    }
  }
);

jsblock.module:

// Render the chart in the block inside the divs specified by the getElementById calls in the chart code above
<?php

function jsblock_block_info() {
    $blocks = array();
    $blocks['jsblock']['info'] = t('My JS Block');
    return $blocks;
}

function jsblock_block_view($delta = '') {
    $block = array();
    $block['subject'] = t("The title");
    $block['content']['#markup'] = "My content goes here"; 
    $block['content']['#attached']['css'][] = drupal_get_path("module", "jsblock")."/css/styles.css";
    $block['content']['#attached']['js'][] = drupal_get_path("module", "jsblock")."/js/custom.js";
    $block['content']['#attached']['js'] = array(
  'https://www.gstatic.com/charts/loader.js' => array(
    'type' => 'external',
    ),
    );
    $block['content']['#markup'] = "
       <div id=\"content\" class=\"column\"><div class=\"section\">
       <div id=\"timeline\">
       <h2 style=\"padding-left: 2em; min-width: 250px;\"> Technology Product Life Cycle </h2>
       <div id=\"programmatic_dashboard_div\">
          <table class=\"columns\">
             <tr>
                <td>
                    <div id=\"programmatic_chart1_div\" style=\"padding-left: 2em; min-width: 500px;\"></div>
               </td>
            </tr>
            <tr>
                <td>
                    <div id=\"control4\" style=\"padding-left: 2em; min-width: 250px\"></div>
                </td>
            </tr>
         </table>
      </div>
  </div>
</div>";

  return $block;
}

Here's how it's currently rendering:

enter image description here

Here is how it should look:

enter image description here

No console errors in chrome or firefox.

Any help is greatly appreciated!

5
  • If you use single quotes for your HTML strings you don't have to escape all the double quotes. – rooby Oct 9 '17 at 9:42
  • From the looks of it your block is printing correctly but something in the chart JS you wrote isn't correct, which means I don't think that this is a drupal specific question, it's just a google charts question. I can't test it thoroughly because your spreadsheet link is missing, but one thing that stands out is that you never call the draw chart function. You also refer to the containerID 'timeline', which doesn't exist in your block markup. It might just be an omission from your question but you also don't attach the google charts JS and there are some missing closing brackets in your JS. – rooby Oct 9 '17 at 10:21
  • @rooby Thanks for these suggestions. I've updated my code with the timeline div as well as the attached external script. I also checked over the js and I can't find any missing closing brackets. As for calling the draw chart function, you can see the functions chart.draw(dataTable, options); and dashboard.draw(data); near the bottom. I'll mock up a sheet and update the code so there is a better working example. – lane Oct 9 '17 at 12:20
  • Re the closing brackets. I made a custom module with the code you have here and it had a javascript error unexpected ) on the last line. Instead of ); at the end it should be }; }(jQuery)); - If the code in this question is exactly what you are using and you really aren't getting any javascript errors then your javascript would seem to be not running at all. – rooby Oct 9 '17 at 12:28
  • @rooby I scoured the document and found I had a bracket in the wrong place! Thank you for encouraging me to take a closer look! – lane Oct 9 '17 at 16:27
0

At first sight I see 2 problems in your code.

  1. The javascript order, the external file has to load first in order to use the code in your custom javascript.

  2. The custom javascript will never be loaded because you rebuild the complete $block['content']['#attached']['js'] array in the next line.

Change

$block['content']['#attached']['js'][] = drupal_get_path("module", "jsblock")."/js/custom.js";
$block['content']['#attached']['js'] = array(
  'https://www.gstatic.com/charts/loader.js' => array(
    'type' => 'external',
  ),
);

to

$block['content']['#attached']['js'] = array(
  'https://www.gstatic.com/charts/loader.js' => array(
    'type' => 'external',
  ),
  drupal_get_path("module", "jsblock") . "/js/custom.js"
);

Add

Also, if is good practice to use hook_theme to load a template instead of inserting html directly as content markup.

1
  • the order of loading was the final thing keeping my chart from loading. This did it. Thanks for taking the time to provide an answer and for showing me how to add multiple js files into an #attached array! – lane Oct 9 '17 at 16:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.