Загрузите Google Chart из асинхронного ответа AJAX - PullRequest
3 голосов
/ 09 декабря 2011

В старом API Google Chart можно было использовать PHP для визуализации диаграммы, для этого была даже оболочка: http://code.google.com/p/gchartphp/

Но с новым API диаграммы http://code.google.com/apis/chart/который производит намного более изящную диаграмму, но загружается только с помощью javascript в браузере.

Эффект, который я пытаюсь достичь, - это отправка формы с множественным выбором на сервер через AJAX, PHP-обновление БД на стороне сервера, а затем возвратобновленный график.

В старом API, я мог бы сделать это.Но по-новому я бы вернул javascript в браузер и добавил его в документ, чтобы отобразить диаграмму.Это не будет выполнено из-за этого.Я полагаю, что смогу eval () этот javascript, но это плохая форма, не правда ли, потому что кто-то может сделать что-то неприятное, с чем он не может - eval () получить ответ на сервере?

Как я могу преодолетьэтот?Есть ли обертка PHP, чтобы помочь этому?Или есть еще одна причина, которую я упустил из виду?

Большое спасибо

Ответы [ 3 ]

6 голосов
/ 13 декабря 2011

То, как я решил эту проблему, в конце концов было довольно очевидно.Мне просто нужно было выйти за пределы своих мыслей и подойти к нему под другим углом.

Я пытался выполнить всю работу по обработке информации базы данных И создать Google Chart (в данном случае круговую диаграмму) нана стороне сервера, используя PHP.Затем верните это как ответ AJAX.

На самом деле все, что мне нужно было сделать, это вернуть данные, необходимые для создания круговой диаграммы (вместе с некоторыми дополнительными метаданными, такими как идентификатор целевого элемента).Я сделал это как JSON.Затем, просмотрев документацию по Google Charts, я смог выяснить, как вызвать API, используя JavaScript на стороне клиента для загрузки возвращаемых данных JSON.Затем позвольте коду Google визуализировать клиентскую часть диаграммы - так что я в основном перенес всю ответственность за визуализацию на браузер клиента.Это то, чем отличаются старые и новые API диаграмм.

Потребовалось много проб и ошибок и много помощи от Firebug.Стоит упомянуть одну важную проблему, которая заключается в том, что вам нужно загрузить все JSAPI Google, прежде чем вы получите ответ JSON - так же, как отображается начальная страница, - и вам нужно сделать одну вещь:убедитесь, что он загружается при рендеринге страницы.Если вы вызовете это после того, как страница полностью отобразится, то страница перезагрузится.

Надеюсь, это кому-нибудь поможет.

3 голосов
/ 07 ноября 2012

Благодаря andyg1 и Ascendant я смог заставить его работать так (используя PrototypeJS, а не jQuery, но идея та же). Поскольку это совсем не очевидно, я собираюсь показать все шаги.

Конечная точка Ajax просто возвращает json и выглядит следующим образом (шаблон .NET MVC). Обратите внимание, что я обнаружил, что должен был процитировать все, что документация Google не предлагает, необходимо:

<% 
Response.Headers.Add("Content-type", "text/json");
Response.AddHeader("Content-type", "application/json");
%>
{
  "cols": [
    {"id": "col_1", "label": "Date", "type": "string"},
    {"id": "col_2", "label": "Score", "type": "number"}
  ],
  "rows": [
    <%
    int index = 0;
    foreach(KeyValuePair<string, double> item in Model.Performance ) { %>
      {"c":[{"v":"<%= item.Key %>"}, {"v":<%= item.Value %>}]}<%= (index == Model.Performance.Count - 1) ? "" : "," %>
      <% index++; %>
      <% 
    } 
    %>
  ]
}

Тогда главная страница содержала это:

<script type="text/javascript" src="https://www.google.com/jsapi"></script> 
<script type="text/javascript" src="/js/myJavascriptFile.js" />

Затем в myJavascriptFile.js (обратите внимание, что последняя строка метода initialize - это google.setOnLoadCallback, который вызывает метод в моем классе, а не drawChart):

google.load('visualization', '1', {'packages':['corechart']});
var colors = {'blue': '#369', 'red': '#c22', 'green': '#283', 'yellow': '#c91'};

var MyClass = Class.create({

  initialize: function() {
    ... 
    google.setOnLoadCallback(this.getTeamCharts);
  },

  getTeamCharts: function () {
    $$(".chart-wrapper").each(function (div) {
      var chartData = div.getData();
      var parameters = {
        ...
      };

      new Ajax.Request('/endpoints/TeamChart.aspx', {
        method: 'get',
        parameters: parameters,
        onSuccess: function(transport) {
            var jsonData = transport.responseJSON;
            var data = new google.visualization.DataTable(jsonData);
            var chartColor = colors[parameters.TeamColor];
            var chartDivId = 'chart_div_' + parameters.TeamIdAsString;

            // Set chart options
            var options = {
              'chartArea': {'left':'15%','top':'15%','width':'80%','height':'70%'},
              'legend': {'position': 'none'},
              'lineWidth': 3,
              'width': 262, 
              'height': 180,
              'colors': [chartColor]
            };

            // Instantiate and draw our chart, passing in some options.
            var chart = new google.visualization.LineChart(document.getElementById(chartDivId));
            chart.draw(data, options);
        }
      });
    });
  }

});

document.observe("dom:loaded", function () {
  var thing = new MyClass();
});

Я уверен, что это может быть улучшено, но это работает!

0 голосов
/ 09 декабря 2011

Я обрабатывал подобные ситуации в прошлом, используя скрытое поле, которое возвращается как часть запроса с соответствующими данными в любом формате, который вы хотите. Никакой JavaScript не возвращается. При успешном обратном вызове ajax вы будете получать и обрабатывать данные из этого ввода.

EDIT:

В основном, если вы получаете прямой доступ через ajax html для обновления страницы, и вы не хотите изменять то, как это работает , поместите как часть ответа ajax скрытый ввод

<input type="hidden" name="yourhiddeninputname" id="yourhiddeninputname" 
   value="whatever|data|you|want,blah,blah,blah" /> 

Затем, как только html внедряется в вашу страницу , вы будете делать что-то вроде

var yourdata = document.getElementById('yourhiddeninputname').value;
// do stuff with your data here.

Это лучший вариант? Я не уверен. Это действительно зависит от того, как вы передаете свой AJAX. Я сделал свои оригинальные комментарии, исходящие из фона ASP.NET, где вы часто рассчитываете на то, что экземпляры классов будут генерировать для вас html, и вы как бы абстрагированы от фактического генерируемого html (и других вещей). Конечно, есть и другие способы справиться с этим, особенно если у вас есть полный контроль над тем, как обрабатывается и обрабатывается ответ AJAX.

...