home about

ActiveCalendar - Javascript Calendar on Rails

June 18th, 2007 cpetersen

Background

When I first started with Rails I was amazed at how quickly you can get a project up and running. Coming from a Java background I was used to configuring either Hibernate, then Spring or spending my days tweaking EJB interfaces. The scaffolding in Rails blew me away. However, the basic date and date time renderer, as I�m sure you will agree, left a little something to be desired. It�s easy to change them after the scaffold was created, but that gets old quick. To solve these problems and others, I created ActiveCalendar.

Development

The first part of the process entailed choosing the look of the date renderer. I�ve always liked the DHTML / JavaScript Calendar from Dynarch. Since it is licensed under the LGPL, it was a suitable choice. Next, I had to write the plugin. I didn�t want a generator because this plugin is designed to be a drop in replacement for the date renderer. It�s not something that has to be generated per scaffold, or configured per field, so I used rails to generate a basic plugin.
./script/generate plugin calendar
Next, I added a public directory where I stored the necessary images and JavaScript and removed all the unused directories and files. In the end I had the following directory structure:
Calendar Directory Structure
After creating the directory structure, it was time to open the hood and have a look at how rails renders fields. After a little digging, I found the FormHelper module in the following file:
/usr/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_view/helpers/form_helper.rb
This quickly led me to the DateHelper in:
/usr/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_view/helpers/date_helper.rb
Inside of the DateHelper module are methods called date_select and datetime_select, which correspond the methods used in the generated new.rhtml and edit.rhtml files. It should be noted that in the first iteration of the plugin, this is where the digging stopped. I overloaded the methods above with my own that rendered the Dynarch calendar. It worked wonderfully, until I discovered ActiveScaffold. ActiveScaffold is a great plugin that replaces the standard rails CRUD pages with a set of sexy AJAX powered pages. However, it uses a different method to render dates, so it was back to drop downs for me. Since I wanted a drop in replacement that would work with both standard Rails and ActiveScaffold, I was forced to dig deeper into the DateHelper. It turns out that the DateHelper, like the other FormHelpers, delegates calls to the InstanceTag class. In the final version of the plugin, I overloaded the to_date_select_tag and to_datetime_select_tag methods in InstanceTag and had them call my own DepotDateHelper class. ActiveScaffold must use the same InstanceTag class because once I did that, the calendar began rendering in ActiveScaffold as well. For good measure, I overloaded the date_select and datetime_select methods of DateHelper and continued to delegate to InstanceTag, but I added a couple of my own options.

Installation

You can install the plugin with the following command:
./script/plugin install http://activecalendar.googlecode.com/svn/trunk/activecalendar
Next add the appropriate javascript and stylesheets to your layout:
1
2
3
4
<%= stylesheet_link_tag "/javascripts/jscalendar-1.0/calendar-win2k-cold-1.css" %>
<%= javascript_include_tag "jscalendar-1.0/calendar.js" %>
<%= javascript_include_tag "jscalendar-1.0/lang/calendar-en.js" %>
<%= javascript_include_tag "jscalendar-1.0/calendar-setup.js" %>
That�s it, your dates should now render as JavaScript calendars.

Screen Shot


ActiveCalendar Screenshot

34 Responses to “ActiveCalendar - Javascript Calendar on Rails”

  1. Art Says:
    Do you support null dates? e.g. I have a helper module AssetsHelper def date_received_form_column(record, input_name) date_select :record, :date_received, :name => input_name, :include_blank => true end and I can't seem to use your plugin to set the date to null ..
  2. Christopher L Petersen Says:
    Thanks for the suggestion, it should work now. I removed the <macro:code lang="html"> readonly="1" </macro:code> from each of the text inputs. So now you can type in a date, or remove it entirely. It might be wise to add some date validation to your model though, since now people can input whatever they want.
  3. Gordon Erlebacher Says:
    HI, I have just installed you calendar plugin into my rails application. I restarted mongrel. The rendering of my date fields has changed as expected. However, the calendar icon is dimmed. I work on MacOSX. Any ideas? Thanks, Gordon
  4. Gordon Erlebacher Says:
    I fixed the problem. I had not added the javascript headers to the ActiveScaffold layout file. My problem now is that I have DateTime objects read in from a database, and they display properly in the text field. However, the calendar default date/time does not reflect this. I'll see what the documentation says, but if you have the answer, I will of course appreciate it. Thanks. Gordon
  5. Christopher L Petersen Says:
    Hi Gordon, You are absolutely right, that was an over sight on my part, Ruby was formatting the date differently than Javascript, so the calendar was failing to initialize properly. I just checked in a fix, basically in the date select helper, I was formatting the date with the code: <macro:code lang="ruby"> date = value(object).strftime("%a %B %d %Y") </macro:code> and I changed it to: <macro:code lang="ruby"> date = value(object).strftime("%m/%d/%Y") </macro:code> and likewise for the date time helper. Thanks for your feedback! Chris
  6. Robin Says:
    Can you give me some more details on just how to implement the calendar? Being a Rails and Ruby Nuby I'm lost as to how to override the methods you describe. If you can get me started with which files modify and put where I can hopefully figure it out. Thanks! The calendar looks awesome! And it fills a big hole in ActiveScaffold.
  7. Robin Says:
    Ah! Spoke too soon! You've already done all the work for me, I just needed to restart the server. Thanks anyway though!
  8. Peer Allan Says:
    First off, I really like this plugin. Now I'll explain the issue I ran into. I wanted to add multiple date selectors on the same page, but the catch was that they were added dynamically via ajax. The problem with this was that there was no way to override the field name. No matter how many were added they were all named the same and only one value would be submitted. To fix this I allowed the options "id" and "name" to be set in th date_select method. I changed lines 83 and 84 in calendar.rb to the following: name = options[:name].nil? ? "#{object_name}[#{method}]" : options[:name] id = options[:id].nil? ? "#{object_name}_#{method}" : options[:id] This does not break the built-in date_select if you remove the plugin, but the custom field names don't work. I realize this is likely rarely to affect anyone else and I didn'
  9. Christopher L Petersen Says:
    Thank you Peer, that's a great addition. I made your change and checked it into svn. I also made the same change to lines 90 and 91 (the datetime_select function). Thanks, Chris
  10. Mike Figley Says:
    I 'm using ActiveCalendar/jscalendar as date renderer & would like to restrict the allowable dates selected & possibly use various formatting for certain classes of dates. Has anyone figured out how to 1) pass the dateStatusHandler func via AS? (options to date_select -setDateStatusHandler ?) 2) reference the activerecord fields from inside the dateStatusHandler javascript ?
  11. Uma Shankar Ladha Says:
    Hi, Your plugin is great.. Looks nice. I have a odd requirement to do.. Basically, I want the user to only enter month and year.. My application logic is like a magazine subscription service.. Where the magazine subscription start month/year and end month/year is required. So can you let me know how can this be done usring your plugin.
  12. terry Says:
    can you provide a date_select usage and other usages? I've added several options to the standard date_select and I receive a "wrong number of arguments" message. Here's a typical scaffold creation and usage: [:month, :day, :year], :use_short_month => true, :include_blank => true %>
  13. terry Says:
    Sorry, the blog text was chopped off. this is the first have of my usage:
  14. terry Says:
    sorry, my message was chopped off a bit. Maybe this will work? date_select 'third_p_product', 'ga_date', :order => [:month, :day, :year], :use_short_month => true, :include_blank => true
  15. Christopher L Petersen Says:
    Hi All, I just checked some code into svn that I think will alleviate SOME of these issues. There have been a lot of changes in the last week or so, so instead of detailing them in a comment, I want to devote a new blog post to the changes. I will write that post this weekend, and post back here with the link. Thank you all for your comments, Chris
  16. Uma Shankar Ladha Says:
    terry, I tried adding a file with this name in my app/views/controller/_startSubMonth_form_column.rhtml. That file contains [:month, :year] %> But still that doesnt work. :(
  17. Assay Depot Development Blog &raquo; Blog Archive &raquo; ActiveCalendar Update, Validators and adde Says:
    [...] (hopefully improvements) to the code base. Rather than continue to detail them in the comments of the original post, I decided roll them up and describe them [...]
  18. Joost Van Averbeke Says:
    I am a rails and ruby newbie and I am using activescaffold to render my patient form. I have added the appropriate javascript and stylesheets to my layout after the standard activescaffold once: But when the form is rendered the calendar icon doesn't get activated. When I remove the include , the calendar pops up, but of course then I gets javascript load errors during my activescaffold rendering. What am I doing wrong ? F.Y.I.: I am using a mongrel server on Mac OS
  19. Peter Says:
    You hardcode the absolute path to the calendar.png image in calendar.rb but this is probably better as a calculated value for web apps that hang off a URL like "http://someserver/appname/". image_path seems to work under normal circumstances for this but the following change in calendar.rb doesn't seem to work. can you have a look? html \n)
  20. Peter Says:
    html \n) Sorry, I didn't embed the code in a code block. ;)
  21. Olkenava &raquo; ActiveCalendar - How to Pretty up your Rails Date Fields Says:
    [...] read more | digg story [...]
  22. Nao Says:
    It's an excellent plugin, just after 2 steps, my ActiveAcaffold application allow me to use jscalendar ! (doesn't require any modifiction of models and controllers) Thanks Chris,
  23. Nao Says:
    This is an excellent plugin, my ActiveScaffold application works with jscalendar just after 2steps of installation ! This is excat what I am looking for. Thanks Chris,
  24. Francois Says:
    Hi! I've just found your calendar, which is exactly what i needed for my project! Thank you very much! However, I am facing this "little" problem when usingit in ajax generated forms: You have a nil object when you didn't expect it! You might have expected an instance of ActiveRecord::Base. The error occurred while evaluating nil.errors ... #{RAILS_ROOT}/vendor/plugins/activecalendar/lib/assay_depot/calendar.rb:21:in `depot_date_select' #{RAILS_ROOT}/vendor/plugins/activecalendar/lib/assay_depot/calendar.rb:134:in `to_date_select_tag' #{RAILS_ROOT}/vendor/plugins/activecalendar/lib/assay_depot/calendar.rb:119:in `date_select' C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_view/helpers/date_helper.rb:417:in `date_select' I am really not sure what causes this error. I found a temporary solution, by commenting out all the lines related to "error" in the calendar.rb file, so that i can keep working on my project, but i would like to know if there's anything I can do to fix this problem... BTW, am I the only one in this situation? Thank you for any help anybody can provide :) Francois
  25. Andreas Says:
    Hi, thanks for that plug-in. But there is still problem: the internationalization seams to be buggy.... it works fine as long as i have calendar-en.js imported. When changing to another language (calendar-de.js) the calender showas up "undefined" as days... any idea? Regards Andreas
  26. Michal Says:
    Hi, Is it possible to use ActiveCalendar with Scaffolding Extensions Plugin? The problem is that it renders correctly on the scaffold view, but the datetaime input fields have name/id attributes blank. It looks like depot_date_select() and depot_datetime_select() functions receive empty options. I am new to Ruby and Rails and can't solve this problem. Regards, Michal
  27. gorenje Says:
    Cool! Seems a little repetitive (reading all the other comments) but Great!!! Love it, exactly what i was looking for :-)
  28. Mark Lynn Says:
    Hi Chris, A wonderful piece of work .. i tried a lot of plugins (calendar-date-select,dhtml-calendar) , none of them worked for me .. Now the issue is that , the im unable to select the dates .. i get an error setFullYear(2008)calendar.js (line 1817) . . . . some 200 times etFullYear(2008)calendar.js (line 1796) setDateOnly(Thu Jan 24 2008 19:57:28 GMT+0530 (India Standard Time))calendar.js (line 1721) cellClick(td.selected, mouseup clientX=0, clientY=0)calendar.js (line 592) tableMouseUp(mouseup clientX=0, clientY=0)calendar.js (line 347) d.__msh_oldSetFullYear(y); Any help would be very much appreciated Cheers, Mark
  29. Thai Says:
    Hi, I tried something like 'saldate' %> and it gives me the standard date drop-down. I can't use date_select because I don't have a model for this particular form. Any help?
  30. Thai Says:
    Sorry, The last post should read:
    'saldate' %>">
  31. mike Says:
    First off, like everybody else, thank you, I was having some problems getting dhtml_calendar to work and your plugin worked right out of the box, great news now, I am a rails/ruby newb and I am completely ignorant of javascript I would really like to make date fields in my listing editable inline.... I have taken a look at the rails recipe for modifying the default text inline editor to do drop downs and I am wondering how you would do this w/ a date field .. preferably (if possible) using your plugin... anybody know of any resources for learning how to do this? Is it as simple as copying whatever is in the view more or less to your listing? If its simple I would really appreciate a short run down of how this is done. Thanks for reading
  32. Michael Figley Says:
    Been using Christopher's great plugin for a while now! Now, i've reason to intialize 'date'. I mucked about, setting the 'date' to a string passed in as an option :value. This did initialize the calendar's text value - and messed up the calendar's year - 2186! What does object(value) do? Cheer!
  33. Ace Suares Says:
    Great work, but how to get rid of the time ?
  34. Sandra Says:
    Hi! I am a newbie to rails and like this plugin. What do I have to do if I wish to display it at a whole page without clicking on a Icon before? Thanks, Sandra

Leave a Reply