Google Visualization Gauge 使用 jquery ajax 进行动态更新 - 来自 json feed
我收到了一位客户的请求,希望查看 LAMP 服务器上 sysInfo 数据的图形表示。对于我们这些喜欢视觉效果的人来说,这里有现场演示。
我在谷歌图表上找到了仪表,在他们的演示中,图表正在移动。这就是我向客户展示的,所以这就是他们想要的。只是在深入研究之后,我很快意识到他们只是用随机数更新它。所以我尝试自己做。我在互联网上搜索,甚至在这里发布了我的问题,但没有人回复。
所以,这就是我所做的...
最初,我试图通过 ajax 更新我的谷歌可视化仪表图表。我的 json feed 返回:
[
{"key":"label1","value":"50.25"},
{"key":"label2","value":"99.43"},
{"key":"label3","value":"4.47"},
{"key":"label4","value":"7.06"}
]
我让它最初渲染静态图像,但它似乎从未更新。我花了一段时间,然后我发现我的价值观周围有引号。这是问题 #1:API 正在寻找数字数据。这是我第一次使用 json 服务。我不确定是否需要以某种方式添加状态:“ok”,或者是否需要像许多其他帖子告诉我的那样执行 eval() 。好吧,我也不需要...
我的脚本如下:
<script type='text/javascript' src='http://www.google.com/jsapi'></script>
<script type='text/javascript'>
// load the visualization api & skin
google.load('visualization', '1', {packages:['gauge']});
// draw the initial chart from snapshot data for quick rendering
google.setOnLoadCallback(drawChart);
// set global vars once DOM finishes
$(document).ready(function() {
chart = new google.visualization.Gauge(document.getElementById('chart_div'));
options = {width: 400, height: 120,
redFrom: <?=$CODE_RED?>, redTo:100,
yellowFrom:<?=$CODE_YEL?>, yellowTo:<?=$CODE_RED?>,
greenFrom:<?=$CODE_GRN?>0, greenTo:<?=$CODE_YEL?>,
minorTicks: 5};
// initialize ajax update of chart every 15 seconds
setInterval("getStats ('./getJson.sysinfo.php?dash')", 15000);
});
然后我渲染了一个静态图:
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Label');
data.addColumn('number', 'Value');
data.addRows(8);
data.setValue(0, 0, 'label1');
data.setValue(0, 1, <?=number_format($X1,2) ?>);
data.setValue(1, 0, 'label2');
data.setValue(1, 1, <?=number_format($X2,2)?>);
data.setValue(2, 0, 'label3');
data.setValue(2, 1, <?=number_format($X3,2)?>);
data.setValue(3, 0, 'label4');
data.setValue(3, 1, <?=number_format($X4,3)?>);
chart.draw(data, options);
}
所有这些似乎都工作正常,直到 doc.ready 中讨厌的 setInterval() 方法在我的草率代码中启动 - 15几秒钟后。 ajax 源是一个用 json_encode() 包装的 php 数组。当脚本更新时,我的整个图表消失了 - 这有点糟糕!我看到 json 通过 firebug 传入。它只是不起作用。看一下:
function getStats (source) {
$.ajax({
url: source,
type: 'POST',
dataType: 'json',
success: function(data) { refreshChart(data); },
error: function (request, status, error) {
alert("REQUEST:\t"+request
+"\nSTATUS:\t"+status
+"\nERROR:\t"+error);
}
});
}
然后我的refreshChart()就是一切都崩溃的地方:
function refreshChart(serverData) {
var chartData = [];
for(var i = 0; i < serverData.length; i++) {
// chartData.push([serverData[i][0], $.serverData[i][1]['value']]);
// chartData.push([serverData[i][0], $.serverData[i][1].val()]);
chartData.push([serverData[i][0], serverData[i][1].value]);
}
// note2self[347] = "I tried the above a million different ways and firebug coming back
//+ with: "missing ] after element list" on the function declaration line..."
var data = new google.visualization.DataTable();
data.addColumn('string', 'Label');
data.addColumn('number', 'Value');
data.addRows(chartData);
chart.draw(data, options);
}
</script>
我在想也许我需要创建另一个DataTable对象,或者如果在函数外部声明它,也许我可以使用setInterval(data.setValue(i,1) , serverDatai),1500) 到直接更新元素。无论哪种方式,第一步都是访问 json 数据。我知道我一定做了一些愚蠢的事情......在我的帖子底部(在我重新编辑它之前的本页上)我补充道:“任何帮助,甚至是朝正确方向的推动都会极大地帮助我。”非常感谢……”一周以来我每天都回来重新编辑。我以为我只是不清楚或者这是一个愚蠢的问题。 “我见过一些愚蠢的问题得到了解答,”我想,“也许我的问题真的非常愚蠢?”尽管如此,我仍然需要一个答案。虽然我不是最好的程序员,但我是一个非常好的谷歌用户。我读了所有我能看到的东西。运气不好。 nada,non,zylch,niet,什么都没有......
好吧,这让我发疯,所以这就是我发现的:
- 正如我之前提到的,我在我的数值周围加了引号。这就是我的图表炸弹的原因......并且由于 jQuery 不会给你任何错误,所以我对我将字符数据填充到新数组中的事实视而不见,直到我调用 .draw() 方法和我漂亮的图片消失了。
- 我没有想到要检查的另一个问题是我正在使用的 jQuery 版本。它很旧而且很旧。没有内置 json 解析。因此,我必须评估服务器数据,解析数据流并获取数据。从那里构建数据结构。
- #1 和 #1 #2 导致数据行更新失败,并且我的字段全部返回未定义。
- 我还有一些超出范围的变量声明 - 即添加 .Guage 的类,顺便还添加了 .DataTable() - 随之而来。
- data.setValue(i,1,serverData[i].value) 应该在 AJAX() 调用的成功回调中循环 - 这完全消除了我的 refreshChart() 方法。
- 我遇到的最后一个问题是弄清楚如何访问 json 数据&将其填充到我现有的数组中。这比我想象的要棘手一些。一个更有经验的程序员可能会更清楚......但是,我很固执。您可以看到我试图在现有数组中执行 ChartData.push() 的位置。我连续几个晚上都在调用 arrayName[][] 的每种可能组合。事实证明,我可以重新使用谷歌的 .setValue() 方法。正如您将在下面看到的,使用 success() 回调方法,一旦将第一个元素填充到仪表中,并将其余元素填充到需要去的其他位置,我就能够循环它,使用:
for (var i = 0; i < data.length; i++) { 如果(i<4){ dashData.setValue(i, 0, jsonData[i].k); dashData.setValue(i, 1, jsonData[i].v); } ...
我从头开始重写了整个事情。接下来的几天,我可能会重新写几次。最终这将演变成成熟的 drupal & WordPress 插件和操作方法文章。我会将其发布在我的博客 LogicWizards.NET 上,因为 jQuery 文档很模糊,而且 google 网站上的示例演示也不是很直接。
为了让故事变得更长,我想到了以下内容:
<!-- /** Client-Side Scripts **/ -->
<script type='text/javascript' src='http://www.google.com/jsapi'></script>
<script type='text/javascript'>
// load the visualization api & skin
google.load('visualization', '1', {packages:['gauge']});
// draw the initial chart from snapshot data for quick rendering
google.setOnLoadCallback(drawChart); //as soon as the API is loaded
// set global vars once DOM finishes
$(document).ready(function() {
dash = new google.visualization.Gauge(document.getElementById('chart_div'));
dashData = new google.visualization.DataTable();
options = { width: 400, height: 120,
redFrom:75, redTo:100,
yellowFrom:50, yellowTo:75,
greenFrom:00, greenTo:50,
minorTicks: 5};
});
function drawChart() {
// method to define initial chart
dashData.addColumn('string', 'Label');
dashData.addColumn('number', 'Value');
dashData.addRows(8);
dashData.setValue(0, 0, 'CPU');
dashData.setValue(0, 1, 54.40);
dashData.setValue(1, 0, 'RAM');
dashData.setValue(1, 1, 99.54);
dashData.setValue(2, 0, 'SWAP');
dashData.setValue(2, 1, 4.25);
dashData.setValue(3, 0, 'NET');
dashData.setValue(3, 1, 0.402);
dash.draw(dashData, options);
}
function updateJSON (source) {
// method to update all subsequent charts
var jsonData = null; //there's really no reason for this anymore (see below)
$.ajax({ url:source, type:'POST', dataType:'json',
success: function(data) { jsonData=data;
for (var i = 0; i < data.length; i++) {
if (i<4) {
dashData.setValue(i, 0, jsonData[i].k);
dashData.setValue(i, 1, jsonData[i].v);
if (i<3) { dash.draw(dashData, options); }
}
$("#"+jsonData[i].k).text(jsonData[i].v);
}
},
error: function (request, status, error) {
alert("REQUEST:\t"+request
+"\nSTATUS:\t"+status
+"\nERROR:\t"+error); }
}); //end-ajax
return jsonData; //obsolete: updates are now done through the success callback
}
function isSet (variable) { // mimic the php function
return (typeof variable !== "undefined" && variable.length) ? 1 : 0;
}
function setDelay(delay){
// method to change timer's sleep interval
clearInterval(timer); //kill the last timer
timer=setInterval(json,delay*1000); //delay is miliseconds
}
</script>
您将看到大部分繁重的工作是通过 updateJSON() 函数完成的。现在效果很好。我想,如果我遇到这么多问题,那么其他人可能会从我原来的帖子的快速编辑中受益——我一边回答我自己的问题。我认为为 StackedOverflow 写出问题的过程帮助我区分了问题和症状,并找到了答案。尽管没有其他人给出答案。
如果有人想观看现场演示,请访问 http ://LogicWizards.NET 如果您需要此表示层内容,请随时从“查看源代码”中窃取它。该应用程序的核心内容都在后端......现在,我花了一周的大部分时间才将所有部分组合在一起。请原谅我的胡言乱语。当我有更多时间时我会编辑这个。多年来,我刚刚从这个网站和社区的其他部分获取了很多代码,我很乐意回馈一点……如果您使用这篇文章,请记住投票赞成。
我希望它能帮助有需要的人。
黑客快乐,
Joe Negron ~ NYC
I had a REQ from a client that wanted to see a graphical representation of the sysInfo data on a LAMP server. For those of us who prefer a visual there's live demo here.
I found the gauges on google charts and in their demo the graph was moving. That's what I showed the client, so that's what they wanted. It's just that after poking around under the hood, I quickly realized that they were just updating it with random numbers. so I attempted to do it myself. I scoured the internet and I even posted my issues here but no-one replied.
So, here's what I did...
Initially, I was trying to get my google visualization gauge chart to update via ajax. my json feed returned:
[
{"key":"label1","value":"50.25"},
{"key":"label2","value":"99.43"},
{"key":"label3","value":"4.47"},
{"key":"label4","value":"7.06"}
]
I got it to initially render a static image, but it never seemed to update. it took me a while, then I figured out that my values had quotes around them. That was problem #1: the API was looking for numeric data.It was my 1st time with a json service. I wasn't sure if I needed to somehow add the status:"ok" or if I needed to do an eval() like so many other posts told me. Well, I didn't need either...
My script was as follows:
<script type='text/javascript' src='http://www.google.com/jsapi'></script>
<script type='text/javascript'>
// load the visualization api & skin
google.load('visualization', '1', {packages:['gauge']});
// draw the initial chart from snapshot data for quick rendering
google.setOnLoadCallback(drawChart);
// set global vars once DOM finishes
$(document).ready(function() {
chart = new google.visualization.Gauge(document.getElementById('chart_div'));
options = {width: 400, height: 120,
redFrom: <?=$CODE_RED?>, redTo:100,
yellowFrom:<?=$CODE_YEL?>, yellowTo:<?=$CODE_RED?>,
greenFrom:<?=$CODE_GRN?>0, greenTo:<?=$CODE_YEL?>,
minorTicks: 5};
// initialize ajax update of chart every 15 seconds
setInterval("getStats ('./getJson.sysinfo.php?dash')", 15000);
});
then I rendered a static graph with:
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Label');
data.addColumn('number', 'Value');
data.addRows(8);
data.setValue(0, 0, 'label1');
data.setValue(0, 1, <?=number_format($X1,2) ?>);
data.setValue(1, 0, 'label2');
data.setValue(1, 1, <?=number_format($X2,2)?>);
data.setValue(2, 0, 'label3');
data.setValue(2, 1, <?=number_format($X3,2)?>);
data.setValue(3, 0, 'label4');
data.setValue(3, 1, <?=number_format($X4,3)?>);
chart.draw(data, options);
}
all of that seemed to work fine until that pesky setInterval() method in doc.ready kicked in my sloppy code - 15 seconds later. The ajax source is a php array wrapped with json_encode(). When the script updated, my entire graph disappeared - which kinda sucked! I saw the json coming in via firebug. It just wasn't working. Take a look:
function getStats (source) {
$.ajax({
url: source,
type: 'POST',
dataType: 'json',
success: function(data) { refreshChart(data); },
error: function (request, status, error) {
alert("REQUEST:\t"+request
+"\nSTATUS:\t"+status
+"\nERROR:\t"+error);
}
});
}
and then my refreshChart() is where everything just fell apart:
function refreshChart(serverData) {
var chartData = [];
for(var i = 0; i < serverData.length; i++) {
// chartData.push([serverData[i][0], $.serverData[i][1]['value']]);
// chartData.push([serverData[i][0], $.serverData[i][1].val()]);
chartData.push([serverData[i][0], serverData[i][1].value]);
}
// note2self[347] = "I tried the above a million different ways and firebug coming back
//+ with: "missing ] after element list" on the function declaration line..."
var data = new google.visualization.DataTable();
data.addColumn('string', 'Label');
data.addColumn('number', 'Value');
data.addRows(chartData);
chart.draw(data, options);
}
</script>
I was thinking maybe I needed to create another DataTable object, or if declared it outside the function, maybe I can use setInterval(data.setValue(i,1, serverDatai),1500) to update the element directly. Either way, the 1st step was accessing the json data. I knew I must have been be doing something stupid... At the bottom of my post (on this page, before I re-re-edited it) I added:"any help or even a nudge in the right direction would be greatly appreciated..." I came back every day for a week and re-re-re-edited. I thought I was just being unclear or that it was a stupid question. "I've seen stupid questions get answered", I thought, "maybe mine was really-really stupid?" None-the-less, I still needed an answer. Although I'm not the best programmer - I'm a pretty good googler. I read everything I could get my eyes on. No luck. nada, non, zylch, niet, nothing...
Well, it was driving me nuts, so here's what I figured out:
- As I mentioned before, I had quotes around my numeric values. That's what made my chart bomb... and since jQuery doesn't give you any errors I was kind of blind to the fact that I was stuffing character data into my new array until I called the .draw() method and my pretty picture disappeared.
- Another problem that I didn't think to check was the version of jQuery I was using. It was old & didn't have json parsing built into it. so, I would have had to eval the server data, parse the data stream & build the data structure from there.
- Both #1 & #2 caused the data row updates to fail and my fields WERE all coming back undefined.
- I also had some variable declarations out of scope - namely the class that added the .Guage and incidently the .DataTable() - which came along for the ride.
- data.setValue(i,1,serverData[i].value) should have been looped in the success callback of the AJAX() call - and this completely eliminated my refreshChart() method.
- The last problem I was having was figuring out how to access the json data & stuff it into my existing array. That was a little more tricky than I thought. a more experienced programmer probably would have just known better... but, I was stubborn. You can see where I was trying to do a chartData.push() into the existing array. I was calling possible every combination of arrayName[][] for several nights. It turned out that I COULD just re-use google's .setValue() method. As you will see below, using the success() callback method I was able to loop it once stuff the 1st few elements into the gauge and the rest into the other places it needed to go, using:
for (var i = 0; i < data.length; i++) { if (i<4) { dashData.setValue(i, 0, jsonData[i].k); dashData.setValue(i, 1, jsonData[i].v); } ...
I re-wrote the whole thing from scratch. In the next few days, I will probably re-write it again, several times. Eventually this will evolve into full blown drupal & wordpress plug-ins and a how-to article. I will post it on my blog LogicWizards.NET b/c the jQuery documentation is vague and the example demo on google's site isn't very straight forward, either.
To make a long story even longer, here's what I came up with:
<!-- /** Client-Side Scripts **/ -->
<script type='text/javascript' src='http://www.google.com/jsapi'></script>
<script type='text/javascript'>
// load the visualization api & skin
google.load('visualization', '1', {packages:['gauge']});
// draw the initial chart from snapshot data for quick rendering
google.setOnLoadCallback(drawChart); //as soon as the API is loaded
// set global vars once DOM finishes
$(document).ready(function() {
dash = new google.visualization.Gauge(document.getElementById('chart_div'));
dashData = new google.visualization.DataTable();
options = { width: 400, height: 120,
redFrom:75, redTo:100,
yellowFrom:50, yellowTo:75,
greenFrom:00, greenTo:50,
minorTicks: 5};
});
function drawChart() {
// method to define initial chart
dashData.addColumn('string', 'Label');
dashData.addColumn('number', 'Value');
dashData.addRows(8);
dashData.setValue(0, 0, 'CPU');
dashData.setValue(0, 1, 54.40);
dashData.setValue(1, 0, 'RAM');
dashData.setValue(1, 1, 99.54);
dashData.setValue(2, 0, 'SWAP');
dashData.setValue(2, 1, 4.25);
dashData.setValue(3, 0, 'NET');
dashData.setValue(3, 1, 0.402);
dash.draw(dashData, options);
}
function updateJSON (source) {
// method to update all subsequent charts
var jsonData = null; //there's really no reason for this anymore (see below)
$.ajax({ url:source, type:'POST', dataType:'json',
success: function(data) { jsonData=data;
for (var i = 0; i < data.length; i++) {
if (i<4) {
dashData.setValue(i, 0, jsonData[i].k);
dashData.setValue(i, 1, jsonData[i].v);
if (i<3) { dash.draw(dashData, options); }
}
$("#"+jsonData[i].k).text(jsonData[i].v);
}
},
error: function (request, status, error) {
alert("REQUEST:\t"+request
+"\nSTATUS:\t"+status
+"\nERROR:\t"+error); }
}); //end-ajax
return jsonData; //obsolete: updates are now done through the success callback
}
function isSet (variable) { // mimic the php function
return (typeof variable !== "undefined" && variable.length) ? 1 : 0;
}
function setDelay(delay){
// method to change timer's sleep interval
clearInterval(timer); //kill the last timer
timer=setInterval(json,delay*1000); //delay is miliseconds
}
</script>
You will see that the bulk of the heavy lifting is done via the updateJSON() function. and now it works pretty nicely. I figured that if I was having this many problems then somebody else might benefit from a quick edit of my original post - with me answering my own questions as I went along. I think that the process of writing my questions out for StackedOverflow helped me to tell the difference between the problems and the symptoms, and also to find the answers. Even though nobody else had an answer.
If anyone would like to see a live demo go to http://LogicWizards.NET If you need this presentation layer stuff, please feel free to steal it from the 'view source'. The guts of the application are all on the back end... Now, it took me the better part of a week to put all the pieces together. Forgive me for rambling. I will edit this when I have more time. I've just taken so much code from THIS site and the rest of the community, over the years, I feel good about giving a little bit back... just remember to vote this article up, if you use it.
I hope it helps someone who needs it.
Happy Hacking,
Joe Negron ~ NYC
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
根据问题跟踪器项目,升级到 1.1 应该可以解决该问题。
而不是
使用
According to the project issues tracker, upgrade to 1.1 should fix the issue.
instead of
use