Have my graph and graph it too?
May 15, 2012 8:55 AM   Subscribe

How can I generate a graph server-side, and update it client-side?

My boss just handed me the job of creating graphs for one of our systems, but he'd like it to work with or without Javascript, so I can't just use one of the many javascript-based graphing libraries unless I also implement the graphs as static images. Flash is also out, since it won't work on the iPad.

So, what I'm looking for is some way to generate a graph on the server (possibly as SVG?) and then some way to manipulate the graph with Javascript (the dataset gets updated about once every 5 seconds) so that users with Javascript enabled can see auto-updating graphs in the UI (and users with Javascript disabled will just see a static representation of the data as of when the page is loaded).

Does this kind of thing exist? Or would I just be better implementing things twice?
posted by fvox13 to Computers & Internet (11 answers total) 1 user marked this as a favorite
d3 might be useful? I've never used it but I've heard it's very robust.
posted by Strass at 9:03 AM on May 15, 2012

Best answer: You can make this work with HighCharts. They have instructions on how to set up a server export to convert the output data into an SVG and push the same data to their client-side js library.
posted by mkultra at 9:08 AM on May 15, 2012 [1 favorite]

SVG could work. A friend of mine built a time-series graph that rendered an initial graph as SVG and then updated it via JS.

On Preview: He built Synynyms, but he was rendering all of the SVG in the browser. Harumph.
posted by thebigdeadwaltz at 9:12 AM on May 15, 2012

Best answer: Do everything on the server side, throw the graph in an <iframe> , and set the iframe to auto-refresh every 5 seconds. Works for everyone with or without JavaScript.
posted by xbonesgt at 9:17 AM on May 15, 2012 [2 favorites]

Use client-side d3 to render server-generated, JSON-formatted data into a graph. Use Ajax requests to deliver fresh data every x seconds. If the request is successful, call your d3 graph function on the new data to redraw.
posted by Blazecock Pileon at 10:27 AM on May 15, 2012

A note to the various d3 suggestions: Unless you know something I don't, d3 is a client-side JavaScript library. Which means that, unless it operates on SVG files (which I wouldn't if I were developing it, I'd just stick with JavaScript Canvas elements), it doesn't fulfill the primary requirement of the original poster: No JavaScript.

I suspect that what fvox13 is looking for is a way to not do what I'm going to suggest:

Bifurcate the pipelines. Using something like one of the graphing libraries that sits on top of libGD generate PNG or GIF graphs. Then build a JavaScript version using D3 or jqPlot or Flot or what-have-you that takes the JSON data and builds the graph client side, and hides the raster server-side version.

Make sure that you can log the requests for the raster server-side version and for the JSON data so that in 6 months you can go back to your boss and say "really, I appreciate the non-JS compatibility, but the reality is that out of 2815 requests, we've had 3 that may be non-JS". But sometimes the more complex version (2 pipelines) is going to be the simpler one in the long-term.
posted by straw at 10:50 AM on May 15, 2012

Oh, and since I didn't mash reload before I posted (hand slap), you could also use server-push instead of iframes.
posted by straw at 10:51 AM on May 15, 2012

I'm sorry if this doesn't answer the question, but if it were me I would really push back hard on this no-javascript requirement. Things like the google charts API make this so incredibly easy that it's really a bit crazy to do anything else. Does he have real, recent analytic data that shows a significant portion of your users don't have javascript enabled?

Even if such data exists, I would still argue that your initial release use the API. That way you get the kinks worked out in terms of pulling the right data and have a working prototype of the charts themselves that shows the data is sound (and which, oh by the way, will function beautifully for 99% of your users). And you will have done it in the 1/2 the time that it will take to implement a server-side solution. (Seriously, once you have your data the google API is butt easy and provides functionality that will be simply impossible with a generated image, this d3 thing is probably the same). If, at that point, he still insists you indulge him on his outdated notions regarding javascript*, then you can talk about spending your other 1/2 of your time developing an alternate process for the users than need it.

* Again, maybe he has good technical reasons for the requirement. I can't know from where I'm sitting, but I am guessing this boss is not a developer and is working off assumptions that may have been true in the past but have since been overtaken by events.

posted by Dano St at 11:49 AM on May 15, 2012 [1 favorite]

The enterprise way that I've done this before is to have two APIs - getData() and getChart() - so that JS users can access the raw values via getData() and have an interactive experience, and non-JS users can get an image via getChart().

JFreeChart is a great library for server-side charts, and Flot.js is a great JS library for client-side charts. You can tune JFreeChart to match the styling of Flot.js and the two will be almost indistinguishable.

Depending on how many requests you get to view the same charts/time ranges, you can also cache the chart images server-side to improve response times.

One advantage of supporting server-side charts is for embedding in alternate applications/dashboards. Using JS means that you have to access via a browser, and sometimes that's not what you want. Or that you have to view it as the JS library renders it (with all the little decorations that may not be desired).

For example, in a fancy dashboard-like website, you want a lot of thumbnail charts without decoration. Dynamically rendering 100 charts in a webpage like that every 5min is kinda sucky.

Also, when viewing a lot of data, like 10 metrics over a year @ 5min resolution, in a 300x600 chart, is much cheaper to render as an image than trying to return all that data to the browser and render something client-side in JS.

You should make it clear to your boss that server-side images are non-interactive, and client-side (JS) images are (can be) interactive, so there will be a varying customer experience.
posted by jpeacock at 2:19 PM on May 15, 2012 [2 favorites]

If you're comfortable with javascript you could try your hand at node.js which is basically javascript on the server.

Probably what I would do is set up a basic html template, inject the JSON data into it, then create a canvas element chart based on that data and inject that between <noscript> tags. That way, you have an up-to-date (from the last refresh) chart if JS is not available, but you also have the data on the page that can be initially picked up and played with if JS is available. You can then use AJAX to grab more data from the server as and when you need it.

If JS is available the static chart won't be visible.
posted by urbanwhaleshark at 5:21 PM on May 15, 2012

Write it in d3.js for the javascript-on use case - one of the important features is that it very nicely handles additions of data so you won't re-render the whole graph.

For the non-javascript use case, use the same d3 code on a small Node.js server. This example from the creator of d3 runs on Node and renders the graph to a PNG file, which should work in whatever god-forsaken browser someone tries to use.
posted by 23 at 10:07 PM on May 28, 2012

« Older What does it mean to be diagnosed with emphysema?   |   Turnaround time for detaching Blizzard... Newer »
This thread is closed to new comments.