<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>app/controllers/recurring_todos_controller.rb</filename>
    </added>
    <added>
      <filename>app/helpers/recurring_todos_helper.rb</filename>
    </added>
    <added>
      <filename>app/models/recurring_todo.rb</filename>
    </added>
    <added>
      <filename>app/views/recurring_todos/_edit_form.html.erb</filename>
    </added>
    <added>
      <filename>app/views/recurring_todos/_recurring_todo.html.erb</filename>
    </added>
    <added>
      <filename>app/views/recurring_todos/_recurring_todo_form.erb</filename>
    </added>
    <added>
      <filename>app/views/recurring_todos/create.js.rjs</filename>
    </added>
    <added>
      <filename>app/views/recurring_todos/destroy.js.rjs</filename>
    </added>
    <added>
      <filename>app/views/recurring_todos/edit.js.rjs</filename>
    </added>
    <added>
      <filename>app/views/recurring_todos/index.html.erb</filename>
    </added>
    <added>
      <filename>app/views/recurring_todos/new.html.erb</filename>
    </added>
    <added>
      <filename>app/views/recurring_todos/show.html.erb</filename>
    </added>
    <added>
      <filename>app/views/recurring_todos/toggle_check.js.rjs</filename>
    </added>
    <added>
      <filename>app/views/recurring_todos/toggle_star.js.rjs</filename>
    </added>
    <added>
      <filename>app/views/recurring_todos/update.js.rjs</filename>
    </added>
    <added>
      <filename>db/migrate/039_create_recurring_todos.rb</filename>
    </added>
    <added>
      <filename>public/images/add.png</filename>
    </added>
    <added>
      <filename>public/images/recurring16x16.png</filename>
    </added>
    <added>
      <filename>public/images/recurring24x24.png</filename>
    </added>
    <added>
      <filename>public/images/recurring_menu16x16.png</filename>
    </added>
    <added>
      <filename>public/images/recurring_menu24x24.png</filename>
    </added>
    <added>
      <filename>public/images/trans70.png</filename>
    </added>
    <added>
      <filename>test/fixtures/recurring_todos.yml</filename>
    </added>
    <added>
      <filename>test/functional/recurring_todos_controller_test.rb</filename>
    </added>
    <added>
      <filename>test/unit/recurring_todo_test.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -20,4 +20,4 @@ For those upgrading, change notes are available in /doc/CHANGELOG. If you are th
 
 While fully usable for everyday use, Tracks is still a work in progress. Make sure that you take sensible precautions and back up all your data frequently, taking particular care when you are upgrading.
 
-Enjoy being productive!
\ No newline at end of file
+Enjoy being productive!</diff>
      <filename>README</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,6 @@
-# The filters added to this controller will be run for all controllers in the application.
-# Likewise will all the methods added be available for all controllers.
+# The filters added to this controller will be run for all controllers in the
+# application. Likewise will all the methods added be available for all
+# controllers.
 
 require_dependency &quot;login_system&quot;
 require_dependency &quot;tracks/source_view&quot;
@@ -47,11 +48,12 @@ class ApplicationController &lt; ActionController::Base
     # http://wiki.rubyonrails.com/rails/show/HowtoChangeSessionOptions
     unless session == nil
       return if @controller_name == 'feed' or session['noexpiry'] == &quot;on&quot;
-      # If the method is called by the feed controller (which we don't have under session control)
-      # or if we checked the box to keep logged in on login
-      # don't set the session expiry time.
+      # If the method is called by the feed controller (which we don't have
+      # under session control) or if we checked the box to keep logged in on
+      # login don't set the session expiry time.
       if session
-        # Get expiry time (allow ten seconds window for the case where we have none)
+        # Get expiry time (allow ten seconds window for the case where we have
+        # none)
         expiry_time = session['expiry_time'] || Time.now + 10
         if expiry_time &lt; Time.now
           # Too late, matey...  bang goes your session!
@@ -80,10 +82,10 @@ class ApplicationController &lt; ActionController::Base
   #   end
   # end
   
-  # Returns a count of next actions in the given context or project
-  # The result is count and a string descriptor, correctly pluralised if there are no
+  # Returns a count of next actions in the given context or project The result
+  # is count and a string descriptor, correctly pluralised if there are no
   # actions or multiple actions
-  #
+  # 
   def count_undone_todos_phrase(todos_parent, string=&quot;actions&quot;)
     count = count_undone_todos(todos_parent)
     if count == 1
@@ -105,9 +107,9 @@ class ApplicationController &lt; ActionController::Base
     count || 0
   end
 
-  # Convert a date object to the format specified in the user's preferences
-  # in config/settings.yml
-  #  
+  # Convert a date object to the format specified in the user's preferences in
+  # config/settings.yml
+  # 
   def format_date(date)
     if date
       date_format = prefs.date_format
@@ -118,10 +120,10 @@ class ApplicationController &lt; ActionController::Base
     formatted_date
   end
 
-  # Uses RedCloth to transform text using either Textile or Markdown
-  # Need to require redcloth above
-  # RedCloth 3.0 or greater is needed to use Markdown, otherwise it only handles Textile
-  #
+  # Uses RedCloth to transform text using either Textile or Markdown Need to
+  # require redcloth above RedCloth 3.0 or greater is needed to use Markdown,
+  # otherwise it only handles Textile
+  # 
   def markdown(text)
     RedCloth.new(text).to_html
   end
@@ -130,21 +132,19 @@ class ApplicationController &lt; ActionController::Base
     Hash[*projects.reject{ |p| p.default_context.nil? }.map{ |p| [p.name, p.default_context.name] }.flatten].to_json 
   end
   
-  # Here's the concept behind this &quot;mobile content negotiation&quot; hack:
-  # In addition to the main, AJAXy Web UI, Tracks has a lightweight
-  # low-feature 'mobile' version designed to be suitablef or use
-  # from a phone or PDA. It makes some sense that tne pages of that
-  # mobile version are simply alternate representations of the same
-  # Todo resources. The implementation goal was to treat mobile
-  # as another format and be able to use respond_to to render both
-  # versions. Unfortunately, I ran into a lot of trouble simply
-  # registering a new mime type 'text/html' with format :m because
-  # :html already is linked to that mime type and the new
-  # registration was forcing all html requests to be rendered in
-  # the mobile view. The before_filter and after_filter hackery
-  # below accomplishs that implementation goal by using a 'fake'
-  # mime type during the processing and then setting it to 
-  # 'text/html' in an 'after_filter' -LKM 2007-04-01
+  # Here's the concept behind this &quot;mobile content negotiation&quot; hack: In
+  # addition to the main, AJAXy Web UI, Tracks has a lightweight low-feature
+  # 'mobile' version designed to be suitablef or use from a phone or PDA. It
+  # makes some sense that tne pages of that mobile version are simply alternate
+  # representations of the same Todo resources. The implementation goal was to
+  # treat mobile as another format and be able to use respond_to to render both
+  # versions. Unfortunately, I ran into a lot of trouble simply registering a
+  # new mime type 'text/html' with format :m because :html already is linked to
+  # that mime type and the new registration was forcing all html requests to be
+  # rendered in the mobile view. The before_filter and after_filter hackery
+  # below accomplishs that implementation goal by using a 'fake' mime type
+  # during the processing and then setting it to 'text/html' in an
+  # 'after_filter' -LKM 2007-04-01
   def mobile?
     return params[:format] == 'm' || response.content_type == MOBILE_CONTENT_TYPE
   end
@@ -220,9 +220,9 @@ class ApplicationController &lt; ActionController::Base
     end
   end  
   
-  # Set the contents of the flash message from a controller
-  # Usage: notify :warning, &quot;This is the message&quot;
-  # Sets the flash of type 'warning' to &quot;This is the message&quot;
+  # Set the contents of the flash message from a controller Usage: notify
+  # :warning, &quot;This is the message&quot; Sets the flash of type 'warning' to &quot;This is
+  # the message&quot;
   def notify(type, message)
     flash[type] = message
     logger.error(&quot;ERROR: #{message}&quot;) if type == :error
@@ -231,5 +231,29 @@ class ApplicationController &lt; ActionController::Base
   def set_time_zone
     Time.zone = current_user.prefs.time_zone if logged_in?
   end
+
+  def create_todo_from_recurring_todo(rt, date=nil)
+    # create todo and initialize with data from recurring_todo rt
+    todo = current_user.todos.build( { :description =&gt; rt.description, :notes =&gt; rt.notes, :project_id =&gt; rt.project_id, :context_id =&gt; rt.context_id})
+    
+    # set dates
+    todo.due = rt.get_due_date(date)
+    todo.show_from = rt.get_show_from_date(date)
+    todo.recurring_todo_id = rt.id
+    saved = todo.save
+    if saved
+      todo.tag_with(rt.tag_list, current_user)
+      todo.tags.reload 
+    end
+
+    # increate number of occurences created from recurring todo
+    rt.inc_occurences
+    
+    # mark recurring todo complete if there are no next actions left
+    checkdate = todo.due.nil? ? todo.show_from : todo.due
+    rt.toggle_completion! unless rt.has_next_todo(checkdate)
+    
+    return saved ? todo : nil
+  end
   
 end</diff>
      <filename>app/controllers/application.rb</filename>
    </modified>
    <modified>
      <diff>@@ -121,6 +121,10 @@ class TodosController &lt; ApplicationController
   # 
   def toggle_check
     @saved = @todo.toggle_completion!
+    
+    # check if this todo has a related recurring_todo. If so, create next todo
+    check_for_next_todo if @saved
+    
     respond_to do |format|
       format.js do
         if @saved
@@ -235,6 +239,10 @@ class TodosController &lt; ApplicationController
     @todo = get_todo_from_params
     @context_id = @todo.context_id
     @project_id = @todo.project_id
+
+    # check if this todo has a related recurring_todo. If so, create next todo
+    check_for_next_todo
+    
     @saved = @todo.destroy
     
     respond_to do |format|
@@ -643,6 +651,19 @@ class TodosController &lt; ApplicationController
   def self.is_feed_request(req)
     ['rss','atom','txt','ics'].include?(req.parameters[:format])
   end
+  
+  def check_for_next_todo
+    # check if this todo has a related recurring_todo. If so, create next todo
+    @new_recurring_todo = nil
+    @recurring_todo = nil
+    if @todo.from_recurring_todo?
+      @recurring_todo = current_user.recurring_todos.find(@todo.recurring_todo_id)
+      if @recurring_todo.active? &amp;&amp; @recurring_todo.has_next_todo(@todo.due)
+        date = @todo.due &gt;= Date.today() ? @todo.due : Date.today()-1.day
+        @new_recurring_todo = create_todo_from_recurring_todo(@recurring_todo, date) 
+      end
+    end 
+  end
 
   class FindConditionBuilder
 
@@ -711,6 +732,6 @@ class TodosController &lt; ApplicationController
       return false if context_name.blank?
       true
     end
-      
+          
   end
 end</diff>
      <filename>app/controllers/todos_controller.rb</filename>
    </modified>
    <modified>
      <diff>@@ -47,7 +47,7 @@ module TodosHelper
       :prevent_default =&gt; true
   end    
 
-  def remote_star_icon
+  def remote_star_icon 
     str = link_to( image_tag_for_star(@todo),
       toggle_star_todo_path(@todo),
       :class =&gt; &quot;icon star_item&quot;, :title =&gt; &quot;star the action '#{@todo.description}'&quot;)
@@ -66,7 +66,7 @@ module TodosHelper
   
   def remote_edit_icon
     if !@todo.completed?
-      str = link_to( image_tag_for_edit,
+      str = link_to( image_tag_for_edit(@todo),
         edit_todo_path(@todo),
         :class =&gt; &quot;icon edit_icon&quot;)
       set_behavior_for_edit_icon
@@ -205,12 +205,12 @@ module TodosHelper
     javascript_tag str
   end
   
-  def item_container_id
+  def item_container_id (todo)
     if source_view_is :project
-      return &quot;p#{@todo.project_id}&quot; if @todo.active?
-      return &quot;tickler&quot; if @todo.deferred?
+      return &quot;p#{todo.project_id}&quot; if todo.active?
+      return &quot;tickler&quot; if todo.deferred?
     end
-    return &quot;c#{@todo.context_id}&quot;
+    return &quot;c#{todo.context_id}&quot;
   end
 
   def should_show_new_item
@@ -272,8 +272,8 @@ module TodosHelper
     image_tag(&quot;blank.png&quot;, :title =&gt;&quot;Delete action&quot;, :class=&gt;&quot;delete_item&quot;)
   end
   
-  def image_tag_for_edit
-    image_tag(&quot;blank.png&quot;, :title =&gt;&quot;Edit action&quot;, :class=&gt;&quot;edit_item&quot;, :id=&gt; dom_id(@todo, 'edit_icon'))
+  def image_tag_for_edit(todo)
+    image_tag(&quot;blank.png&quot;, :title =&gt;&quot;Edit action&quot;, :class=&gt;&quot;edit_item&quot;, :id=&gt; dom_id(todo, 'edit_icon'))
   end
   
   def image_tag_for_star(todo)
@@ -281,4 +281,4 @@ module TodosHelper
     image_tag(&quot;blank.png&quot;, :title =&gt;&quot;Star action&quot;, :class =&gt; class_str)
   end  
   
-end
\ No newline at end of file
+end</diff>
      <filename>app/helpers/todos_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 class Tag &lt; ActiveRecord::Base
   has_many_polymorphs :taggables,
-                      :from =&gt; [:todos], 
+                      :from =&gt; [:todos, :recurring_todos], 
                       :through =&gt; :taggings,
                       :dependent =&gt; :destroy
 </diff>
      <filename>app/models/tag.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,6 +3,7 @@ class Todo &lt; ActiveRecord::Base
   belongs_to :context
   belongs_to :project
   belongs_to :user
+  belongs_to :recurring_todo
   
   STARRED_TAG_NAME = &quot;starred&quot;
   
@@ -120,4 +121,8 @@ class Todo &lt; ActiveRecord::Base
     starred?  
   end
 
+  def from_recurring_todo?
+    return self.recurring_todo_id != nil
+  end
+  
 end
\ No newline at end of file</diff>
      <filename>app/models/todo.rb</filename>
    </modified>
    <modified>
      <diff>@@ -63,6 +63,9 @@ class User &lt; ActiveRecord::Base
   has_many :todos,
            :order =&gt; 'todos.completed_at DESC, todos.created_at DESC',
            :dependent =&gt; :delete_all
+  has_many :recurring_todos,
+           :order =&gt; 'recurring_todos.completed_at DESC, recurring_todos.created_at DESC',
+           :dependent =&gt; :delete_all
   has_many :deferred_todos,
            :class_name =&gt; 'Todo',
            :conditions =&gt; [ 'state = ?', 'deferred' ],</diff>
      <filename>app/models/user.rb</filename>
    </modified>
    <modified>
      <diff>@@ -18,6 +18,7 @@ window.onload=function(){
   Nifty(&quot;div#todo_new_action_container&quot;,&quot;normal&quot;);
   Nifty(&quot;div#project_new_project_container&quot;,&quot;normal&quot;);
   Nifty(&quot;div#context_new_container&quot;,&quot;normal&quot;);
+  Nifty(&quot;div#recurring_new_container&quot;,&quot;normal&quot;);
   if ($('flash').visible()) { new Effect.Fade(&quot;flash&quot;,{duration:5.0}); }
 }
 &lt;/script&gt;
@@ -56,6 +57,7 @@ window.onload=function(){
   &lt;% if current_user.is_admin? -%&gt;
     &lt;li&gt;&lt;%= navigation_link(&quot;Admin&quot;, users_path, {:accesskey =&gt; &quot;a&quot;, :title =&gt; &quot;Add or delete users&quot;} ) %&gt;&lt;/li&gt;
   &lt;% end -%&gt;
+  &lt;li&gt;&lt;%= navigation_link(image_tag(&quot;recurring_menu16x16.png&quot;, :size =&gt; &quot;16X16&quot;, :border =&gt; 0), {:controller =&gt; &quot;recurring_todos&quot;, :action =&gt; &quot;index&quot;}, :title =&gt; &quot;Manage recurring actions&quot; ) %&gt;&lt;/li&gt;
   &lt;li&gt;&lt;%= navigation_link(image_tag(&quot;feed-icon.png&quot;, :size =&gt; &quot;16X16&quot;, :border =&gt; 0), {:controller =&gt; &quot;feedlist&quot;, :action =&gt; &quot;index&quot;}, :title =&gt; &quot;See a list of available feeds&quot; ) %&gt;&lt;/li&gt;
   &lt;li&gt;&lt;%= navigation_link(image_tag(&quot;menustar.gif&quot;, :size =&gt; &quot;16X16&quot;, :border =&gt; 0), tag_path(&quot;starred&quot;), :title =&gt; &quot;See your starred actions&quot; ) %&gt;&lt;/li&gt;
   &lt;li&gt;&lt;%= navigation_link(image_tag(&quot;stats.gif&quot;, :size =&gt; &quot;16X16&quot;, :border =&gt; 0), {:controller =&gt; &quot;stats&quot;, :action =&gt; &quot;index&quot;}, :title =&gt; &quot;See your statistics&quot; ) %&gt;&lt;/li&gt;</diff>
      <filename>app/views/layouts/standard.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -13,6 +13,7 @@
     &lt;div class=&quot;description&lt;%= staleness_class( todo ) %&gt;&quot;&gt;
       &lt;%= date_span -%&gt;
       &lt;span class=&quot;todo.descr&quot;&gt;&lt;%= h sanitize(todo.description) %&gt;&lt;/span&gt;
+      &lt;%= link_to(image_tag(&quot;recurring16x16.png&quot;), {:controller =&gt; &quot;recurring_todos&quot;, :action =&gt; &quot;index&quot;}, :class =&gt; &quot;recurring_icon&quot;) if @todo.from_recurring_todo? %&gt;
       &lt;%= tag_list %&gt;
       &lt;%= deferred_due_date %&gt;
       &lt;%= project_and_context_links( parent_container_type, :suppress_context =&gt; suppress_context, :suppress_project =&gt; suppress_project ) %&gt;</diff>
      <filename>app/views/todos/_todo.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -15,7 +15,7 @@ if @saved
       page.insert_html :top, 'display_box', :partial =&gt; 'contexts/context', :locals =&gt; { :context =&gt; @todo.context, :collapsible =&gt; true }
     else
       page.call &quot;todoItems.ensureVisibleWithEffectAppear&quot;, &quot;c#{@todo.context_id}&quot; if source_view_is_one_of(:todo, :deferred)
-      page.insert_html :bottom, item_container_id + 'items', :partial =&gt; 'todos/todo', :locals =&gt; { :parent_container_type =&gt; parent_container_type, :source_view =&gt; @source_view }
+      page.insert_html :bottom, item_container_id(@todo) + 'items', :partial =&gt; 'todos/todo', :locals =&gt; { :parent_container_type =&gt; parent_container_type, :source_view =&gt; @source_view }
       page.visual_effect :highlight, dom_id(@todo), :duration =&gt; 3
       page[empty_container_msg_div_id].hide unless empty_container_msg_div_id.nil?
     end</diff>
      <filename>app/views/todos/create.js.rjs</filename>
    </modified>
    <modified>
      <diff>@@ -1,9 +1,23 @@
 if @saved
   page[@todo].remove
   page['badge_count'].replace_html @down_count
-  page.visual_effect :fade, item_container_id, :duration =&gt; 0.4 if source_view_is_one_of(:todo, :deferred) &amp;&amp; @remaining_in_context == 0
+  
+  # remove context if empty
+  page.visual_effect :fade, item_container_id(@todo), :duration =&gt; 0.4 if source_view_is_one_of(:todo, :deferred) &amp;&amp; @remaining_in_context == 0
+  
+  # show message if there are no actions
   page[empty_container_msg_div_id].show if !empty_container_msg_div_id.nil? &amp;&amp; @down_count == 0
   page['tickler-empty-nd'].show if source_view_is(:deferred) &amp;&amp; @down_count == 0
+  
+  # show new todo if the completed todo was recurring
+  unless @new_recurring_todo.nil?
+    page.call &quot;todoItems.ensureVisibleWithEffectAppear&quot;, item_container_id(@new_recurring_todo)
+    page.insert_html :bottom, item_container_id(@new_recurring_todo), :partial =&gt; 'todos/todo', :locals =&gt; { :todo =&gt; @new_recurring_todo, :parent_container_type =&gt; parent_container_type }
+    page.visual_effect :highlight, dom_id(@new_recurring_todo, 'line'), {'startcolor' =&gt; &quot;'#99ff99'&quot;}      
+    page.notify :notice, &quot;Action was deleted. Because this action is recurring, a new action was added&quot;, 6.0
+  else
+    page.notify :notice, &quot;There is no next action after the recurring action you just deleted. The recurrence is completed&quot;, 6.0 unless @recurring_todo.nil?
+  end
 else
   page.notify :error, &quot;There was an error deleting the item #{@todo.description}&quot;, 8.0
 end
\ No newline at end of file</diff>
      <filename>app/views/todos/destroy.js.rjs</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,8 @@
 if @saved  
   page[@todo].remove
   if @todo.completed?
-    # Don't try to insert contents into a non-existent container!
+    # completed todos move from their context to the completed container
+    
     unless @prefs.hide_completed_actions?
       page.insert_html :top, &quot;completed&quot;, :partial =&gt; 'todos/todo', :locals =&gt; { :parent_container_type =&gt; &quot;completed&quot; }
       page.visual_effect :highlight, dom_id(@todo, 'line'), {'startcolor' =&gt; &quot;'#99ff99'&quot;}
@@ -9,16 +10,30 @@ if @saved
       page.show 'tickler-empty-nd' if source_view_is(:project) &amp;&amp; @deferred_count == 0
       page.hide 'empty-d' # If we've checked something as done, completed items can't be empty
     end
+    
+    # remove container if empty
     if @remaining_in_context == 0 &amp;&amp; source_view_is(:todo)
-      page.visual_effect :fade, item_container_id, :duration =&gt; 0.4
+      page.visual_effect :fade, item_container_id(@todo), :duration =&gt; 0.4
     end
+    
+    # show new todo if the completed todo was recurring
+    unless @new_recurring_todo.nil?
+      page.call &quot;todoItems.ensureVisibleWithEffectAppear&quot;, item_container_id(@new_recurring_todo)
+      page.insert_html :bottom, item_container_id(@new_recurring_todo), :partial =&gt; 'todos/todo', :locals =&gt; { :todo =&gt; @new_recurring_todo, :parent_container_type =&gt; parent_container_type }
+      page.visual_effect :highlight, dom_id(@new_recurring_todo, 'line'), {'startcolor' =&gt; &quot;'#99ff99'&quot;}      
+    else
+      page.notify :notice, &quot;There is no next action after the recurring action you just finished. The recurrence is completed&quot;, 6.0 unless @recurring_todo.nil?
+    end
+    
   else
-    page.call &quot;todoItems.ensureVisibleWithEffectAppear&quot;, item_container_id
-    page.insert_html :bottom, item_container_id, :partial =&gt; 'todos/todo', :locals =&gt; { :parent_container_type =&gt; parent_container_type }
+    # todo is activated from completed container
+    page.call &quot;todoItems.ensureVisibleWithEffectAppear&quot;, item_container_id(@todo)
+    page.insert_html :bottom, item_container_id(@todo), :partial =&gt; 'todos/todo', :locals =&gt; { :parent_container_type =&gt; parent_container_type }
     page.visual_effect :highlight, dom_id(@todo, 'line'), {'startcolor' =&gt; &quot;'#99ff99'&quot;}
     page.show &quot;empty-d&quot; if @completed_count == 0
     page[empty_container_msg_div_id].hide unless empty_container_msg_div_id.nil? # If we've checked something as undone, incomplete items can't be empty
   end
+  
   page.hide &quot;status&quot;
   page.replace_html &quot;badge_count&quot;, @down_count
   if @todo.completed?  &amp;&amp; !@todo.project_id.nil? &amp;&amp; @prefs.show_project_on_todo_done &amp;&amp; !source_view_is(:project)</diff>
      <filename>app/views/todos/toggle_check.js.rjs</filename>
    </modified>
    <modified>
      <diff>@@ -6,7 +6,7 @@ if @saved
   status_message = 'Added new context / ' + status_message if @new_context_created
   page.notify :notice, status_message, 5.0
   
-  #update auto completer arrays for context and project
+  # #update auto completer arrays for context and project
   page &lt;&lt; &quot;contextAutoCompleter.options.array = #{context_names_for_autocomplete}; contextAutoCompleter.changed = true&quot; if @new_context_created
   page &lt;&lt; &quot;projectAutoCompleter.options.array = #{project_names_for_autocomplete}; projectAutoCompleter.changed = true&quot; if @new_project_created
   if source_view_is_one_of(:todo, :context)
@@ -88,9 +88,9 @@ if @saved
       page.replace dom_id(@todo), :partial =&gt; 'todos/todo', :locals =&gt; { :parent_container_type =&gt; parent_container_type }
       page.visual_effect :highlight, dom_id(@todo), :duration =&gt; 3
     end
-    elsif source_view_is :stats
-      page.replace dom_id(@todo), :partial =&gt; 'todos/todo', :locals =&gt; { :parent_container_type =&gt; parent_container_type }
-      page.visual_effect :highlight, dom_id(@todo), :duration =&gt; 3    
+  elsif source_view_is :stats
+    page.replace dom_id(@todo), :partial =&gt; 'todos/todo', :locals =&gt; { :parent_container_type =&gt; parent_container_type }
+    page.visual_effect :highlight, dom_id(@todo), :duration =&gt; 3    
   else
     logger.error &quot;unexpected source_view '#{params[:_source_view]}'&quot;
   end</diff>
      <filename>app/views/todos/update.js.rjs</filename>
    </modified>
    <modified>
      <diff>@@ -58,6 +58,10 @@ ActionController::Routing::Routes.draw do |map|
   map.preferences 'preferences', :controller =&gt; 'preferences', :action =&gt; 'index'
   map.integrations 'integrations', :controller =&gt; 'integrations', :action =&gt; 'index'
 
+  map.resources :recurring_todos,
+    :member =&gt; {:toggle_check =&gt; :put, :toggle_star =&gt; :put}
+  map.recurring_todos 'recurring_todos', :controller =&gt; 'recurring_todos', :action =&gt; 'index'
+
   # Install the default route as the lowest priority.
   map.connect ':controller/:action/:id'
 </diff>
      <filename>config/routes.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,39 +1,90 @@
 var Login = {
-  showOpenid: function() {
-    if ($('database_auth_form')) $('database_auth_form').hide();
-    if ($('openid_auth_form')) $('openid_auth_form').show();
-    if ($('alternate_auth_openid')) $('alternate_auth_openid').hide();
-    if ($('alternate_auth_database')) $('alternate_auth_database').show();
-    if ($('openid_url')) $('openid_url').focus();
-    if ($('openid_url')) $('openid_url').select();
+    showOpenid: function() {
+        if ($('database_auth_form')) $('database_auth_form').hide();
+        if ($('openid_auth_form')) $('openid_auth_form').show();
+        if ($('alternate_auth_openid')) $('alternate_auth_openid').hide();
+        if ($('alternate_auth_database')) $('alternate_auth_database').show();
+        if ($('openid_url')) $('openid_url').focus();
+        if ($('openid_url')) $('openid_url').select();
 	new CookieManager().setCookie('preferred_auth', 'openid');
-  },
+    },
 
-  showDatabase: function(container) {
-    if ($('openid_auth_form')) $('openid_auth_form').hide();
-    if ($('database_auth_form')) $('database_auth_form').show();
-    if ($('alternate_auth_database')) $('alternate_auth_database').hide();
-    if ($('alternate_auth_openid')) $('alternate_auth_openid').show();
-    if ($('user_login')) $('user_login').focus();
-    if ($('user_login')) $('user_login').select();
+    showDatabase: function(container) {
+        if ($('openid_auth_form')) $('openid_auth_form').hide();
+        if ($('database_auth_form')) $('database_auth_form').show();
+        if ($('alternate_auth_database')) $('alternate_auth_database').hide();
+        if ($('alternate_auth_openid')) $('alternate_auth_openid').show();
+        if ($('user_login')) $('user_login').focus();
+        if ($('user_login')) $('user_login').select();
 	new CookieManager().setCookie('preferred_auth', 'database');
-  }
+    }
 }
 var TracksForm = {
-  toggle: function(toggleDivId, formContainerId, formId, hideLinkText, hideLinkTitle, showLinkText, showLinkTitle) {
-    $(formContainerId).toggle();
-    toggleDiv = $(toggleDivId);
-    toggleLink = toggleDiv.down('a');
-    if (toggleDiv.hasClassName('hide_form')) {
-      toggleLink.update(showLinkText).setAttribute('title', showLinkTitle);
-    }
-    else {
-      toggleLink.update(hideLinkText).setAttribute('title', hideLinkTitle);
-      Form.focusFirstElement(formId);
+    toggle: function(toggleDivId, formContainerId, formId, hideLinkText, hideLinkTitle, showLinkText, showLinkTitle) {
+        $(formContainerId).toggle();
+        toggleDiv = $(toggleDivId);
+        toggleLink = toggleDiv.down('a');
+        if (toggleDiv.hasClassName('hide_form')) {
+            toggleLink.update(showLinkText).setAttribute('title', showLinkTitle);
+        }
+        else {
+            toggleLink.update(hideLinkText).setAttribute('title', hideLinkTitle);
+            Form.focusFirstElement(formId);
+        }
+        toggleDiv.toggleClassName('hide_form');
+    }, 
+    get_period: function() {
+        if ($('recurring_todo_recurring_period_daily').checked) {
+            return 'daily';
+        } 
+        else if ($('recurring_todo_recurring_period_weekly').checked) {
+            return 'weekly';
+        }
+        else if ($('recurring_todo_recurring_period_monthly').checked) {
+            return 'monthly';
+        }
+        else if ($('recurring_todo_recurring_period_yearly').checked) {
+            return 'yearly';
+        }
+        else {
+            return 'no period'
+        }
+    },
+    get_edit_period: function() {
+        if ($('recurring_edit_todo_recurring_period_daily').checked) {
+            return 'daily';
+        } 
+        else if ($('recurring_edit_todo_recurring_period_weekly').checked) {
+            return 'weekly';
+        }
+        else if ($('recurring_edit_todo_recurring_period_monthly').checked) {
+            return 'monthly';
+        }
+        else if ($('recurring_edit_todo_recurring_period_yearly').checked) {
+            return 'yearly';
+        }
+        else {
+            return 'no period'
+        }
+    },
+    hide_all_recurring: function () {
+        $('recurring_daily').hide();
+        $('recurring_weekly').hide();
+        $('recurring_monthly').hide();
+        $('recurring_yearly').hide();
+    },
+    hide_all_edit_recurring: function () {
+        $('recurring_edit_daily').hide();
+        $('recurring_edit_weekly').hide();
+        $('recurring_edit_monthly').hide();
+        $('recurring_edit_yearly').hide();
+    },
+    toggle_overlay: function () {
+        el = document.getElementById(&quot;overlay&quot;);
+        el.style.visibility = (el.style.visibility == &quot;visible&quot;) ? &quot;hidden&quot; : &quot;visible&quot;;
     }
-    toggleDiv.toggleClassName('hide_form');
-  }
 }
+
 // uncomment the next four lines for easier debugging with FireBug
 // Ajax.Responders.register({
 //  onException: function(source, exception) {
@@ -43,10 +94,10 @@ var TracksForm = {
 
 /* fade flashes automatically */
 Event.observe(window, 'load', function() { 
-  $A(document.getElementsByClassName('alert')).each(function(o) {
-    o.opacity = 100.0
-    Effect.Fade(o, {duration: 8.0})
-  });
+    $A(document.getElementsByClassName('alert')).each(function(o) {
+        o.opacity = 100.0
+        Effect.Fade(o, {duration: 8.0})
+    });
 });
 
 /**
@@ -55,12 +106,12 @@ Event.observe(window, 'load', function() {
  */
 CookieManager = Class.create();
 CookieManager.prototype =
-{
+    {
     BROWSER_IS_IE:
         (document.all
-         &amp;&amp; window.ActiveXObject
-         &amp;&amp; navigator.userAgent.toLowerCase().indexOf(&quot;msie&quot;) &gt; -1
-         &amp;&amp; navigator.userAgent.toLowerCase().indexOf(&quot;opera&quot;) == -1),
+        &amp;&amp; window.ActiveXObject
+        &amp;&amp; navigator.userAgent.toLowerCase().indexOf(&quot;msie&quot;) &gt; -1
+        &amp;&amp; navigator.userAgent.toLowerCase().indexOf(&quot;opera&quot;) == -1),
 
     /**
      * I hate navigator string based browser detection too, but when Opera alone</diff>
      <filename>public/javascripts/application.js</filename>
    </modified>
    <modified>
      <diff>@@ -3,75 +3,75 @@
 /* @override http://0.0.0.0:3000/stylesheets/standard.css?1180885851 */
 
 body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td { 
-	margin:0;
-	padding:0;
+    margin:0;
+    padding:0;
 }
 table {
-	border-collapse:collapse;
-	border-spacing:0;
+    border-collapse:collapse;
+    border-spacing:0;
 }
 fieldset,img { 
-	border:0;
+    border:0;
 }
 address,caption,cite,code,dfn,em,strong,th,var {
-	font-style:normal;
-	font-weight:normal;
+    font-style:normal;
+    font-weight:normal;
 }
 ol,ul {
-	list-style:none;
+    list-style:none;
 }
 caption,th {
-	text-align:left;
+    text-align:left;
 }
 h1,h2,h3,h4,h5,h6 {
-	font-size:100%;
-	font-weight:normal;
+    font-size:100%;
+    font-weight:normal;
 }
 q:before,q:after {
-	content:'';
+    content:'';
 }
 abbr,acronym { border:0;
 }
 
 body {
-      font-family: &quot;Lucida Grande&quot;, Verdana, Geneva, Arial, sans-serif;
-      font-size: 80%;
-      padding: 0px 10px;
-      margin: 0px;
-      background: #eee;
-      }
+    font-family: &quot;Lucida Grande&quot;, Verdana, Geneva, Arial, sans-serif;
+    font-size: 80%;
+    padding: 0px 10px;
+    margin: 0px;
+    background: #eee;
+}
 
 p {
-      padding: 2px;
-      font-size: 92%;
-      line-height: 140%;
-      }
+    padding: 2px;
+    font-size: 92%;
+    line-height: 140%;
+}
 
 a, a:link, a:active, a:visited {
-      color: #cc3334;
-      text-decoration: none;
-      padding-left: 1px;
-      padding-right: 1px;
-      }
-      
+    color: #cc3334;
+    text-decoration: none;
+    padding-left: 1px;
+    padding-right: 1px;
+}
+
 a:hover {
-      color: #fff;
-      background-color: #cc3334;
-      } 
+    color: #fff;
+    background-color: #cc3334;
+} 
 
 h1 {
-	font-size: 304%;
-	font-weight: bold;
+    font-size: 304%;
+    font-weight: bold;
 }
 
 h2 {
-	font-size: 148%;
-	font-weight: bold;
+    font-size: 148%;
+    font-weight: bold;
 }
 
 h3 {
-	font-size: 129%;
-	font-weight: bold;
+    font-size: 129%;
+    font-weight: bold;
 }
 
 /* Rules for the icon links */
@@ -105,287 +105,368 @@ a.show_notes:hover, a.link_to_notes:hover {background-image: url(../images/notes
 /* Structural divs */
 
 #content {
-      margin-top: 90px;
-      }
-      
+    margin-top: 90px;
+}
+
 #display_box {
-      float: left;
-      width: 55%;
-      margin: 0px 10px 50px 15px;
-      }
+    float: left;
+    width: 55%;
+    margin: 0px 10px 50px 15px;
+}
 
 #single_box {
-      width: 60%;
-      margin: 80px auto;
-      }
+    width: 60%;
+    margin: 80px auto;
+}
 
 #full_width_display {
-      float: left;
-      width: 95%;
-      margin: 0px 15px 90px 15px;
-      }
+    float: left;
+    width: 95%;
+    margin: 0px 15px 90px 15px;
+}
 
 #display_box_projects {
-      float: left;
-      width: 95%;
-      margin: 0px 15px 90px 15px;
-      }
+    float: left;
+    width: 95%;
+    margin: 0px 15px 90px 15px;
+}
+
+#recurring_timespan, #recurring_target {
+    border: none;
+    clear: both;
+}
+
+#recurring_target {
+    border-top-style: dotted;
+    padding: 15px 0px 0px 0px;
+}
+
+#recurring_daily, #recurring_weekly, #recurring_monthly, #recurring_yearly,
+#recurring_edit_daily, #recurring_edit_weekly, #recurring_edit_monthly, #recurring_edit_yearly {
+    border: none;
+    border-top-style: dotted;
+    clear: both;
+    padding: 15px 0px 15px 0px;
+}
+
+#recurring_period_id, #recurring_edit_period_id {
+    border: none;
+    float: left;
+    margin: 0px 50px 0px 0px;
+    padding: 0px 25px 15px 50px;
+    border-right-style: none;
+}
+
+#recurring_todo {
+    width: 270px;
+}
+
+#recurring_todo_form_container {
+    border-right-style: dotted;
+    padding: 0px 50px 15px 0px;
+    float: left;
+}
+
+#recurring_todo input, #recurring_todo textarea {
+    width: 100%;
+}
+
+#overlay {
+    visibility: hidden;
+    position: absolute;
+    left: 0px;
+    top: 0px;
+    width: 100%;
+    height: 100%;
+    z-index: 102;
+    text-align: center;
+    background-image:url(&quot;../images/trans70.png&quot;);
+}
+
+#overlay #new-recurring-todo, #overlay #edit-recurring-todo {
+    width:750px;
+    background-color: #fff;
+    border:1px solid #000;
+    padding: 15px;
+    margin: 70px auto;
+}
+
+.recurring_container {
+    padding: 0px 5px 0px 5px; 
+    border: 1px solid #999;
+    margin: 0px 0px 0px 0px;
+    background: #fff; 
+    text-align: left;
+}
+
+.recurring_submit_box {
+    height: 25px;
+    padding: 5px 0;
+    text-align: center;
+    clear: both;
+    border: none;
+}      
 
 /* Navigation links at the top */
 
 #navcontainer {
-      position: fixed;
-      top: 48px;
-      left: 0px;
-      }
-            
+    position: fixed;
+    top: 48px;
+    left: 0px;
+}
+
 #navlist {
-      margin: 0;
-      padding: 0 0 20px 5px;
-/*      border-bottom: 1px solid #000;*/
-      }
+    margin: 0;
+    padding: 0 0 20px 5px;
+    /*      border-bottom: 1px solid #000;*/
+}
 
 #navlist ul, #navlist li {
-      margin: 0;
-      padding: 0;
-      display: inline;
-      list-style-type: none;
-      }
+    margin: 0;
+    padding: 0;
+    display: inline;
+    list-style-type: none;
+}
 
 #navlist a:link, #navlist a:visited {
-      float: left;
-      line-height: 14px;
-      font-weight: bold;
-      margin: 0 10px 4px 10px;
-      text-decoration: none;
-      color: #eee;
-      }
+    float: left;
+    line-height: 14px;
+    font-weight: bold;
+    margin: 0 10px 4px 10px;
+    text-decoration: none;
+    color: #eee;
+}
 
 #navlist a:link#current, #navlist a:visited#current, #navlist a:hover {
-      border-bottom: 4px solid #CCC;
-      padding-bottom: 2px;
-      background: transparent;
-      color: #CCC;
-      }
+    border-bottom: 4px solid #CCC;
+    padding-bottom: 2px;
+    background: transparent;
+    color: #CCC;
+}
 
 #navlist a:hover { color: #CCC; }
 
 #topbar {
-      position: fixed;
-      top: 0px;
-      left: 0px;
-      height: 68px;
-      margin-bottom: 20px;
-      clear: both;
-      background-color: #000;
-      filter: alpha(opacity=75);
-      -moz-opacity: .75;
-      opacity: .75;
-      color: #eee;
-      width: 100%;
-      z-index:1100;
-      }
+    position: fixed;
+    top: 0px;
+    left: 0px;
+    height: 68px;
+    margin-bottom: 20px;
+    clear: both;
+    background-color: #000;
+    filter: alpha(opacity=75);
+    -moz-opacity: .75;
+    opacity: .75;
+    color: #eee;
+    width: 100%;
+    z-index:101;
+}
 body.stats #topbar {
     filter: alpha(opacity=100);
     -moz-opacity: 1;
     opacity: 1;
 }      
 #date {
-      float: left;
-      width: 45%;
-      padding-left: 15px;
-      margin-top: 15px;
-      margin-bottom: 5px;
-      white-space: nowrap; /* added 2006-05-17 for safari display, timfm */ 
-      }
+    float: left;
+    width: 45%;
+    padding-left: 15px;
+    margin-top: 15px;
+    margin-bottom: 5px;
+    white-space: nowrap; /* added 2006-05-17 for safari display, timfm */ 
+}
 #date h1 {
-      font-size: 152%;
-      }
-      
+    font-size: 152%;
+}
+
 #minilinks {
-      text-align: right;
-      position: fixed;
-      right: 15px;
-      top: 10px;
-      font-size: 0.9em;
-      }
-      
+    text-align: right;
+    position: fixed;
+    right: 15px;
+    top: 10px;
+    font-size: 0.9em;
+}
+
 .container {
-      padding: 0px 5px 0px 5px; 
-      border: 1px solid #999;
-      margin: 0px 0px 15px 0px;
-      background: #fff; 
-      }
+    padding: 0px 5px 0px 5px; 
+    border: 1px solid #999;
+    margin: 0px 0px 15px 0px;
+    background: #fff; 
+}
 
 .completed {
     background: #eee; 	
 }
-      
+
 .container h2 {
-      background: #ccc;
-      padding: 5px;
-      margin-top: 0px;
-      margin-left: -5px;
-      margin-right: -5px;
-      margin-bottom: 0px;      
-      color: #666;
-      position:left;  /* changed from relative to left in order to show 'add note' */
-      /* text-shadow: rgba(0,0,0,.4) 0px 2px 5px; */
-      }
+    background: #ccc;
+    padding: 5px;
+    margin-top: 0px;
+    margin-left: -5px;
+    margin-right: -5px;
+    margin-bottom: 0px;      
+    color: #666;
+    position:left;  /* changed from relative to left in order to show 'add note' */
+    /* text-shadow: rgba(0,0,0,.4) 0px 2px 5px; */
+}
 
 .container_toggle img {
-		height:20px;
-		width:20px;
-		border:0px;
-		}
+    height:20px;
+    width:20px;
+    border:0px;
+}
 
 h2 a, h2 a:link, h2 a:active, h2 a:visited {
-      color: #666;
-      text-decoration: none;
-      }
-      
+    color: #666;
+    text-decoration: none;
+}
+
 h2 a:hover {
-      color: #cc3334;
-      background-color: transparent;
-      text-decoration: none;
-      }
-      
+    color: #cc3334;
+    background-color: transparent;
+    text-decoration: none;
+}
+
 div#input_box {
-      margin: 0px 15px 0px 58%;
-      padding: 0px 15px 0px 0px;
-      }
+    margin: 0px 15px 0px 58%;
+    padding: 0px 15px 0px 0px;
+}
 
 #input_box h2 {
-      color: #999;
-      
-      }
+    color: #999;
+    
+}
 
 #input_box ul {list-style-type: circle; font-size: 0.9em;}
 
 .show_from_input, .due_input, .project_input, .context_input {
-	float:left;
+    float:left;
 }
 
 .box {
-      float: left;
-      width: 20px;
-      }
+    float: left;
+    width: 20px;
+}
 
 div.item-container {
-      padding: 2px 0px;
-      line-height:20px;
-      clear: both;
-      }
-      
+    padding: 2px 0px;
+    line-height:20px;
+    clear: both;
+}
+
+a.recurring_icon {
+    vertical-align: middle;
+    background-color: transparent;    
+}
+
 a.icon {
-      float: left;
-      vertical-align: middle;
-      background-color: transparent;
-      }
-      
+    float: left;
+    vertical-align: middle;
+    background-color: transparent;
+}
+
 input.item-checkbox {
-   	float: left;
-      margin-left: 10px;
-      vertical-align: middle;
-      }
+    float: left;
+    margin-left: 10px;
+    vertical-align: middle;
+}
 
 .description {
-      margin-left: 85px;
-      position:relative
-      }
+    margin-left: 85px;
+    position:relative
+}
 
 .stale_l1, .stale_l2, .stale_l3 {
-   	margin-left: 82px;
-	padding-left: 3px;
-      }
+    margin-left: 82px;
+    padding-left: 3px;
+}
 
 .stale_l1 {
-      background: #ffC;
-      }
-      
+    background: #ffC;
+}
+
 .tools {
-      margin-left: 25px;
-      width: 40px;
-      border-top: 1px solid #999;
-      }
-            
+    margin-left: 25px;
+    width: 40px;
+    border-top: 1px solid #999;
+}
+
 #footer {
-      clear: both;
-      font-size: 85%;
-      text-align: center;
-      color: #999;
-      margin: 20px 20px 5px 20px;
-      padding: 0px;
-      }
-      
+    clear: both;
+    font-size: 85%;
+    text-align: center;
+    color: #999;
+    margin: 20px 20px 5px 20px;
+    padding: 0px;
+}
+
 /* The notes which may be attached to an item */      
 .todo_notes {
-      margin: 5px;
-      padding: 3px;
-      border: 1px solid #F5ED59;
-      background: #FAF6AE;
-      color: #666666;
-      }
-      
+    margin: 5px;
+    padding: 3px;
+    border: 1px solid #F5ED59;
+    background: #FAF6AE;
+    color: #666666;
+}
+
 .todo_notes p, .todo_notes li {
-      padding: 1px;
-      margin: 0px;
-      font-size: 12px;
-      }
-      
+    padding: 1px;
+    margin: 0px;
+    font-size: 12px;
+}
+
 .todo_notes ul, .note_wrapper ul {
-      list-style-type: disc;
-      margin-left:20px;
+    list-style-type: disc;
+    margin-left:20px;
 }
 
 .todo_notes ol {
-      list-style-type: decimal;
-      margin-left:20px;
+    list-style-type: decimal;
+    margin-left:20px;
 }
 
 /* The notes for the project */
 
 div.note_wrapper {
-      margin: 3px;
-      padding: 2px;
-      }
+    margin: 3px;
+    padding: 2px;
+}
 
 div.note_wrapper p {
-      display: inline;
-      }
-      
+    display: inline;
+}
+
 div.note_footer {
-      border-top: 1px solid #999;
-      padding-top: 3px;
-      font-style: italic;
-      font-size: 0.9em;
-      color: #666;
-      }
+    border-top: 1px solid #999;
+    padding-top: 3px;
+    font-style: italic;
+    font-size: 0.9em;
+    color: #666;
+}
 
 div.note_footer a, div.note_footer a:hover {
-      border-top: none;
-      padding-top: 0px;
-      vertical-align: middle;
-      background-color: transparent;
-      }
+    border-top: none;
+    padding-top: 0px;
+    vertical-align: middle;
+    background-color: transparent;
+}
 
 div.add_note_link {
-	margin-top:12px;
-	float: right;
-	}
+    margin-top:12px;
+    float: right;
+}
 div#project_status &gt; div {
-	padding: 10px;
-	}
+    padding: 10px;
+}
 #project_status span {
-	margin-right:5px;
-	background-color:white;
+    margin-right:5px;
+    background-color:white;
 }
 #project_status .active_state {
-	font-weight:bold;
+    font-weight:bold;
 }
 
 div#default_context &gt; div{
-	padding:10px;
+    padding:10px;
 }
 a.footer_link {color: #cc3334; font-style: normal;}
 a.footer_link:hover {color: #fff; background-color: #cc3334 !important;}
@@ -393,192 +474,192 @@ a.footer_link:hover {color: #fff; background-color: #cc3334 !important;}
 /* Tag formatting */
 
 span.tag {
-  font-size: 0.8em;
-  background-color: #CCE7FF;
-  color: #000;
-  padding: 1px;
-  margin-right: 2px;
+    font-size: 0.8em;
+    background-color: #CCE7FF;
+    color: #000;
+    padding: 1px;
+    margin-right: 2px;
 }
 
 span.tag a, 
 span.tag a:link, 
 span.tag a:active, 
 span.tag a:visited {
-  color: #000;
+    color: #000;
 }
 
 span.tag a:hover {
-  background-color: #99CCFF;
-  color: #333;
+    background-color: #99CCFF;
+    color: #333;
 }
 
 /* Flash box styling */
 
 div#message_holder {
-  position: absolute;
-  z-index: 100;
-  left: 60%;
-  top: 30px;
-  right: 0px;
-  margin: 0px;
+    position: absolute;
+    z-index: 100;
+    left: 60%;
+    top: 30px;
+    right: 0px;
+    margin: 0px;
 }
 
 h4.alert  {
-   font-size: 1em;
-   margin: 0px;
-   padding: 5px;
-   text-align: center;
+    font-size: 1em;
+    margin: 0px;
+    padding: 5px;
+    text-align: center;
 }
 
 h4.warning  {
-  border: 1px solid #ED2E38; 
-  background-color: #F6979C;
-  color: #000;
+    border: 1px solid #ED2E38; 
+    background-color: #F6979C;
+    color: #000;
 }
 h4.error  {
-   color:#fff; 
-   background:#c00;
+    color:#fff; 
+    background:#c00;
 }
 h4.notice {
-  border: 1px solid #007E00; 
-  background-color: #c2ffc2;
-  color: #007E00;
+    border: 1px solid #007E00; 
+    background-color: #c2ffc2;
+    color: #007E00;
 }
 
 /* *****/
 
 .project_completed {
-      border: 1px solid #007E00; 
-      background-color: #c2ffc2;
-      padding: 5px;
-      color: #007E00;
-      text-align: center;
+    border: 1px solid #007E00; 
+    background-color: #c2ffc2;
+    padding: 5px;
+    color: #007E00;
+    text-align: center;
 }
-              
+
 /*   Draw attention to some text 
-    Same format as traffic lights */
+Same format as traffic lights */
 .red {
-      color: #fff;
-      background: #f00;
-      padding: 1px;
-      font-size: 85%;
-      }
-      
+    color: #fff;
+    background: #f00;
+    padding: 1px;
+    font-size: 85%;
+}
+
 .amber {
-      color: #fff;
-      background: #ff6600;
-      padding: 1px;
-      font-size: 85%;
-      }
-         
+    color: #fff;
+    background: #ff6600;
+    padding: 1px;
+    font-size: 85%;
+}
+
 .orange {
-      color: #fff;
-      background: #FFA500;
-      padding: 1px;
-      font-size: 85%;
-      }
+    color: #fff;
+    background: #FFA500;
+    padding: 1px;
+    font-size: 85%;
+}
 
 .green {
-      color: #fff;
-      background: #33cc00;
-      padding: 1px;
-      font-size: 85%;
-      }
-      
+    color: #fff;
+    background: #33cc00;
+    padding: 1px;
+    font-size: 85%;
+}
+
 .grey {
-      color: #fff;
-      background: #999;
-      padding: 2px;
-      font-size: 85%;
-      }
-      
+    color: #fff;
+    background: #999;
+    padding: 2px;
+    font-size: 85%;
+}
+
 .info {
-      color: #fff;
-      background: #CCC;
-      border: 1px solid #999;
-      padding: 5px;
-      text-align: center;
-      }
-      
+    color: #fff;
+    background: #CCC;
+    border: 1px solid #999;
+    padding: 5px;
+    text-align: center;
+}
+
 .highlight {
-      background: #ffC;
-      padding: 2px;
+    background: #ffC;
+    padding: 2px;
 } 
 
 /*  Backgrounds marking out 'staleness' of a task based on age of creation date
-    The colour of the background gets progressively yellower with age */
-    
+The colour of the background gets progressively yellower with age */
+
 .stale_l1 {
-      background: #ffC;
-      }
-      
+    background: #ffC;
+}
+
 .stale_l2 {
-      background: #ff6;
-      }
+    background: #ff6;
+}
 
 .stale_l3 {
-      background: #ff0;
-      }
+    background: #ff0;
+}
 
 /* Shows the number of undone next action */
 .badge {
-      color: #fff;
-      background: #f00;
-      padding: 3px 5px;
-      font-size: 12pt;
-      margin: 10px 10px 0px 0px;
-      height:26px;
-      }
-        
+    color: #fff;
+    background: #f00;
+    padding: 3px 5px;
+    font-size: 12pt;
+    margin: 10px 10px 0px 0px;
+    height:26px;
+}
+
 ul {
-      list-style-type: none;
-      }
+    list-style-type: none;
+}
 
 #sidebar h3 {
-	margin-top:15px;
-	margin-bottom:5px;
+    margin-top:15px;
+    margin-bottom:5px;
 }
-      
+
 #sidebar ul {
-      margin-left: auto;
-      list-style-position: inside;
-      }
-      
+    margin-left: auto;
+    list-style-position: inside;
+}
+
 li {
-      font-size: 1.1em;
-      padding: 3px 0px;
-      }
+    font-size: 1.1em;
+    padding: 3px 0px;
+}
 #sidebar li {
-      padding: auto;
-      }
+    padding: auto;
+}
 #sidebar .integrations-link {
-	margin-top:10px;
-	padding-top:10px;
-	font-size: 0.8em;
+    margin-top:10px;
+    padding-top:10px;
+    font-size: 0.8em;
 }
 .sortable_row {
-      background: #fff;
-      _background: transparent;
-      padding: 4px 4px 4px 8px;
-      margin: 2px 2px;
-      border: 1px solid #ccc;
-      }
+    background: #fff;
+    _background: transparent;
+    padding: 4px 4px 4px 8px;
+    margin: 2px 2px;
+    border: 1px solid #ccc;
+}
 
 .edit-form {
-      background: #ccc;
-      padding: 0 10px;
-      border-top: 1px solid #999;
-      border-bottom: 1px solid #999;
-      position:relative;
-      }
+    background: #ccc;
+    padding: 0 10px;
+    border-top: 1px solid #999;
+    border-bottom: 1px solid #999;
+    position:relative;
+}
 
 /* Right align labels in forms */
 .label {
-      text-align: right;
-      }
-      
+    text-align: right;
+}
+
 input {
-      vertical-align: middle;
+    vertical-align: middle;
 }
 
 /* Positioning the 'cells' in the list */
@@ -587,47 +668,47 @@ img.position, a:hover img.position {
     text-align: left;
     vertical-align: middle;
     background-color: transparent;
-    }
-    
+}
+
 .data {
     text-align: left;
     margin-left: 20px;
     float: left;
-    }
-    
+}
+
 div.buttons, div.buttons a, div.buttons a:hover {
     text-align: right;
     margin-right: 0px;
     vertical-align: middle;
     background-color: transparent;
-    }
+}
 
 div#list-active-projects, div#list-hidden-projects, div#list-completed-projects, div#list-contexts, div#projects-empty-nd {
     clear:right;
-	border: 1px solid #999;
-    }
+    border: 1px solid #999;
+}
 .project-state-group h2 {
-	margin:20px 0px 8px 13px;
+    margin:20px 0px 8px 13px;
 }
 
 .search-result-group h2 {
-        margin:20px 0px 8px 13px
+    margin:20px 0px 8px 13px
 }
 
 div.alpha_sort {
-	margin-top:-20px;
-	float:right;
+    margin-top:-20px;
+    float:right;
 }
 
-    
+
 .container td {
     border: none;
     padding-bottom: 5px;
-    }
+}
 
 .container form {
     border: none;
-    }
+}
 
 div.project_description {
     background: #eee;
@@ -640,48 +721,52 @@ div.project_description {
     font-size: 12px;
     font-weight: normal;
     /* Uncomment line below if you want the description to have
-       shadowed text */
+    shadowed text */
     /* text-shadow: rgba(0,0,0,.4) 0px 2px 5px; */
-    }
+}
 #project-next-prev {
-  text-align:right;
+    text-align:right;
 }
-    
+
 /* Form elements */
 form {
     border: 1px solid #CCC;
     padding: 10px;
     margin: 0px;
-    }
+}
 .inline-form {
     border: none;
     padding: 3px;
-    }
+}
 
 .inline-form table {
     padding-right: 3px;
-    }
+}
 
 /* expand form contents to fill the whole form */
 .inline-form table,
 .inline-form textarea#item_notes, 
 .inline-form input#item_description {
     width: 100%;
-    }
+}
 
 /* shrink the label/left column as small as necessary */
 .inline-form table td.label {
     width: 13ex;
-    }
-#todo_new_action_container, #project_new_project_container, #context_new_container {
-	background: #ddd;
-	width: 270px;
-	padding: 5px 10px;
-	background-color: #000;
-	filter: alpha(opacity=75);
-	-moz-opacity: .75;
-	opacity: .75;
-	color: #eee;
+}
+#todo_new_action_container, #project_new_project_container, #context_new_container, #recurring_new_container {
+    background: #ddd;
+    width: 270px;
+    padding: 5px 10px;
+    background-color: #000;
+    filter: alpha(opacity=75);
+    -moz-opacity: .75;
+    opacity: .75;
+    color: #eee;
+}
+
+#recurring_new_container img {
+    vertical-align: middle;
 }
 
 #project_new_project_filler {
@@ -693,7 +778,7 @@ form {
 #project_new_project_container input,
 #project_new_project_container textarea,
 #context_new_container input  {
-	width: 100%;
+    width: 100%;
 }
 
 input#go_to_project, input#context_hide {
@@ -701,47 +786,47 @@ input#go_to_project, input#context_hide {
 }
 
 #todo_new_action_container .show_from_input, #todo_new_action_container .due_input {
-	width: 45%;
+    width: 45%;
 }
 
 #todo_new_action_container .show_from_input {
-	float: right;
+    float: right;
 }
 
 #todo-form-new-action .submit_box, #project_form .submit_box, #context_form .submit_box {
-	height: 25px;
-	padding: 5px 0;
-	text-align: center;
-	clear: right;
+    height: 25px;
+    padding: 5px 0;
+    text-align: center;
+    clear: right;
 }
 
 .edit_todo_form .submit_box {
-	height: 25px;
-	padding: 5px 0;
-	text-align: center;
-	clear: right;
+    height: 25px;
+    padding: 5px 0;
+    text-align: center;
+    clear: right;
 }
 
 .edit_todo_form input, .edit_todo_form textarea {
-	width:100%;
+    width:100%;
 }
 
 .edit_todo_form .tag_list_label {
-	clear:both;
+    clear:both;
 }
 .edit_todo_form .due_input, .edit_todo_form .show_from_input, .edit_todo_form .project_input, .edit_todo_form .context_input {
-	width:48%;
+    width:48%;
 }
 
 .edit_todo_form .show_from_input, .edit_todo_form .context_input {
-	float: right;
+    float: right;
 }
 
 .edit_todo_form .submit_box input {
-	width:120px;
+    width:120px;
 }
 .hide_form {
-	text-align:right;
+    text-align:right;
 }
 #todo-form-new-action label, .edit_todo_form label {
     display: block;
@@ -749,20 +834,20 @@ input#go_to_project, input#context_hide {
 }
 
 form.button-to {
-	border: none;
-	padding: 0px;
-	margin: 0px;
+    border: none;
+    padding: 0px;
+    margin: 0px;
 }
 
 label {
     font-weight: bold;
     padding: 0px 0px;
-    }
-    
+}
+
 input, select, textarea {
     margin: 0px 0px 5px 0px;
-    }
-    
+}
+
 .feed {
     font-family: verdana, sans-serif; 
     font-size: 10px; 
@@ -774,13 +859,13 @@ input, select, textarea {
     border-color: #FC9 #630 #330 #F96; 
     padding:0px 3px 0px 3px; 
     margin:0px;
-    }
-    
+}
+
 /* Classes for Drag and Drop */
 .position {
     float: left;
-	margin-top:2px;
-    }
+    margin-top:2px;
+}
 .handle {
     color: #fff;
     background: #000;
@@ -790,180 +875,180 @@ input, select, textarea {
 }
 
 div.message {
-  margin: 5px 0px; 
-	background: #FAF4B5;
-	padding: 2px;
+    margin: 5px 0px; 
+    background: #FAF4B5;
+    padding: 2px;
 }
 
 .message p {
-  margin: 0px;
-  padding: 0px;
-	text-align: center;
-	font-size: 1em;
-	color: #666;
+    margin: 0px;
+    padding: 0px;
+    text-align: center;
+    font-size: 1em;
+    color: #666;
 }
 
 /* Error message styles */
 .fieldWithErrors {
-  padding: 2px;
-  background-color: red;
-  display: table;
+    padding: 2px;
+    background-color: red;
+    display: table;
 }
 
 #errorExplanation {
-  border: 2px solid #ff0000;
-  padding: 7px;
-  padding-bottom: 12px;
-  margin: 10px auto 20px auto;
-  background-color: #f0f0f0;
+    border: 2px solid #ff0000;
+    padding: 7px;
+    padding-bottom: 12px;
+    margin: 10px auto 20px auto;
+    background-color: #f0f0f0;
 }
 
 #errorExplanation h2 {
-  text-align: left;
-  font-weight: bold;
-  padding: 5px 5px 5px 15px;
-  font-size: 12px;
-  margin: -7px;
-  background-color: #c00;
-  color: #fff;
+    text-align: left;
+    font-weight: bold;
+    padding: 5px 5px 5px 15px;
+    font-size: 12px;
+    margin: -7px;
+    background-color: #c00;
+    color: #fff;
 }
 
 #errorExplanation &gt; p {
-  color: #333;
-  margin-top: 5px;
-  margin-bottom: 0;
-  padding: 5px;
+    color: #333;
+    margin-top: 5px;
+    margin-bottom: 0;
+    padding: 5px;
 }
 
 #errorExplanation ul li {
-  font-size: 1em;
-  list-style-type: disc;
-  list-style-position: inside;
-  margin-left:7px;
-  color: #333; 
+    font-size: 1em;
+    list-style-type: disc;
+    list-style-position: inside;
+    margin-left:7px;
+    color: #333; 
 }
 
 ul#prefs {list-style-type: disc; margin-left: 15px;}
 #token_area, #authentication_area {
-  text-align:center;
-  margin-top:20px;
-  margin-bottom:10px;
+    text-align:center;
+    margin-top:20px;
+    margin-bottom:10px;
 }
 #token_area .description{ 
-  font-weight:bold;
+    font-weight:bold;
 }
 #token_area form {
-  width:100%;
-  text-align:center;
+    width:100%;
+    text-align:center;
 }
 .prefscontainer .actions {
-  text-align:center;
-  margin-bottom:20px;
+    text-align:center;
+    margin-bottom:20px;
 }
 .authtype_container .actions {
-  margin-top:20px;
-  margin-bottom:20px;	
+    margin-top:20px;
+    margin-bottom:20px;	
 }
 #feedlegend {
-  padding: 2px;
-  border: 1px solid #CCC; 
-  background-color: #D2D3D6;
-  color: #666;
-  padding: 5px 20px;
-  text-align: left;
+    padding: 2px;
+    border: 1px solid #CCC; 
+    background-color: #D2D3D6;
+    color: #666;
+    padding: 5px 20px;
+    text-align: left;
 }
 #feedlegend h3, #feedlegend dl, #feedlegend dt, #feedlegend dd {
-	display: inline;
+    display: inline;
 }
 #feedlegend dt {
-	margin-left: 15px;
+    margin-left: 15px;
 }
 #feedlegend dd {
-	margin-left: 3px;
+    margin-left: 3px;
 }
 #feedlegend p {
-	margin-bottom: 0px;
+    margin-bottom: 0px;
 }
 #feeds img.rss-icon {
-	margin-bottom: -4px;
+    margin-bottom: -4px;
 }
 #feeds li {
-	font-size:13px;
-  font-family: &quot;Lucida Grande&quot;, Verdana, Geneva, Arial, sans-serif;
+    font-size:13px;
+    font-family: &quot;Lucida Grande&quot;, Verdana, Geneva, Arial, sans-serif;
 }
 #feeds li h4 {
-	margin-top: 12px;
-	margin-bottom: 4px;
-	font-weight: normal;
-	font-style:oblique;
+    margin-top: 12px;
+    margin-bottom: 4px;
+    font-weight: normal;
+    font-style:oblique;
 }
 input.open_id {
-   background: url(../images/open-id-login-bg.gif) no-repeat; 
-   background-color: #fff; 
-   background-position: 0 50%;
-   color: #000;
-   padding-left: 18px;
-   width:182px;
+    background: url(../images/open-id-login-bg.gif) no-repeat; 
+    background-color: #fff; 
+    background-position: 0 50%;
+    color: #000;
+    padding-left: 18px;
+    width:182px;
 }
 div.page_name_auto_complete {
-	width: 100%;
-	background: #fff;
-	display: inline;
-        z-index: 100;
+    width: 100%;
+    background: #fff;
+    display: inline;
+    z-index: 100;
 }
 
 div.page_name_auto_complete ul {
-	border: 1px solid #888;
-	margin: 0;
-	padding: 0;
-	width: 100%;
-	list-style-type: none;
+    border: 1px solid #888;
+    margin: 0;
+    padding: 0;
+    width: 100%;
+    list-style-type: none;
 }
 
 div.page_name_auto_complete ul li {
-	margin: 0;
-	padding: 2px;
-	font-weight:bold;
-	list-style-type: none;
-	color: #000;
+    margin: 0;
+    padding: 2px;
+    font-weight:bold;
+    list-style-type: none;
+    color: #000;
 }
 
 div.page_name_auto_complete ul li.selected { 
-	background-color: #ffb; 
+    background-color: #ffb; 
 }
 
 div.page_name_auto_complete ul strong.highlight { 
-	color: #800; 
-	margin: 0;
-	padding: 0;
+    color: #800; 
+    margin: 0;
+    padding: 0;
 }
 
 table.next_actions td {
-	padding:5px 3px 2px 0px;
+    padding:5px 3px 2px 0px;
 }
 
 table.users_table {
-  width: 100%;
-  text-align: center;
-  border: 1px solid #666;
-  background-color: #fff;
-  border-spacing: 0px;
+    width: 100%;
+    text-align: center;
+    border: 1px solid #666;
+    background-color: #fff;
+    border-spacing: 0px;
 }
 
 .users_table th {color: #fff; background-color: #000;}
 .users_table td {border: none;}
 
 table.export_table {
-  border: 1px solid #666;
-  background-color: #fff;
-  border-spacing: 0px;    
+    border: 1px solid #666;
+    background-color: #fff;
+    border-spacing: 0px;    
 }
 
 .export_table th {color: #fff; background-color: #000;}
 .export_table td {border: 1px; padding: 5px 0px 5px 5px;}
 
 /* Submit button styling from ParticleTree
-    http://particletree.com/features/rediscovering-the-button-element/ */
+http://particletree.com/features/rediscovering-the-button-element/ */
 
 .widgets a, .widgets button{
     display:block;
@@ -973,7 +1058,7 @@ table.export_table {
     border:1px solid #dedede;
     border-top:1px solid #eee;
     border-left:1px solid #eee;
-
+    
     font-family:&quot;Lucida Grande&quot;, Verdana, Geneva, Arial, sans-serif;
     font-size:80%;
     line-height:100%;
@@ -1047,61 +1132,61 @@ button.positive, .widgets a.positive{
     color:#fff;
 }
 .tracks__waiting {
-	background-image:url('../images/waiting.gif');
-	background-repeat:no-repeat;
-	background-position:center center;
-	background-color:white;
+    background-image:url('../images/waiting.gif');
+    background-repeat:no-repeat;
+    background-position:center center;
+    background-color:white;
 }
 
 .bigWaiting {
-	background-image:url('../images/bigWaiting.gif');
-	background-repeat:no-repeat;
-	background-position:center 20%;
-	background-color:white;
+    background-image:url('../images/bigWaiting.gif');
+    background-repeat:no-repeat;
+    background-position:center 20%;
+    background-color:white;
 }
 
 .blackWaiting {
-	background-image:url('../images/blackWaiting.gif');
-	background-repeat:no-repeat;
-	background-position:center center;
-	background-color:black;
+    background-image:url('../images/blackWaiting.gif');
+    background-repeat:no-repeat;
+    background-position:center center;
+    background-color:black;
 }
 
 .bigBlackWaiting {
-	background-image:url('../images/bigBlackWaiting.gif');
-	background-repeat:no-repeat;
-	background-position:center center;
-	background-color:black;
+    background-image:url('../images/bigBlackWaiting.gif');
+    background-repeat:no-repeat;
+    background-position:center center;
+    background-color:black;
 }
 .stats_content .open-flash-chart, .stats_content .stats_module {
-	float: left;
-	width: 450px;
-	margin-right:20px;
-	padding-bottom:20px;
+    float: left;
+    width: 450px;
+    margin-right:20px;
+    padding-bottom:20px;
 }
 .stats_content h2
 {
-	clear:both;
-	margin-top:15px;
-	margin-bottom:15px;
+    clear:both;
+    margin-top:15px;
+    margin-bottom:15px;
 }
 body.integrations h2 {
-	margin-top:40px;
-	padding-top:20px;
-	margin-bottom:10px;
-	border-top:1px solid #ccc;
+    margin-top:40px;
+    padding-top:20px;
+    margin-bottom:10px;
+    border-top:1px solid #ccc;
 }
 body.integrations p, body.integrations li {
-	font-size:1.0em;
+    font-size:1.0em;
 }
 body.integrations li {
-	list-style-type: disc;
-	list-style-position: inside;
-	margin-left:30px;	
+    list-style-type: disc;
+    list-style-position: inside;
+    margin-left:30px;	
 }
 body.integrations textarea {
-	margin:10px;
-	padding:3px;
-	width:80%;
-	background-color:#ddd;
+    margin:10px;
+    padding:3px;
+    width:80%;
+    background-color:#ddd;
 }
\ No newline at end of file</diff>
      <filename>public/stylesheets/standard.css</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>c46f0a8e0424ca7bb98998972363aae1e037dd26</id>
    </parent>
  </parents>
  <author>
    <name>Reinier Balt</name>
    <email>lrbalt@gmail.com</email>
  </author>
  <url>http://github.com/bsag/tracks/commit/8bc41e2cb05217b103de28c2cba9741f6e226a5b</url>
  <id>8bc41e2cb05217b103de28c2cba9741f6e226a5b</id>
  <committed-date>2008-07-19T11:27:45-07:00</committed-date>
  <authored-date>2008-07-19T11:27:45-07:00</authored-date>
  <message>add recurring todos to tracks</message>
  <tree>20f1028c7bb120f89d43d1b76c9fa925ac449472</tree>
  <committer>
    <name>Reinier Balt</name>
    <email>lrbalt@gmail.com</email>
  </committer>
</commit>
