How to format the time elapsed displayed in vAxis of Line Chart

277 views
Skip to first unread message

Robert Mayer

unread,
Oct 6, 2013, 5:45:25 PM10/6/13
to google-visua...@googlegroups.com
I'm using the following code to render a line chart: 

function drawVisualization() {
  // Create and populate the data table.
  var data = google.visualization.arrayToDataTable([
    ['Date', 'Michelle 800m'],
    ['3/16',  163.84],
    ['4/13',  161.69],
    ['4/20',  162],
    ['5/4',   154.22],
    ['6/1',   155.46],
    ['6/8',   153],
    ['6/15',  151.22],
    ['6/22',  156.45],
    ['6/29',  153.45],
    ['7/31',  153.95]
  ]);
  // Create and draw the visualization.
  new google.visualization.LineChart(document.getElementById('visualization')).
      draw(data, {curveType: "none",
                  width: 500, height: 250,
                  vAxis: {minValue: 140}}
          );
}

Each data point on the vAxis represents time elapsed in seconds. The data points are graphed correctly, but the problem is that for times in excess of one minute, the typical convention is to display it
in the format, mm:ss.ss. How can I make this conversion for display purposes only?

- Robert -

asgallant

unread,
Oct 6, 2013, 7:32:17 PM10/6/13
to google-visua...@googlegroups.com
There is not built-in conversion for seconds to "mm:ss.SS" - you will have to do so manually by calculating the appropriate string value and setting the formatted value of the cell to that value.

Thomas Rybka

unread,
Oct 7, 2013, 4:58:31 PM10/7/13
to google-visua...@googlegroups.com
You could use timeofday for your specification of the time.

I tried it, and it seems to work well, but the tick calculation doesn't seem to fall on ms boundaries, so the fractional seconds 
are all 000.

Sadly, the tooltips are formatted a little strange, so I overrode the tooltips to get something a little nicer (using Moment.js http://momentjs.com/).

Here's a jsfiddle that munged your data to put the seconds and ms in an array, and added a tooltip column, and axis formatting:


--
You received this message because you are subscribed to the Google Groups "Google Visualization API" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-visualizati...@googlegroups.com.
To post to this group, send email to google-visua...@googlegroups.com.
Visit this group at http://groups.google.com/group/google-visualization-api.
For more options, visit https://groups.google.com/groups/opt_out.

Robert Mayer

unread,
Oct 8, 2013, 6:47:19 AM10/8/13
to google-visua...@googlegroups.com
Thanks, this seems like you're on the right track, but when I tried you JSFiddle example, it produced no output when I tried to run it. Any ideas?

- Robert -
To unsubscribe from this group and stop receiving emails from it, send an email to google-visualization-api+unsub...@googlegroups.com.

Robert Mayer

unread,
Oct 8, 2013, 7:29:35 AM10/8/13
to google-visua...@googlegroups.com
One other thought... would it be advantageous at all if I were to supply my data values in ticks rather than seconds and fractions?

- Robert -

On Monday, October 7, 2013 3:58:31 PM UTC-5, trybka wrote:
To unsubscribe from this group and stop receiving emails from it, send an email to google-visualization-api+unsub...@googlegroups.com.

Thomas Rybka

unread,
Oct 8, 2013, 7:49:37 AM10/8/13
to google-visua...@googlegroups.com
Try http://jsfiddle.net/fERP6/7/ (apparently some of the timeofday improvements are in the "testing" release, 1.1)

What do you mean by ticks in this case? 

Thomas Rybka | Software Engineer | try...@google.com | GViz


To unsubscribe from this group and stop receiving emails from it, send an email to google-visualizati...@googlegroups.com.

Robert Mayer

unread,
Oct 8, 2013, 2:55:03 PM10/8/13
to google-visua...@googlegroups.com
In the .net world, a tick equals 100 nanoseconds: http://msdn.microsoft.com/en-us/library/system.datetime.ticks.aspx. It wasn't clear to me whether ticks in this context were something entirely different.


From: Thomas Rybka <try...@google.com>
To: google-visua...@googlegroups.com
Sent: Tuesday, October 8, 2013 6:49 AM
Subject: Re: [visualization-api] Re: How to format the time elapsed displayed in vAxis of Line Chart

You received this message because you are subscribed to a topic in the Google Groups "Google Visualization API" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/google-visualization-api/_cheTV4xG8Q/unsubscribe.
To unsubscribe from this group and all its topics, send an email to google-visualizati...@googlegroups.com.

Robert Mayer

unread,
Oct 15, 2013, 1:19:00 AM10/15/13
to google-visua...@googlegroups.com
I've finally managed to get the tooltip formatting the way I want it and also to render a series of graphs based on a series of data sets: http://jsfiddle.net/fERP6/12/

However, the one thing I'm currently hung up on is trying to make it work when I render the divs for the graphs dynamically, which always results in a "JavaScript runtime error: Container is not defined" error. Any thoughts on this?

- Robert -
To unsubscribe from this group and stop receiving emails from it, send an email to google-visualization-api+unsubscr...@googlegroups.com.
To post to this group, send email to google-visua...@googlegroups.com.

asgallant

unread,
Oct 15, 2013, 10:35:25 AM10/15/13
to google-visua...@googlegroups.com
Post the code you are using that generates the errors (or a jsfiddle example).

Robert Mayer

unread,
Oct 16, 2013, 12:55:37 AM10/16/13
to google-visua...@googlegroups.com
I'm dynamically creating everything in an ASP.NET app during the page load. You can see the resulting javascript (which works) in the jsfiddle link in my previous reply. What I'm trying to do is while I'm looping through my data building each array of data, create an HTML string of corresponding div tags and then pass it to the innerHTML attribute of my container div (which already exists on the page at design time). Here's the whole routine:

        private void RenderGraphs(List<BLL.Athlete> athletes)
        {
            StringBuilder script = new StringBuilder();
            StringBuilder scriptData = new StringBuilder();
            StringBuilder scriptViews = new StringBuilder();
            StringBuilder scriptViz = new StringBuilder();
            script.Append("<script type='text/javascript' src='https://www.google.com/jsapi'></script>\n");
            script.Append("<script type='text/javascript' src='http://momentjs.com/downloads/moment-with-langs.js'></script>\n");
            script.Append("<script type='text/javascript'>\n");
            script.Append("\t");
            script.Append("google.load('visualization', '1.1', {packages: ['corechart']});\n");
            script.Append("\t");
            script.Append("google.setOnLoadCallback(drawVisualization);\n\n");
            script.Append("\tfunction drawVisualization() {\n");
            script.Append("\t\t");
            script.Append("function getTooltip(dataTable, rowNum) {\n");
            script.Append("\t\t\t");
            script.Append("var min = Math.floor(dataTable.getValue(rowNum, 1)[2]/60);\n");
            script.Append("\t\t\t");
            script.Append("var sec = dataTable.getValue(rowNum, 1)[2] - (min * 60);\n");
            script.Append("\t\t\t");
            script.Append("var ms = dataTable.getValue(rowNum, 1)[3];\n");
            script.Append("\t\t\t");
            script.Append("var newtime = new moment([1900, 1, 1, 0, min, sec, ms]);\n");
            script.Append("\t\t\t");
            script.Append("return newtime.format('m:ss.SS');\n");
            script.Append("\t\t}\n\n");
            StringBuilder divHTML = new StringBuilder();
            int counter = 0;
            foreach (BLL.Athlete athlete in athletes)
            {
                if (athlete.History != null && athlete.History.Count > 1)
                {
                    counter++;    // Increment athlete counter
                    divHTML.Append("<div id='divGraph" + counter.ToString() + "' />");
                    scriptData.Append("\t\tvar data" + counter.ToString() + " = google.visualization.arrayToDataTable([\n");
                    scriptData.Append("\t\t\t['Date', '" + athlete.FullName + "'],");
                    // Build array of data points
                    StringBuilder dataPoints = new StringBuilder();
                    double floor = 999999;
                    foreach (IPerformance p in athlete.History)
                    {
                        string shortDate = String.Format("{0:M/d}", p.PerformanceDate);
                        if (dataPoints.Length > 0)
                            dataPoints.Append(",");
                        double secs = Math.Truncate(p.ResultValue);
                        int ms = Convert.ToInt32((p.ResultValue - secs) * 1000);
                        dataPoints.Append("\n\t\t\t['" + shortDate + "', [0, 0, " + secs.ToString() + ", " + ms.ToString() + "]]");
                        if (p.ResultValue < floor)
                            floor = p.ResultValue;
                    }
                    scriptData.Append(dataPoints.ToString());
                    scriptData.Append("\n\t\t]);\n\n");
                    scriptViews.Append("\t\t");
                    scriptViews.Append("var view" + counter.ToString() + " = new google.visualization.DataView(data" + counter.ToString() + ");\n");
                    scriptViews.Append("\t\t");
                    scriptViews.Append("view" + counter.ToString() + ".setColumns([0, 1, {\n");
                    scriptViews.Append("\t\t\t");
                    scriptViews.Append("calc: getTooltip,\n");
                    scriptViews.Append("\t\t\t");
                    scriptViews.Append("type: 'string',\n");
                    scriptViews.Append("\t\t\t");
                    scriptViews.Append("role: 'tooltip'\n");
                    scriptViews.Append("\t\t}]);\n\n");
                    string minValue = (floor * .9).ToString("N0");
                    string hAxis = "hAxis: { title: 'Date' }";
                    string vAxis = "vAxis: { title: 'Time', minValue: " + minValue + ", format: 'm:ss'}";
                    scriptViz.Append("\t\t");
                    scriptViz.Append("new google.visualization.LineChart(document.getElementById('divGraph" + counter.ToString() + "')).draw(view" + counter.ToString() + ", {curveType: 'none', width: 600, height: 300, " + hAxis + ", " + vAxis + "});\n");
                }
            }
            // Write out data arrays
            script.Append(scriptData.ToString());
            // Write out data views
            script.Append(scriptViews.ToString());
            // Write out calls to LineChart method
            script.Append(scriptViz.ToString());
            // Create new div for each of the graphs
            script.Append("divGraphContainer.innerHTML=\"" + divHTML.ToString() + "\";\n");
            script.Append("\t}\n");
            script.Append("</script>");
            Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "GoogleChartsScript", script.ToString(), false);
        }

asgallant

unread,
Oct 16, 2013, 9:56:01 AM10/16/13
to google-visua...@googlegroups.com
What does this script produce for javascript/HTML?

Robert Mayer

unread,
Oct 16, 2013, 10:23:17 AM10/16/13
to google-visua...@googlegroups.com
The javascript that is produced looks exactly like what is used in the jsfiddle link I provided earlier. The only difference is with the HTML where instead of having 10 pre-existing div tags on the page, I'm trying to create them dynamically and emit them to the page using javascript (see my 4th line of code from the bottom of my example).

- Robert -

asgallant

unread,
Oct 16, 2013, 10:40:41 AM10/16/13
to google-visua...@googlegroups.com
What does this line:

script.Append("divGraphContainer.innerHTML=\"" + divHTML.ToString() + "\";\n");

output in your javascript?

Robert Mayer

unread,
Oct 16, 2013, 10:54:06 AM10/16/13
to google-visua...@googlegroups.com
divGraphContainer.innerHTML="<div id='divGraph1'></div><div id='divGraph2'></div><div id='divGraph3'></div><div id='divGraph4'></div><div d='divGraph5'></div><div id='divGraph6'></div><div id='divGraph7'></div><div id='divGraph8'></div><div id='divGraph9'></div><div id='divGraph10'></div>";

Now I think I may be seeing what the problem is. I think that line needs to look like this:

document.getElementById("divGraphContainer").innerHTML= ...

I'll have to update my code this evening and give that a try.

- Robert -

Robert Mayer

unread,
Oct 17, 2013, 1:18:19 AM10/17/13
to google-visua...@googlegroups.com
Unfortunately, this change didn't solve my problem. I would really like to find a more elegant solution than hard-coding 50+ div tags on my page just in case I may need them.

asgallant

unread,
Oct 17, 2013, 9:35:36 AM10/17/13
to google-visua...@googlegroups.com
The only problem I see with the string is that the graph5 div is missing an "i" from the "id" parameter, which is causing graph5 to fail:

<div d='divGraph5'>

should be

<div id='divGraph5'>

when I replaced the divs in your jsfiddle with that bit of code, it worked: http://jsfiddle.net/asgallant/fERP6/13/

Robert Mayer

unread,
Oct 18, 2013, 12:36:59 AM10/18/13
to google-visua...@googlegroups.com
That must be just a copy-paste error. Since these div tags are being created in a loop of code, there's no way only one of them would be missing the id attribute.

asgallant

unread,
Oct 18, 2013, 9:17:17 AM10/18/13
to google-visua...@googlegroups.com
Well, if that's not the problem, then I'm stumped.  Can you post a link to the page so I can see it for myself?

Robert Mayer

unread,
Oct 21, 2013, 12:14:38 PM10/21/13
to google-visua...@googlegroups.com
I managed to solve the problem finally (and of course it was something that should've been obvious enough to me). I had to move this line of code...

script.Append("divGraphContainer.innerHTML=\"" + divHTML.ToString() + "\";\n");

... to appear before this line...

scriptViz.Append("new google.visualization.LineChart(document.getElementById('divGraph" + counter.ToString() + "')).draw(view" + counter.ToString() + ", {curveType: 'none', width: 600, height: 300, " + hAxis + ", " + vAxis + "});\n");

Naturally when the google.visualization.LineChart() method is called, any div that is referenced in that call must have already been rendered on the page.

- Robert -
Reply all
Reply to author
Forward
0 new messages