Archive for the ‘Javascript’ Category:
11 Aug
Over 4 years ago, I wrote a tutorial for doing dynamic (cascading) select boxes.
Still getting comments and emails to this day. Mostly asking how to get this working with rails 3, which has moved from prototype to jquery.
So here's a tutorial for getting 3 select boxes to trigger updates for each other.
First set things up:
I just used the html5 haml twitter bootstrap, etc template. Really useful.
If you need data, here's what I used - put this in your db/seeds.rb file:
Next, setup your model associations:
Genres have many artists.
Artists have many songs.
Genres have many songs through artists.
I'm just using a home controller to setup variables for the index page as well as setup variables for use in the dynamic updating:
Now the view just has the 3 select boxes and the unobtrusive javascript (triggered onchange) to make the ajax calls for updating:
We need our rjs files for updating the select boxes, one for the songs (when artist changes) and one for the artists and songs (when genre changes):
Our routes are simple:
That's it.
UPDATE: Here's an erb alternative for index.html.
And the js.haml can be converted to js.erb by taking #{...} and converting to <%= ... %> :
06 Jan
I was asked recently (well sort of) to give an example of saving an image to the server. If you look at teethgrinder's example for this, you will see that he has made available an external interface to do just that - POST your graph as png raw data to your server for storage. This has many benefits such as saving the image for use in a PDF report or for printing, since we know at times it is a bit troublesome to print the embedded flash object.
I think the main problem people are having with this is the receiving of the image data post - see the upload_image method below. Also, teethgrinder's example never really says where to make the post_image() call. So I touch on both in the code below.
Here is an example of the png that is saved when I did this for the chart in the previous example:
Well, let's just get right in to the code.
The controller contains the same code as my last post with only a few minor changes to the index method and the addition of the upload_image method.
In the controller, I have this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
class TestItController < ApplicationController
def index
# note the user of open_flash_chart_object_from_hash instead of just open_flash_chart_object
# this allows you to pass in the id of the div you want the the chart to be in
# this is useful for when we need to findSWF by this id
@graph = open_flash_chart_object_from_hash("/test_it/chart", :div_name => "my_chart")
end
# added to recieve the post data for the OFC png image of the OFC graph
def upload_image
name = "tmp_image.png" || params[:name]
# the save_image method that is provided by the OFC swf file sends raw post data, so get to it like this
data = request.raw_post
File.open("#{RAILS_ROOT}/tmp/#{name}", "wb") { |f| f.write(data) } if data
render :nothing => true
end
def chart
# same code from here - http://pullmonkey.com/2010/01/05/open-flash-chart-ii-x-axis-date-and-time/
...
end
end
|
So just note the use of open_flash_chart_object_from_hash() in the index method, this way we can pass in the id of the div.
In the view, I have this:
1
2
3
4
5
|
<%= javascript_include_tag 'swfobject.js' %>
<%= @graph %>
<%= save_as_image("http://localhost:3000/test_it/upload_image?name=tmp.png", :id => "my_chart") %>
<br/>
<%= button_to_function "Save Image", "post_image()" %>
|
Really the only difference from what we would normally have in our view is that I am using the save image setup method that was added to the open flash chart ruby on rails plugin in the last couple hours (as of this post). The save_image method takes some arguments, mainly the url to post the image data to and the id of the chart we setup in the controller.
23 Sep
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):
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!
22 Sep
This article is a follow on to Part 1. In this article, I will discuss how we can change between various charts on the fly - meaning, changing the SWFObject without sending a request or rerendering the page.
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 Chart 1||Load Chart 2||Load Chart 3
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
|
class TestItController < ApplicationController
def index
title = Title.new("MY TITLE")
bar = BarGlass.new
bar.set_values([1,2,3,4,5,6,7,8,9])
chart1 = OpenFlashChart.new
chart1.set_title(title)
chart1.add_element(bar)
title = Title.new("MY TITLE 2")
bar = BarGlass.new
bar.set_values([1,2,3,4,5,6,7,8,9].reverse)
chart2 = OpenFlashChart.new
chart2.set_title(title)
chart2.add_element(bar)
title = Title.new("MY TITLE - some new data")
bar = BarGlass.new
bar.set_values([1,3,2,5,4,7,6,9,8])
chart3 = OpenFlashChart.new
chart3.set_title(title)
chart3.add_element(bar)
@charts = [chart1, chart2, chart3]
end
end
|
And in your view (index.html.erb):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<html>
<head>
<%= javascript_include_tag :defaults, 'swfobject' %>
</head>
<body>
<%= @charts.first.js_open_flash_chart_object("my_chart_js_2", 550,300) %>
<br/><br/>
<% @charts.each_with_index do |chart, i| %>
<%= chart.link_to_ofc_load("Load Chart #{i + 1}", "my_chart_js_2") %>
<%= " || " if i < @charts.size - 1 %>
<% end %>
</body>
</html>
|
In this example, we make use of the link_to_ofc_load method that basically creates a link_to_function along with the function that we call to load the chart data into the swfobject chart. It takes two arguments, the link text and the id of the div whose swf we will load new data into.
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!
21 Sep
This article (and the work behind it -- meaning get the latest from github) is generously sponsored by Harry Seldon who wants to be able to pass data around using javascript. There are quite a few benefits to this, learn more from teethgrinder's tutorial on the same topic.
This example opens up a lot of possibilities and I thank Harry for pointing me to it. So more to come on OFC and Javascript. For a taste of what is to come, check these out:
Here is the graph we are after in this example:
More Open Flash Chart II examples.
And here is the code (the controller):
1
2
3
4
5
6
7
8
9
10
11
|
class TestItController < ApplicationController
def index
title = Title.new("MY TITLE")
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
end
|
Notice that I do not render the chart object, however I turn it into an instance variable for use in our javascript rendering of our chart.
And in your view (index.html.erb):
1
2
3
4
5
6
7
8
9
|
<html>
<head>
<%= javascript_include_tag :defaults, "swfobject" %>
</head>
<body>
<%= @chart.js_open_flash_chart_object("my_chart_js_1", 550,300) %>
</body>
</html>
|
I do a lot behind the scenes but if you look, you will see a few new things here.
- The data comes from the @chart.js_open_flash_chart_object(...) call which sets up a few javascript callback methods to send the data to the SWF object. It takes 3 required arguments div_name (the id of the div that houses the chart), width and height and one optional argument base_url which defaults to "/".
- If you look at the HTML source, it is quite a bit different, we simply embed the SWF object. We do not need to point to the data method since there actually isn't one.
- One difference between this Rails example and php example (from teethgrinder) is that prototype which comes standard with rails, has a JSON implementation for javascript, so we do not need the json2.js file, but make sure to include prototype.js in your apps.
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! and Harry, I hope this helps, otherwise please drop me a line.