Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

Josh Adams http://www.isotope11.com

« Newer Snippets
Older Snippets »
Showing 1-1 of 1 total  RSS 

week_view_helper

// Week view helper.

require 'date'

# Author: Josh Adams
# This helper is based on CalendarHelper.
# WeekViewHelper allows you to draw a databound week view calendar with fine-grained CSS formatting
module WeekViewHelper
  VERSION = '0.0.1'

  # Returns an HTML week-view calendar. In its simplest form, this method generates a plain
  # calendar (which can then be customized using CSS) for a given span of days.
  # However, this may be customized in a variety of ways -- changing the default CSS
  # classes, generating the individual day entries yourself, and so on.
  # 
  # The following options are required:
  #  :start_date
  #  :end_date
  # 
  # The following are optional, available for customizing the default behaviour:
  #   :table_class       => "week-view"        # The class for the <table> tag.
  #   :day_name_class    => "dayName"         # The class is for the names of the days, at the top.
  #   :day_class         => "day"             # The class for the individual day number cells.
  #                                             This may or may not be used if you specify a block (see below).
  #   :show_today        => true              # Highlights today on the calendar using the CSS class 'today'. 
  #                                           # Defaults to true.
  #   :previous_span_text   => nil            # Displayed left if set
  #   :next_span_text   => nil                # Displayed right if set
  #
  # For more customization, you can pass a code block to this method, that will get two argument, both DateTime objects,
  # and return a values for the individual table cells. The block can return an array, [cell_text, cell_attrs],
  # cell_text being the text that is displayed and cell_attrs a hash containing the attributes for the <td> tag
  # (this can be used to change the <td>'s class for customization with CSS).
  # This block can also return the cell_text only, in which case the <td>'s class defaults to the value given in
  # +:day_class+. If the block returns nil, the default options are used.
  # 
  # Example usage:
  #   week_view(:start_date => (Date.today - 5), :end_date => Date.today) # This generates the simplest possible week-view.
  #   week_view(:start_date => (Date.today - 5), :end_date => Date.today, :table_class => "calendar_helper"}) # This generates a week-view, as
  #                                                                             # before, but the <table>'s class
  #                                                                             # is set to "calendar_helper".
  #   week_view(:start_date => (Date.today - 5), :end_date => Date.today) do |s| # This generates a simple week-view, but gives special spans
  #     if listOfSpecialSpans.include?(s)          # (spans that are in the array listOfSpecialSpans) one CSS class,
  #       ["", {:class => "specialSpan"}]      # "specialSpan", and gives the rest of the spans another CSS class,
  #     else                                      # "normalSpan". You can also use this to highlight the current time differently
  #       ["", {:class => "normalSpan"}]       # from the rest of the days, etc.
  #     end
  #   end
  #
  # For consistency with the themes provided in the calendar_styles generator, use "specialSpan" as the CSS class for marked days.
  # 
  def week_view(options = {}, &block)
    raise(ArgumentError, "No start date given")  unless options.has_key?(:start_date)
    raise(ArgumentError, "No end date given") unless options.has_key?(:end_date)
    span = (options[:end_date] - options[:start_date]).to_i # Get the number of days represented by the span given
    dates = (options[:start_date]..options[:end_date])
    start_time = 8
    end_time   = 17
    time_range = (start_time..end_time).to_a
    duration = 15

    block                        ||= Proc.new {|d| nil}
    defaults = {
      :table_class => 'week-view',
      :day_name_class => 'dayName',
      :day_class => 'day',
      :show_today => true,
      :previous_span_text => nil,
      :next_span_text => nil
    }
    options = defaults.merge options

		if options[:url]
      next_start_date = options[:end_date] + 1
      next_end_date   = next_start_date + 5
      next_link = link_to('>>', url_for(options[:url].merge(:start_date => next_start_date, :end_date => next_end_date)) + options[:url_append])
      prev_start_date = options[:start_date] - span
      prev_end_date = options[:start_date] - 1
      prev_link = link_to('<<', url_for(options[:url].merge(:start_date => prev_start_date, :end_date => prev_end_date)) + options[:url_append])
		end

    # TODO Use some kind of builder instead of straight HTML
    cal = %(<table class="#{options[:table_class]}">\n)
    cal << %(\t<thead>\n\t\t<tr>\n)
    cal << %(\t\t\t<th>#{dates.first.strftime("%Y")}</th>\n)
    dates.each do |d|
      cal << "\t\t\t<th#{Date.today == d ? " class='today'" : ""}>#{d.strftime("%A")}<br />#{d.strftime("%m/%d")}</th>\n"
    end
    cal << "\t\t</tr>\n\t</thead>\n\t<tbody>\n"
    time_range.each do |hour|
      minutes = 0
      print_hour = hour.to_s.rjust(2, '0')
      4.times do |i|
        print_minutes = minutes.to_s.rjust(2, '0')
        cal << %(\t\t<tr class='m#{print_minutes} d#{duration}'>\n)
        cal << %(\t\t\t<th rowspan="4"><h3>#{hour}</h3>AM</th>\n) if i==0
        options[:start_date].upto(options[:end_date]) do |d|
          the_minutes = minutes
          print_start_minutes = the_minutes.to_s.ljust(2, '0')
          start_datetime_string = %(#{d.to_s(:db)}T#{print_hour}:#{print_start_minutes}:00-06:00)
          start_datetime = DateTime.parse(start_datetime_string).to_datetime
          end_datetime = (start_datetime + duration.minutes).to_datetime
          range = (start_datetime...end_datetime)

          # cell_attrs should return a hash.
          cell_text, cell_attrs = block.call(range)
          cell_text ||= ""
          cell_attrs ||= {}
          cell_attrs[:class] = cell_attrs[:class].to_s + " today" if Date.today == d
          cell_attrs = cell_attrs.map {|k, v| %(#{k}="#{v}") }.join(" ")

          cal << "\t\t\t<td #{cell_attrs}>\n#{cell_text}&nbsp;\t\t\t</td>\n"
        end
        minutes += duration
        cal << %(\t\t</tr>)
      end
    end
    cal << "\n\t</tbody>\n</table>"
  end
  
  private
end



// Usage

<%= week_view :start_date => (Date.today - 2), :end_date => (Date.today + 2) do |range|
      cell_text = ""
      cell_attrs = {}
      @events.each do |e|
        #if range.first.to_date == e.starts_at.to_date#range.include?(e.starts_at.to_datetime)
        if range.include?(e.starts_at.to_datetime)
          cell_text << "<div class='event-container'>\n"
          if e.work_order
            work_order_text = ""
            work_order_text << "<h3>" << e.work_order.ticket.summary + "</h3>\n"
            work_order_text << e.work_order.description

            klass = ["event"]
            klass << "closed" if e.work_order.closed?
            klass << "mm" + (e.work_order.hours * 60).to_i.to_s

            work_order_text = "<div class='#{klass.join(" ")}'>\n#{work_order_text}\n</div>\n"
            work_order_link = link_to(work_order_text, company_asset_ticket_work_order_path(e.work_order.company, e.work_order.asset, e.work_order.ticket, e.work_order))
            cell_text << work_order_link
          end
          cell_text << "</div>\n"
        end
      end
      [cell_text, cell_attrs]
    end 
-%>


// Styles

table.week-view{
  width: 100%;
  padding: 0;
  border-collapse: collapse;
}
table.week-view tbody tr th{
  border-right: 1px solid black;
  text-align: left;
  padding-right: .5em;
}
table.week-view tbody tr th h3{
  display: inline;
  font-size: 3em;
  margin: 0;
  padding: 0;
  background: transparent;
  border: none;
}
table.week-view th{
  background-color: #eee;
  color: black;
}
table.week-view tr td{
  border-style: solid;
  border-width: 1px 1px 0 0;
  width: 19%;
  padding: 0;
  background-color: #ffffd5;
}
table.week-view tr.d15 td,
table.week-view tr.d15 th{
  font-size: 8px;
  height: 1em;
  border-color: #f3e4b1 #000;
}
table.week-view div.event-container{
  position: relative;
}
table.week-view tr td div.event{
  padding: 2px;
  background-color: #fff;
  height: 2em;
  width: 90%;
  position: absolute;
  top: 0;
  left: 0;
  border-style: solid;
  border-color: black black black #00f;
  border-width: .0625em .0625em .0625em .5em;
  margin-right: .5em;
  color: #333;
  overflow: hidden;
  float: left;
}
table.week-view tr td div.event.mm60{
  height: 8em;
}
table.week-view tr td div.event.mm120{
  height: 16em;
}
table.week-view tr td div.event h3{
  margin: 0;
  font-size: 9px;
  color: black;
  padding: 0;
  border: 0;
  background: transparent;
}
table.week-view tr.m00 td{
  border-top-color: #c2b68d;
}
table.week-view tr.m00 th{
  vertical-align: top;
}
« Newer Snippets
Older Snippets »
Showing 1-1 of 1 total  RSS