Jon
Jon

Reputation: 3238

Google AnnotatedTimeLine: "Error: Container width is zero. Expecting a valid width."

I need to draw a google.visualization.AnnotatedTimeLine to a <div id="visualization" style="width: 800px; height: 400px; display: none;"></div> div. Google uses the width and height of the div to determine the size of the visualization. Unfortunately Google cannot get the width or height because I am drawing to a display: none; div and thus I get a Error: Container width is zero. Expecting a valid width. error.

The only thing that I can think to do is to draw to a display: block; div and THEN hide the div, but doing so would look a bit odd as the graph would be displayed for a split second. Are there any other options?

Sample code to reproduce:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <title>Google Visualization API Sample</title>
  <script type="text/javascript" src="http://www.google.com/jsapi"></script>
  <script type="text/javascript">
    google.load('visualization', '1', {packages: ['annotatedtimeline']});
    function drawVisualization() {
      var data = new google.visualization.DataTable();
      data.addColumn('date', 'Date');
      data.addColumn('number', 'Sold Pencils');
      data.addColumn('string', 'title1');
      data.addColumn('string', 'text1');
      data.addColumn('number', 'Sold Pens');
      data.addColumn('string', 'title2');
      data.addColumn('string', 'text2');
      data.addRows([
        [new Date(2008, 1 ,1), 30000, null, null, 40645, null, null],
        [new Date(2008, 1 ,2), 14045, null, null, 20374, null, null],
        [new Date(2008, 1 ,3), 55022, null, null, 50766, null, null],
        [new Date(2008, 1 ,4), 75284, null, null, 14334, 'Out of Stock', 'Ran out of stock on pens at 4pm'],
        [new Date(2008, 1 ,5), 41476, 'Bought Pens', 'Bought 200k pens', 66467, null, null],
        [new Date(2008, 1 ,6), 33322, null, null, 39463, null, null]
      ]);

      var annotatedtimeline = new google.visualization.AnnotatedTimeLine(
          document.getElementById('visualization'));
      annotatedtimeline.draw(data, {'displayAnnotations': true});
    }

    google.setOnLoadCallback(drawVisualization);
  </script>
</head>
<body style="font-family: Arial; border: 0 none;">
  <div id="visualization" style="width: 800px; height: 400px; display: none;"></div>
  <input type="button" onclick="toggle();" value="Toggle Visualization">
  <script language="javascript">  
    function toggle() {   
      var ele = document.getElementById('visualization'); 
      if(ele.style.display == "block") {
        ele.style.display = "none";
      } else {
        ele.style.display = "block";
      } 
    }  
  </script> 
</body>
</html>

References:

https://developers.google.com/chart/interactive/docs/gallery/annotatedtimeline

http://code.google.com/apis/ajax/playground/?type=visualization

Upvotes: 4

Views: 1756

Answers (4)

EricClapton
EricClapton

Reputation: 1

You could also use style='visibility: hidden;' if you want your div to be "invisible".

Upvotes: 0

trante
trante

Reputation: 34006

@Jon's solution works but I tried a different way. My solution is like this:

In HTML part make "div" hidden like this:

<div id="visualization" style="width: 800px; height: 400px; display: none;">
    </div>

Between script tags, make "div" visible just before the AnnotatedTimeLine line

      data.addRows([
        [new Date(2008, 1 ,1), 30000, null, null, 40645, null, null],
        [new Date(2008, 1 ,2), 14045, null, null, 20374, null, null],
        [new Date(2008, 1 ,3), 55022, null, null, 50766, null, null],
        [new Date(2008, 1 ,4), 75284, null, null, 14334, 'Out of Stock', 'Ran out of stock on pens at 4pm'],
        [new Date(2008, 1 ,5), 41476, 'Bought Pens', 'Bought 200k pens', 66467, null, null],
        [new Date(2008, 1 ,6), 33322, null, null, 39463, null, null]
      ]);

      document.getElementById('visualization').style.display = 'inline-block';
      var annotatedtimeline = new google.visualization.AnnotatedTimeLine(
          document.getElementById('visualization'));
      annotatedtimeline.draw(data, {'displayAnnotations': true});

Because new google.visualization.AnnotatedTimeLine needs a visible "div". When you unhide the "div", visualization class constructs the object successfully.

Upvotes: 1

Mark Westside
Mark Westside

Reputation: 29

I had the same problem and could fix it by adding the units to the width and height:

<div id="visualization" style="width: 800px; height: 400px; display: none;"></div>

Upvotes: 2

Jon
Jon

Reputation: 3238

I came across the answer on a jQuery UI page.

Any component that requires some dimensional computation for its initialization won't work in a hidden tab, because the tab panel itself is hidden via display: none so that any elements inside won't report their actual width and height (0 in most browsers).

There's an easy workaround. Use the off-left technique for hiding inactive tab panels instead of display: none;.

Upvotes: 3

Related Questions