Open Flash Chart II - Javascript (Part 3)
September 23rd, 2008 by charlie
This article is a follow on to Part 1 and Part 2. In this article, I will discuss how we can change between various charts on the fly - meaning, changing the SWFObject without rerendering the page but this time we can do it without storing everything in javascript variables initially. We will use an Ajax request to grab our data off the server.
As promised there are still more topics to come on OFC and Javascript:
Here is the graph and interface we are after in this example:
Load Original Chart (Bar Graph) || Load Chart from server data (Line Graph)
More Open Flash Chart II examples.
And here is the code (the controller):
And in your view (index.html.erb):
In this example, we make use of the link_to_remote_ofc_load method that basically creates a link_to_remote along with the function that we call to load the chart data into the swfobject chart from the server. It takes three arguments, the link text, the id of the div whose swf we will load new data into and the url from which to fetch the data.
For more information on the javascript callbacks that I setup here, you will want to view the page source and read about it further over at teethgrinder's tutorial.
Good Luck!
As promised there are still more topics to come on OFC and Javascript:
- Basics of OFC and Javascript. - Discussed in Part 1
- Change data on the fly with links. - Discussed in Part 2.
- Update and Save data.
- Ajax calls to server - This article.
- Manipulate the data through an interface.
- Some really cool interfaces.
Here is the graph and interface we are after in this example:
Load Original Chart (Bar Graph) || Load Chart from server data (Line Graph)
More Open Flash Chart II examples.
And here is the code (the controller):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
class TestItController < ApplicationController def index title = Title.new("MY TITLE - original") bar = BarGlass.new bar.set_values([1,2,3,4,5,6,7,8,9]) @chart = OpenFlashChart.new @chart.set_title(title) @chart.add_element(bar) end def some_server_data title = Title.new("Multiple Lines") data1 = [] data2 = [] data3 = [] 10.times do |x| data1 << rand(5) + 1 data2 << rand(6) + 7 data3 << rand(5) + 14 end line_dot = LineDot.new line_dot.text = "Line Dot" line_dot.width = 4 line_dot.colour = '#DFC329' line_dot.dot_size = 5 line_dot.values = data1 line_hollow = LineHollow.new line_hollow.text = "Line Hollow" line_hollow.width = 1 line_hollow.colour = '#6363AC' line_hollow.dot_size = 5 line_hollow.values = data2 line = Line.new line.text = "Line" line.width = 1 line.colour = '#5E4725' line.dot_size = 5 line.values = data3 y = YAxis.new y.set_range(0,20,5) x_legend = XLegend.new("MY X Legend") x_legend.set_style('{font-size: 20px; color: #778877}') y_legend = YLegend.new("MY Y Legend") y_legend.set_style('{font-size: 20px; color: #770077}') chart =OpenFlashChart.new chart.set_title(title) chart.set_x_legend(x_legend) chart.set_y_legend(y_legend) chart.y_axis = y chart.add_element(line_dot) chart.add_element(line_hollow) chart.add_element(line) render :text => chart.to_s end end |
And in your view (index.html.erb):
1 2 3 4 5 6 7 8 9 10 11 12 |
<html>
<head>
<%= javascript_include_tag :defaults, 'swfobject' %>
</head>
<body>
<%= @chart.js_open_flash_chart_object("my_chart_js_1", 550,300) %>
<br/><br/>
<%= @chart.link_to_ofc_load("Load Original Chart", "my_chart_js_1") %> ||
<%= @chart.link_to_remote_ofc_load("Load Chart from server data", "my_chart_js_1", "/test_it/some_server_data") %>
</body>
</html>
|
In this example, we make use of the link_to_remote_ofc_load method that basically creates a link_to_remote along with the function that we call to load the chart data into the swfobject chart from the server. It takes three arguments, the link text, the id of the div whose swf we will load new data into and the url from which to fetch the data.
For more information on the javascript callbacks that I setup here, you will want to view the page source and read about it further over at teethgrinder's tutorial.
Good Luck!
September 24th, 2008 at 03:26 AM Another nice example ! Thx.
I haven't tried it yet. However as a suggestion to make the example a little funnier: can you show first the graph with multiple lines and then have the user click on some link to enable/disable one line ?
H
September 24th, 2008 at 01:42 PM Hey,
How can I use open-flash-chart to make radar charts (a.k.a. spider graphs)? Is it possible?
September 24th, 2008 at 02:34 PM
@Joe - Spider graphs are not part of Open Flash Chart.
You may want to mention it on the OFC forums, and see if Monk.e.boy has any plan of adding that to OFC.
September 24th, 2008 at 02:35 PM @Charlie, looking at your example I think some weird things are happening. On this page, when one clicks on "Load Chart from server data" a chart with multiple lines appears whereas a bar chart should appear shoudn't it ?
On a local app, under Rails 2.1, it works fine.
On a local app, under Rails 2.0.2, The first graph is not loaded. Error : ActionController::RoutingError (No route matches "/data-files/horizontal-bar-chart.txt" with {:method=>:get}): I do not know yet where this error comes from.
H
September 24th, 2008 at 02:38 PM @Joe, using scatter graphs, you might get somewhere not too far from a radar charts. Just guessing.
September 24th, 2008 at 04:43 PM
@Harry Seldon - no I am showing a line graph, not a bar graph for the ajax call, just for fun. Sorry if that is confusing. Added some text to the link to make it clear.
For the other problem - I will load 2.0.2 and see what may be causing the problem.
September 25th, 2008 at 05:47 AM
@Harry Seldon - Now I know why you asked that - the code I display is showing that it should be a bar graph, but I am somehow pulling a line graph. Sorry, I didn't match the example with the code very well.
Also, 2.0.2 works for me. Anything that says "data-files" has to do with the AS. So hmm... double check your swf file ?
September 25th, 2008 at 08:33 AM @Charlie, Indeed the example is quite confusing, isn't it simple to make the correction and have the example matching the code ? If it is simple I strongly encourage you to do it for sake of clarity ;-)
About the swf file, is it a file that is regularly updated when you update OFCII ? In that case it is indeed probably the problem.
Thx.
September 25th, 2008 at 10:27 AM
@Harry Seldon - yes, it is updated quite often.
Let me know.
September 26th, 2008 at 12:26 AM @Charlie, that was indeed the problem. I got this trouble updating OFCII because for some reason the command
script/plugin install git://github.com/pullmonkey/open_flash_chart.git does not work in my Rails 2.0.2 app, I get the error : svn: This client is too old to work with working copy.
Is git working on Rails 2.0.2 or only 2.1 ?
Else my app might be not so well updated to Rails 2.0.2.
Thx for having updated the example (even if I prefered the previous version with 2 similar charts which shows better the interest of the example).
September 26th, 2008 at 09:28 AM
@Harry Seldon - uses svn in 2.0.2. Write up an example you'd like to see and I will post it for you.
September 26th, 2008 at 05:06 PM OK So I am migrating to Rails 2.1.1.
And about the example, here is the example I was thinking about in my first comment : click here.
H
September 28th, 2008 at 04:23 AM Now that my app migrated to Rails 2.1.1 (or more exactly that my host made the migration to Rails 2.1.1 possible) you can see the graph of the example here : http://www.thinkosphere.com/test_it/index_js_3_line. (code is in the link I gave in my previous comment)
Charlie, you are welcome to adapt back the example to your blog.
September 28th, 2008 at 12:46 PM Charlie, I have anticipated a little on your "Update and Save data" post. I made up an example here. This one is also quite raw so I am looking forward to an example more "railsish" from you !
September 29th, 2008 at 04:19 PM
@Harry Seldon - Thanks, that will definitely come in handy.
October 8th, 2008 at 11:57 AM Charlie,
Nice work. I tried and it worked great when I have only one chart on a page. However, when I include two charts on the same page, both charts show the same content. After inspecting the html source, it turns out both javascript functions are using the same var data.
October 25th, 2008 at 01:03 AM @pdx3d, That's a good remark. Currently, the whole goal for this ajax way of displaying the charts is to dynamically modify a chart. This is possible through sharing the data variables between several graphs. Therefore, I understand there might be some problems when displaying 2 different charts.
Some work needs to be done to define a data variable different for each graph.
October 25th, 2008 at 01:09 AM @joe, you asked: "How can I use open-flash-chart to make radar charts (a.k.a. spider graphs)? Is it possible?".
As Charlie pointed it in his last post, it is now possible to make radar charts.
How ? My answer is in this radar chart example.
November 25th, 2008 at 03:07 PM Hi,
First, thanks for the great information.
I've been going through the tutorials, and they all make sense. I'm having a tough time with the Ajax one though. Probably something silly I am doing (or, perhaps not doing)...
Anyway, when I run the code, I get an error:
"no id given"
This is related to the call:
<%= @graph.js_open_flash_chart_object('my_chart_js_1', 550,300) %>
Any ideas what the problem might be?
Mike
November 25th, 2008 at 03:38 PM
@Mike C - Do you have a file/line number or trace by any chance for that error? Let me know.
November 25th, 2008 at 06:18 PM Hi there,
Thanks... here is the response I receive:
ArgumentError in
Test_it#index
Showing test_it/index.html.erb where line #8 raised:
Extracted source (around line #8):
RAILS_ROOT: C:/EclipseWorkspaceFolder/test_ofc_2Thanks,
Mike
November 25th, 2008 at 06:36 PM
@Mike C - ok, I am more interested in all the stuff after the rails root, like the full trace. So click full trace and send it on over :) I need to know where it is failing in the OFC code and this will certainly help.
November 25th, 2008 at 06:47 PM Hi,
Here's the trace:
Showing test_it/index.html.erb where line #8 raised:
Extracted source (around line #8):
RAILS_ROOT: C:/EclipseWorkspaceFolder/test_ofc_2Application Trace |
Framework Trace |
Full Trace
Request
Parameters:
Show session dump
Response
Headers:
{"cookie"=>[],"Cache-Control"=>"no-cache"}
November 26th, 2008 at 10:20 AM
@Ah ha - you are using an older version of OFC. Get the latest version.
January 7th, 2009 at 12:40 AM Hi there,
All is going well with my OFC integration efforts with Rails. Thanks very much for your site and guidance. I've noticed that my IE7 browser complains when opening OFC... It works without an error in FF. IE 7 produces the following error (do you have any ideas?):
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at ChartObjects::Factory$/MakeChart()[C:\Users\John\Documents\flex\svn\version-2\open-flash-chart\ChartObjects\Factory.as:21]
at main/build_chart()[C:\Users\John\Documents\flex\svn\version-2\open-flash-chart\main.as:463]
at main/parse_json()[C:\Users\John\Documents\flex\svn\version-2\open-flash-chart\main.as:441]
at main/xmlLoaded()[C:\Users\John\Documents\flex\svn\version-2\open-flash-chart\main.as:412]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at flash.net::URLLoader/onComplete()
Thanks again,
Mike
January 7th, 2009 at 01:31 PM
Hey Mike, sorry I do not work with the AS for the swf object. You will want to take that sort of question to monk.e.boy or post a question in the OFC Forums for him to answer.
January 8th, 2009 at 06:43 AM Hello,
thanks for this great tutorial, really a time savers :)
I have two problems i don't understand how to solve:
- how to include LOADING when data is loading in AJAX requests ??
- i can't get X-labels to be shown correctly - what i mean here is the set_steps which makes vertical lines correctly but labels are still shown. For example i want to show every 3rd label, but my chart is showing all the labels but only every 3rd vertical line...
January 9th, 2009 at 07:52 AM Hey, me again!
I have managed to solve the "problem" with loading indicator for JS calls (i edited ofc file in the plugin so it includes onLoading states....) and it works perfectly.
It seems i can't set offset and steps, tho.
Can anyone help me with this?
January 9th, 2009 at 01:01 PM I was looking into trying to hook into the "Save Image Locally" that is displayed when you right-click on the Flash, as described at http://teethgrinder.co.uk/open-flash-chart-2/save-image-js.php
That seems to require that you know the name of the div in which the OFC is inserted. The standard chart.render method of inserting the OFC into the page makes up a random div name (in open_flash_chart_object.rb). So I was looking at this JavaScript method, as it lets you pick the div name. I managed to get it working, but in the process found that this method of using JavaScript to insert charts breaks if you have more than one chart on the page, as to_open_flash_chart_data (called by js_open_flash_chart_object) always stores the data in a variable named 'data', so the data for all of the charts is overwritten by the last chart displayed.
So it looks like at the moment I'm stuck with choosing between multiple charts on the page via chart.render, or one chart with working export to an image via JavaScript. Would it be possible to specify the desired div name when setting up a chart and/or modifying to_open_flash_chart_data to use a variable name that is unique (possibly by having js_open_flash_chart_object pass it the div name and using that to compose a variable name)?
Thanks,
Jason
January 9th, 2009 at 04:26 PM
@Jason - I've run into this problem myself, but haven't come up with a backwards compatible solution quite yet.
I am thinking:
open_flash_chart_object_from_hash(options) and one of them would be the ability to pass in div name ... This will be a little more flexible and hopefully we can just move to that format over time. I will give it some thought this weekend.
The other thing I have done in the past is modify open_flash_chart_object to return the random div_name, return [html, div_name] and then in my controller I would receive: @graph, @graph_div_name = open_flash_chart_object(....) Then for js manipulation I would have what I needed.
January 9th, 2009 at 04:50 PM
@Mitja - would you mind posting some example code so I can reproduce the problem you are having with the offset and steps?
January 10th, 2009 at 08:20 AM Hey Charlie,
basically I just took the code from this article's example, but filled in my own data and labels (both coming from a AR query ).
What i am trying is just to add something like this (last row) to your existing code:
x = XAxis.new
x.labels = dates
x.set_colour("#000000")
x.set_size(100)
x_legend = XLegend.new("Something")
x_legend.set_style('{font-size: 14px; color: #00345F}')
x.set_steps(2)
What happens is that vertical lines are indeed shown on every second label, but i would also like to show only every second label...
My labels are populated with a timestamps of the data shown on the chart and if i am doing a chart with many of these records, every timestamp is too much to show (timestamps are in a HH:MM format).
What i get at the end is a black line at the x-axis which are all the labels, but very close to each other :)
Thanks for any help!
February 17th, 2009 at 02:03 PM Great stuff guys!
How would I go about loading the graph data every n seconds instead of having to click the "Load Chart from server data (Line Graph)" link? I've got this example working and would like to take it one step further.
Thanks!
March 18th, 2009 at 04:57 PM what's the minimum rails requirement?
Can this work with rails 1.2.3? I'm using that successfully with version 1 of these charts...
March 18th, 2009 at 08:09 PM
@Davis - I can't think of anything off the top of my head that would prevent it from working in any version of rails. the only thing that might cause a problem would be JSON, but can probably be fixed by loading a gem. Let me know how it goes.
March 19th, 2009 at 06:59 AM I was able to run it using Rails 1.1.6.
March 20th, 2009 at 06:28 AM Hi,
I don't understand how to change alpha on bar charts... I didn't find any "set_alpha" function, and wasn't able to modify the source. Any help would be greatly appreciated.
March 20th, 2009 at 10:46 AM
@Raphael - it is all done through method_missing(). bar.alpha = '0.2' or bar.set_alpha('0.2') are interchangeable this way. It may be numeric instead of string. Let me know how it goes.
March 23rd, 2009 at 05:49 AM It doesn't work... Using "method_missing().bar.alpha = '0.2'" results in an error: "no id given"
Using "bar.set_alpha('0.1')" doesn't causes an error, and the json seems generated correctly, but the bar keeps their default opacity.
Here is the json generated:
Now here is the complete code:
I'm using Rails 1.1.6 (and if the error comes from here, it's problematic because I'm not sure to be able to upgrade my application now...)
I've tried with numeric and string values.
March 23rd, 2009 at 10:14 AM
@Raphael - Sorry for the confusion. I use method_missing() - the white space made it look like I said method_missing().bar ... but really i was suggesting that bar.set_alpha("0.1") is not a method that I define, I let method_missing() handle it. See here - http://github.com/pullmonkey/open_flash_chart/blob/81cd40cc5d4221644122768151fa4ef59d4d33d0/lib/open_flash_chart/base.rb Look at the bottom and that is how method_missing is being used.
Your JSON looks correct, so make sure that you have the latest OFC flash (swf) file.
March 23rd, 2009 at 10:41 AM Ok, thanks for your explanation. I got the OFC flash file by installing your plugin a few days ago (less than one week).
Which file should I take, then? (And where?)
Thank you in advance.
March 24th, 2009 at 03:12 AM Update: I got the latest version and it still doesn't work.
I tried with the "test it" example, using Bar instead of BarGlass, and running it with Rails 2.1.0, and I still cannot change the alpha.
I finally tried with other chart types (other bars, lines, pies...) and I was unable to change the alpha for any of these charts.
The JSON produced in each case seems ok.
March 24th, 2009 at 01:28 PM
@Raphael - we need to find an example for you. I have not found any examples since OFC2 for alpha. Look around here for an example - http://teethgrinder.co.uk/open-flash-chart-2/ If you find an example, post the link here and I will do the rails version for you.
March 25th, 2009 at 04:32 AM Ok, I think I solved the problem.
In the current version of your plugin, the swf file doesn't use the alpha values... So the JSON *was* correct, but it just had no effect. (Note that the alpha has to be in numerical value, not string.)
I then tried to download the latest OFC2 swf file ("Ichor" version), but feeding it with my old data returned a blank graph (not even axes, just plain white).
It took me a while to find out which part of the data was incompatible with the Ichor version, but I finally found it: you can't set axes labels to nil values anymore, you have to use empty strings.
So, instead of doing this with the current version of your plugin:
<filter:code>
x_axis = XAxis.new
x_labels = XAxisLabels.new
x_labels.labels = ['1', '2', nil, '4']
x_axis.set_labels(x_labels)
< /filter:code>
You have to do this with the Ichor version of the swf file:
<filter:code>
x_axis = XAxis.new
x_labels = XAxisLabels.new
x_labels.labels = ['1', '2', '', '4']
x_axis.set_labels(x_labels)
< /filter:code>
Thanks for your help, and I hope this will help others too :)
March 25th, 2009 at 05:26 AM One last update: with the Ichor version, the line-based charts don't work anymore, because of a different way to build them. This is what can be read on the download page of OFC2, section "Changes since V2 Hyperion" :
"The PHP code has changed, the way line charts are built is different. This is the old way:
$line_1 = new line_dot();
$line_1->set_values( $data_1 );
$line_1->set_halo_size( 0 );
$line_1->set_width( 2 );
$line_1->set_dot_size( 4 );
This is the new:
$line_1_default_dot = new dot();
$line_1_default_dot->colour('#f00000');
$line_1 = new line();
$line_1->set_default_dot_style($line_1_default_dot);
$line_1->set_values( $data_1 );
$line_1->set_width( 1 );"
So I must currently use the old swf file for line charts, and the Ichor swf file for my bar charts with custom alpha value.
Charlie, do you know when you will be able to update your plugin in order to use it with the Ichor version?
I'll try to do it myself but I'm not sure to be able to do it.
March 25th, 2009 at 08:43 AM
@Raphael - Good work and thanks for the update!
You can do what you want (switch between swf files) right now :)
Check out this blog post.
The gist of it is that you can pass in the swf file you want to use for a particular chart. So you can use any variation of the original swf file as I did in that example. See this line:
@graph = open_flash_chart_object(600,300,"/test_it/graph_code", true, "/", "open-flash-chart-bar-clicking.swf")
Look at the last parameter. "open-flash-chart-bar-clicking.swf" This points to the file I have sitting in my docroot (RAILS_ROOT/public). If it is left blank, it will default to the original open-flash-chart.swf.
Details such as this are documented here.
Let me know if this helps.
March 25th, 2009 at 09:31 AM Actually I was already doing that ;-)
But I'd like to use the latest version only, that's why I was wondering if you planned to update your plugin.
Thank you!
March 25th, 2009 at 10:29 AM
@Raphael - ah ok. You mean you just want the plugin to come with a different version of the swf file? I am not sure how that would help you? If you are just tired of specifying that swf file you want, then you can just rename it to the default name and put it in your public dir and never worry about it again - even after updating the plugin. Or am I missing something?
March 26th, 2009 at 02:33 AM Well, there are mainly two reasons:
- The users of my website would have two download only one swf file, so it would decrease my bandwidth usage (and theirs)
- The latest swf file has some bugfixes and new features.
That's all :)
March 26th, 2009 at 08:24 AM
@Raphael - ok, one question then :)
1) At what point are your users downloading both swf files?
March 26th, 2009 at 10:18 AM
I'm providing them graphs for viewing their stats on a weekly and monthly basis.
The monthly graph uses line charts (the swf file currently in your plugin), one value for each day.
The weekly graph uses bar charts (the Ichor version of the swf file), one value for each hour.
More graphs are likely to come.
So the users use both graphs, and their browser has to download both swf files in order to view them...
March 26th, 2009 at 11:37 AM
@Raphael - so what you are saying is that there is not a single version of the swf file that can do everything you need. What can I do to help that? I thought you were suggesting that I package the plugin with the Ichor swf. But you say that you use the original swf for your line charts. I am not sure how you feel I can help ... but am open for ideas. Just note that I don't maintain the swf files, just the plugin.
March 26th, 2009 at 02:29 PM
I'd simply like to use the new swf file for my line charts, so that users would have to download only one swf file, but the methods in the current version of your plugin doesn't allow to use the line charts of the new swf file.
March 26th, 2009 at 03:34 PM
@Raphael - Ah, I see what is going on :) I thought Ichor was some guy you got a swf file from, however it *IS* the currently official swf file - sorry about that - I have been out of the loop for quite some time. Thanks for being so patient! And now I understand perfectly :)
April 1st, 2009 at 02:33 PM Sometimes I feel a little dense, so if the answer is trivial or obvious, please be patient. In my project I am submitting data to the server through the form_remote_tag and would like to have the response processed similar to the example above. My question is, how would I need to modify this example to fit those requirements? Why I am asking such a broad question is because, I am not sure what detail I am missing.