views:

112

answers:

1

Hi all,

I've been trying to design a widget for my rails app and unfortunately find myself lacking in Javascript skills...

I was able to create a widget based on the short guide from this blog: http://www.eduvoyage.com/2008/8/3/widget-with-rails

But what I need is a little different from what they describe.

If you had a digg or tweetmeme-like application with votes for a particular article, how could you create a widget to display the votes?

Let's say that an article model has a name, a link and a votes_counter.

This is what I tried:

In the articles controller:

    def index
@article = Article.find_by_link("#{request.url}")
 respond_to do |format|
 format.js
     format.html
    end
end

In index.js.erb:

var txt = ''

txt += "<div id='article_widget'>";
txt += "<h2>Article vote count:</h2>";
txt += "<%= escape_javascript(@article.votes)  %>";
txt += "</div>";

document.write(txt);

The problem I'm getting is that the @article turns out to be nil. To figured out what was wrong I added this bit of code to my javascript file:

txt += "<%= escape_javascript(request.url) %>";

The result on the screen was: h ttp://localhost:3000/articles.js. Obviously I wouldn't be able to use the find_by_link method when it just returns the path of the javascript file. What I'd like in the find_by_link method is the current url in the browser.

Or is there a better way to do this?

Is there a way to let my rails app know exactly which article is being referenced? I'm stumped.

+2  A: 

Many widgets actually run two pieces of code: Something like this:

Widget code on client site:

<script src="http://yourdomain.com/javascripts/widget.js" type="text/javascript"></script>

widget.js:

(function(){
  var loc   = window.location,
      title = document.title,
      href  = 'http://yourdomain.com/widgets/count.js?url=' + encodeURIComponent( loc );

  href = href + '&title=' + encodeURIComponent( title );

  var script  = document.createElement('script');
  script.src  = href;
  script.type = "text/javascript";

  // Call your real script:
  document.documentElement.firstChild.appendChild( script );
})();

You could then access it in Rails by using params[:url] and params[:title]

This is not a complete solution as your second script would not have context as to where to place the widget. Most of the big ones (digg, tweetmeme) use document.write but I have a personal aversion to using it.

If I were building this whole thing, I would probably have an empty div with an id be part of the widget code you have the user copy, or I might use document.write in the first js file to write out a holding div that the second script can populate via getElementById.

One final word of warning: Be sure to clean the URL before matching. You don't want http://domain.com and http://domain.com/ providing two different matches.

Doug Neiner
This seems like a good recommendation, although when I tried to see what I got when I entered txt += "<%= escape_javascript(params[:url]) %>"; The url repeated itself ad infinitum. Not sure what to do. I'm extremely new to programming and only really know ruby, rails and SQL. I thought a widget would be simple enough that I wouldn't have to learn javascript, should I go get a book and learn it just to make one widget?
Kenji Crosland
Hmm. Not sure what you mean by repeated itself. It kept reloading the same page? Or it printed a non-ending line of URL's and froze the server?
Doug Neiner
It printed the non-ending line. Not sure why.
Kenji Crosland
I know this was half a year ago and all but I want to really thank you for this solution. I had to start learning Javascript to make sense of it though. Finally, I got it all to work. The widget is far from complete, but at least I got started. Thanks so much for for your help!
Kenji Crosland
@Kenji, I am glad you got it started... hope it works out for you!
Doug Neiner