在旧的谷歌图表API中,可以使用PHP来渲染图表,甚至有一个包装器来完成它:http://code.google.com/p/gchartphp/
但是有了新的图表APIhttp://code.google.com/apis/chart/它可以生成更漂亮的图表,但只能在浏览器中使用javascript加载。
我想要实现的效果是通过AJAX提交一个选择表单到服务器,让PHP更新数据库服务器端,然后返回更新的图表。
在旧的API中我可以做到这一点。但是在新的方式中,我将返回javascript到浏览器并将其附加到文档中以呈现图表。因为这个,它不会执行。我相信我可以eval()这个javascript,但这是糟糕的形式,不是吗,因为有人可以做一些讨厌的东西,他们不能- eval()服务器端响应?
我怎样才能克服这个?有一个PHP包装器来帮助这个吗?还是有我忽略的另一个原因?
多谢
最后我解决这个问题的方法很明显。我只是需要跳出我的想法,从一个不同的角度来看待它。
我试图在服务器端使用PHP处理数据库信息并创建谷歌图表(在这种情况下为饼图)的所有腿部工作。然后将其作为AJAX响应返回。
实际上,我需要做的就是返回创建饼图所需的数据(以及一些额外的元数据,如目标元素id)。我将其作为JSON。然后,通过挑选Google Charts文档,我能够找到如何使用客户端javascript触发API来加载返回的JSON数据。然后让Google代码在客户端呈现图表——所以我基本上把所有的呈现责任都转移到了客户端浏览器上。这就是新旧图表api的不同之处。
这需要大量的试验和错误以及Firebug的大量帮助。值得一提的一个大问题是,您需要在接收JSON响应之前加载所有的Google JSAPI——以便初始页面呈现——并且必须做一件事:google.load("visualization", "1", {packages:["corechart"]});
是确保它在页面呈现时加载。如果在页面完全呈现后调用此函数,则页面将重新加载。
多亏了andyg1和Ascendant,我能够让它像这样工作(使用PrototypeJS而不是jQuery,但想法是一样的)。由于这一点都不明显,我将展示所有步骤。
Ajax端点只返回json,看起来像这样(一个。net MVC模板)。请注意,我发现我必须引用谷歌文档中没有建议的所有内容:<%
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中(注意初始化方法的最后一行是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();
});
我相信它可以进一步改进,但它工作!
我在过去处理过这样的情况,使用隐藏字段作为请求的一部分返回相关数据,以您想要的任何格式。不返回javascript。在ajax的成功回调中,您将从该输入获取并处理数据。
编辑:基本上,如果你直接通过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响应的呈现和处理方式。