<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>@Lathi.net: Dynamic Calendar and Appointments</title>
    <link>http://blog.lathi.net/articles/2005/09/09/dynamic-calendar-and-appointments</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>On Life, Fatherhood, Christianity, and Computers</description>
    <item>
      <title>Dynamic Calendar and Appointments</title>
      <description>&lt;p&gt;&lt;img src="http://blog.lathi.net/files/jscalendar.png" height="153" width="194" border="1" align="left" hspace="10" vspace="5" alt="Jscalendar" /&gt;
One of my clients wants to allow her customers to book appointments through her web site.  I&amp;#8217;m breaking this down into two parts: available time slots and actual appointments.  To get more &amp;#8220;Web 2.0&amp;#8221; pizzaz I&amp;#8217;m also using &lt;a href="http://www.dynarch.com/projects/calendar/"&gt;jscalendar&lt;/a&gt; from &lt;a href="http://dynarch.com"&gt;Dynarch&lt;/a&gt;.  The good news is: I don&amp;#8217;t have to wrestle with Time Zones!&lt;/p&gt;


	&lt;p&gt;First, a bit about jscalendar.  I think this is a fine piece of work.  I&amp;#8217;ve &lt;a href="http://blog.lathi.net/articles/2005/03/29/the-coolest-dhtml-calendar-ever"&gt;blogged about it before&lt;/a&gt;.  It&amp;#8217;s really cool.  Not being a real Javascript pro, it&amp;#8217;s been a little tricky to get working.  I thought I had everything good to go, but when my client looked at it, she didn&amp;#8217;t see anything.  Since this calendar is a pretty crucial part of the navigation, that was bad.  Turns out I had an extra &amp;#8217;,&amp;#8217; that was breaking the parsing in &lt;span class="caps"&gt;IE6&lt;/span&gt;.  I guess sooner or later I&amp;#8217;m going to have to get a machine to test &lt;span class="caps"&gt;IE6&lt;/span&gt; with.&lt;/p&gt;


	&lt;p&gt;As far as available time slots goes, I&amp;#8217;m using a pattern &lt;a href="http://objectwind.com/"&gt;Mark Windholtz&lt;/a&gt; told me about.  I have a &lt;code&gt;TimeX&lt;/code&gt; (Time Expression) class that responds to &lt;code&gt;occurs_on?&lt;/code&gt;.  The whole goal of the time expression is to respond true when the time expression occurs on a specific date.  I subclass this with the various types of time expressions I want to handle.  I have:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;TimeX::SingleDay&lt;/code&gt; &amp;#8211; simply occurs on a single day&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;TimeX::WDay&lt;/code&gt; &amp;#8211; occurs on a given day of the week with a start and stop date&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;TimeX::WDays&lt;/code&gt; &amp;#8211; occurs on a list of days of the week with a start and stop date.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;As it turns out &lt;code&gt;TimeX::WDay&lt;/code&gt; was just an incremental piece before I got to &lt;code&gt;TimeX::WDays&lt;/code&gt;; however, &lt;code&gt;TimeX::WDays&lt;/code&gt; contains a list of &lt;code&gt;TimeX::Wday&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;I didn&amp;#8217;t make the &lt;code&gt;TimeX&lt;/code&gt; classes derive from &lt;code&gt;AcriveRecord&lt;/code&gt;.  What I did was create a &lt;code&gt;TimeExpression&lt;/code&gt; class that&amp;#8217;s derive from &lt;code&gt;AcriveRecord&lt;/code&gt; and contains a &lt;code&gt;TimeX&lt;/code&gt;.  The &lt;code&gt;TimeX&lt;/code&gt; is stored in the database with &lt;code&gt;YAML.dump&lt;/code&gt; on &lt;code&gt;before_save&lt;/code&gt; and then &lt;code&gt;YAML.load&lt;/code&gt; when it&amp;#8217;s used.  The &lt;code&gt;TimeExpression&lt;/code&gt; actually has the available time&amp;#8217;s &lt;code&gt;start_time&lt;/code&gt; and &lt;code&gt;end_time&lt;/code&gt;.  I suppose it&amp;#8217;d be possible to add a &lt;code&gt;to_vCalendar&lt;/code&gt; method on the &lt;code&gt;TimeExpression&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;This whole setup seems more complex than it should.  Each of the pieces works simply enough though.  I think I&amp;#8217;m mainly struggling with vocabulary.  There are so many pieces that are very similar with similar names it&amp;#8217;s easy to get confused.  What I&amp;#8217;m really struggling with vocabulary-wise is that I&amp;#8217;ve named &amp;#8220;available time slots&amp;#8221; &lt;code&gt;TimeExpression&lt;/code&gt;.  I don&amp;#8217;t really want to live with either &lt;code&gt;TimeExpression&lt;/code&gt; or &lt;code&gt;AvailableTimeSlot&lt;/code&gt;.  I&amp;#8217;d like to call it &lt;code&gt;OfficeHours&lt;/code&gt;, but that has some pluralization problems.  Plus, my client didn&amp;#8217;t like that either as her office hours are actually more than these available time slots.  I&amp;#8217;m sure I&amp;#8217;ll refactor this sooner or later.&lt;/p&gt;


	&lt;p&gt;I stole some code from &lt;a href="http://typo.leetsoft.com/"&gt;Typo&lt;/a&gt; for doing &amp;#8220;quick posts&amp;#8221;.  The whole interface is driven from a &lt;code&gt;show&lt;/code&gt; action that lists the &lt;code&gt;TimeExpressions&lt;/code&gt; for a single day.  The jscalendar is there to allow her to change days.  I&amp;#8217;ve got a hidden div with the &amp;#8220;new time expression&amp;#8221; form in it.  Using &lt;code&gt;Effect.BlindUp&lt;/code&gt; and &lt;code&gt;Effect.BlindDown&lt;/code&gt; I can reveal and hide the form as needed.  The form submits to the &lt;code&gt;new&lt;/code&gt; action which redirects to the &lt;code&gt;show&lt;/code&gt; action when it succeeds.  What I haven&amp;#8217;t done is passed everything around properly so the errors from the &lt;code&gt;new&lt;/code&gt; action are displayed on the resulting &lt;code&gt;show&lt;/code&gt; action view.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s the other thing I haven&amp;#8217;t done.  I haven&amp;#8217;t setup any forms for editing the &lt;code&gt;TimeExpression&lt;/code&gt; once they are created.  I suppose I&amp;#8217;ll end up with hidden forms for each of the items.  That just seems a little heavy.&lt;/p&gt;


	&lt;p&gt;One other thing I haven&amp;#8217;t done is allow &lt;code&gt;delete&lt;/code&gt; to only delete a single occurance of the &lt;code&gt;TimeExpression&lt;/code&gt; or all future occurances or all occurances all together.  I have the &lt;code&gt;TimeX::WDay&lt;/code&gt; class with a list of exception days.  I guess it&amp;#8217;d be easy enough to just move the end date for the &amp;#8220;delete all future occurances&amp;#8221; case.  What I&amp;#8217;m not sure about is the UI for doing this.  I&amp;#8217;d like to just put &lt;code&gt;:confirm =&amp;gt; true&lt;/code&gt; on the delete link; but that won&amp;#8217;t work for as many options as I have.  I need to know JS better.&lt;/p&gt;


	&lt;p&gt;Oh, and I have no code for the end customers to actually add appointments and then present them with the time slots not booked.  Back to work&amp;#8230;&lt;/p&gt;</description>
      <pubDate>Fri, 09 Sep 2005 08:30:38 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:68b0a6a27e06b8c5251c83f9b1130fde</guid>
      <author>Doug</author>
      <link>http://blog.lathi.net/articles/2005/09/09/dynamic-calendar-and-appointments</link>
      <category>Programming</category>
      <category>Software</category>
      <category>Ruby on Rails</category>
      <category>Rails</category>
      <category>Calendars</category>
      <category>Appointments</category>
    </item>
    <item>
      <title>"Dynamic Calendar and Appointments" by Jim Weirich</title>
      <description>&lt;p&gt;Have you seen the temporal expression library available on RubyForge: &lt;a href="http://runt.rubyforge.org" rel="nofollow"&gt;http://runt.rubyforge.org&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Fri, 09 Sep 2005 14:14:49 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:88d0dc8a-67cf-4bfd-9bf7-2c450a82bc2a</guid>
      <link>http://blog.lathi.net/articles/2005/09/09/dynamic-calendar-and-appointments#comment-29</link>
    </item>
  </channel>
</rss>

