Introduction
For a not so much recent project I needed to create a standalone widget that can be displayed on any page with less effort.
You can see the result here (don't forget to view source). And if it seems interesting to you, keep on reading :)
As far as I know this can be done with iframe or javascript(jsonp), if you know any other way pls let me know.

The Idea is to create a standalone widget for your application that can be used easily on any other site.
Think of it as minifying your app where cool stuff are happening :)
So I did some research and I've decided to use pure javascript and Apotomo, because:
Fun
Apotomo - which separates the stuff
that you need and you get a much
cleaner code, hence the speed.
Apotomo comes with many othercool
stuff, I recommend that You check
out the tutorials
http://apotomo.de. I'll explain
later why I've decided to use
Apotomo :)
Javascript - I got a bit nostalgic
for writing pure js....and using a
framework may have conflicts with
the clients js, and widgets need to
be independent. The js that is used
is inspired from the twitter widget.
Implementation
Create new rails 3.0.3 app - there is an issue with json serialization in previous rails versions, the to_json method does not return the required structure.
- Add haml+compass in your Gemfile :)
Create new apotomo widget with
rails generate apotomo:widget apotomo_widget display_form --haml
Create/Use the models from your
application so you can get the data that you want to show in the widget.
I've created a simple PostLink model that has title and url.
There is also a rake task that gets the titles and urls from apotomo's feed and stores them in db.
Set up the widget display action -
see source in haml.
After the display action for the widget is defined we can add some styling, but we also want the client to be able to set a theme for our widget.
At first, I've defined different css for every theme that is used when the widget is initialized, but I've depricated that code and I've decided to put
all the styling for different themes in one file. My css skills are .... :) anyway you can check the styling for some themes that I've set here
It's js time
Ok, we've set the display action for the widget, now it's time to create a widgets controller and write some js, so:
- Create a widgets controller that
responds to the index action with js
- set: match "widgets", :to =>
"widgets#index" in routes.rb
- Create index.js.erb in
app/views/widgets directory.
class WidgetsController < ApplicationController
include Apotomo::Rails::ControllerMethods
has_widgets do |root|
root << widget(:apotomo_widget, 'apotomo_widget', :display)
end
def index
respond_to do |format|
format.js
end
end
end
You can check the end result here.
At first I've defined some helper methods that are used through the code. JsonP is used for getting data from the server..css and data that we want to display.
Every widget has it's own istance which is known by the widget_number, and it's own refresh_interval.
For this example I've added options for refresh_interval and theme to be set by the client.
After the widget is initialized the autoRefresh() function is called which updates the widget data.
So how do we get the data from the server?
This is the why apotomo part kicks in....despite the number of widgets that we can create using Apotomo, all apotomos widgets
will respond with the action that we've requested: so for example if we have lets say 3 apotomo widgets (first_widget, second_widget, third_widget)
they'll all respond to /widgets/render_event_response action where as arguments we specify on which widget(source), which action(type) we want to call.
In this example: we request for: &source=apotomo_widget&type=update
This will call the update action in apotomo_widget...which we use to execute our callback.
def update
text = params[:callback] + '(' + PostLink.all.to_json + ')'
render :text => text, :content_type => 'application/json'
end
Unfortunately Apotomo does not accept the :callback parameter :( ...usually the rails way we simply need to call:
render :json => PostLink.all, :callback => params[:callback]
The callback parameter in this example looks like this APOTOMO.Widget.updatePosts_1 for the first widget instance,
APOTOMO.Widget.updatePosts_2 for the second widget instance and so on. So this methods are executed in javascript
which updates the widget data for the widget that requested
At the end
Now all that we need to do is to include our js(path to our widgets/index action) on any page and create the widget/widgets instances. This can be done on any web page, all that
needs to be entered is:
<script type="text/javascript" src="http://widgets.jovanoski.net/widgets"></script>
And where we want the widgets to show we simply put
<script type="text/javascript">new APOTOMO.Widget({refresh_interval: 800000, theme: 'default' });</script>
<script type="text/javascript">new APOTOMO.Widget({refresh_interval: 800000, theme: 'blue' });</script>