为什么使用Google Charts的这段代码如此脆弱?

时间:2018-06-28 22:46:43

标签: javascript google-visualization

我正在尝试了解如何使用Google图表并编写了该程序:

<!DOCTYPE html>
<html>
  <head>
    <style>
     .signal {
       border: 5px solid #333;
       border-radius: 30px;
       height: 30px;
       left: 50%;
       margin: -15px 0 0 -15px;
       opacity: 0;
       position: absolute;
       top: 50%;
       width: 30px;

       animation: pulsate 1s ease-out;
       animation-iteration-count: infinite;
     }

     @keyframes pulsate {
       0% {
         transform: scale(.1);
         opacity: 0.0;
       }
       50% {
         opacity: 1;
       }
       100% {
         transform: scale(1.2);
         opacity: 0;
       }
     }
    </style>

    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>

    <script type="text/javascript">
     google.charts.load('current', {'packages':['corechart']});

     var extrema = [[{label:"Time", id:"time", type:"datetime"},
                     {label:"Lows", id:"lows", type:"number"},
                     {label:"Highs", id:"highs", type:"number"}]];

     var readings = [];


     function drawHighLowChart() {
       var data = google.visualization.arrayToDataTable(extrema, false);
       var options = {
         title:'High/Low',
         //curveType: 'function',
         legend: { position: 'right'},
         hAxis: {format: 'MM/dd',
                 gridlines: {count: extrema.length - 1}}
       };
       var chart = new google.visualization.LineChart(document.getElementById("High_Low"));
       chart.draw(data, options);
     }




     var request = new XMLHttpRequest();
     request.onreadystatechange = function()
     {
       if (this.readyState == 4 && this.status == 200)
         {
           var channel_data = JSON.parse(this.responseText);
           var feeds = channel_data.feeds;
         }

       for (var i in feeds)
         {
           readings.push([new Date(Date.parse(feeds[i].created_at)),
                          parseFloat( feeds[i].field1).toFixed(1)]);
         }


       var low = readings[0][1];
       var high =readings[0][1];
       var current_date = readings[0][0];
       for (var i in readings)
         {
           if (readings[i][0].getDate() != current_date.getDate())
             {
               extrema.push([new Date(current_date.getFullYear(),
                                      current_date.getMonth(), current_date.getDate()),
                             low,
                             high]);
               current_date = readings[i][0];
               low = readings[i][1];
               high = readings[i][1];
             }
           else
             {
               low = Math.min(low, readings[i][1]);
               high = Math.max(high, readings[i][1]);
             }
         }
       extrema.push([current_date, low, high]);

       //document.getElementById('text').innerHTML = extrema;
       drawHighLowChart();
     };

     request.open("GET", "https://api.thingspeak.com/channels/227030/fields/1.json?days=5", true);
     request.send();


    </script>
  </head>


  <body>

    <h2>Corazon del Bosque Temperature Record </h2>


    <div id="Daily Temps" style="width: 900px; height: 500px">
    </div>
    <div id="High_Low" style="width: 900px; height: 500px">
      <div class="signal"></div>
    </div>
  </body>

</html>

我所做的几乎所有事情都会破坏这一点。例如,我尝试添加

<meta charset="UTF-8">

到标题,并且代码产生错误,表明arrayToDataTable不是函数。 如果我只是删除注释行之前的空白行

 //document.getElementById('text').innerHTML = extrema;

我收到LineChart不是构造函数的错误。

我已经检查了隐藏在代码中的隐藏字符(在emacs中使用空白模式),但没有任何内容。

我应该寻找什么来解释这种行为? 如果有任何不同,我正在Windows的最新版本的Firefox中进行测试。

1 个答案:

答案 0 :(得分:0)

需要确保在尝试使用该库之前Google图表已完成加载

有两种方法,可以使用方法setOnLoadCallback
load语句返回

的承诺

像这样尝试...

 google.charts.load('current', {'packages':['corechart']}).then(function () {  // <-- promise
   var extrema = [[{label:"Time", id:"time", type:"datetime"},
                   {label:"Lows", id:"lows", type:"number"},
                   {label:"Highs", id:"highs", type:"number"}]];

   var readings = [];


   function drawHighLowChart() {
     var data = google.visualization.arrayToDataTable(extrema, false);
     var options = {
       title:'High/Low',
       //curveType: 'function',
       legend: { position: 'right'},
       hAxis: {format: 'MM/dd',
               gridlines: {count: extrema.length - 1}}
     };
     var chart = new google.visualization.LineChart(document.getElementById("High_Low"));
     chart.draw(data, options);
   }




   var request = new XMLHttpRequest();
   request.onreadystatechange = function()
   {
     if (this.readyState == 4 && this.status == 200)
       {
         var channel_data = JSON.parse(this.responseText);
         var feeds = channel_data.feeds;
       }

     for (var i in feeds)
       {
         readings.push([new Date(Date.parse(feeds[i].created_at)),
                        parseFloat( feeds[i].field1).toFixed(1)]);
       }


     var low = readings[0][1];
     var high =readings[0][1];
     var current_date = readings[0][0];
     for (var i in readings)
       {
         if (readings[i][0].getDate() != current_date.getDate())
           {
             extrema.push([new Date(current_date.getFullYear(),
                                    current_date.getMonth(), current_date.getDate()),
                           low,
                           high]);
             current_date = readings[i][0];
             low = readings[i][1];
             high = readings[i][1];
           }
         else
           {
             low = Math.min(low, readings[i][1]);
             high = Math.max(high, readings[i][1]);
           }
       }
     extrema.push([current_date, low, high]);

     //document.getElementById('text').innerHTML = extrema;
     drawHighLowChart();
   };

   request.open("GET", "https://api.thingspeak.com/channels/227030/fields/1.json?days=5", true);
   request.send();
 });