Skip to content

Instantly share code, notes, and snippets.

@rafarubert
Created July 11, 2011 22:13
Show Gist options
  • Select an option

  • Save rafarubert/1076921 to your computer and use it in GitHub Desktop.

Select an option

Save rafarubert/1076921 to your computer and use it in GitHub Desktop.
calendar
#encoding: utf-8
module Atendente::AgendaHelper
def calendar(options={}, &block)
caption = String.new
contents = String.new
head = String.new
rows = String.new
options = {
:caption_format => :default,
:events => nil,
:field => :created_at,
:header_format => :week,
:html_tag => "table",
:id => "calendar",
:month => Date.today.month,
:today => nil,
:year => Date.today.year
}.merge(options)
options[:html_tag] = options[:html_tag] == "ul" ? "ul" : "table"
cmd = 'cal '
cmd << '-m ' unless RUBY_PLATFORM =~ /darwin/
# execute the command
output = IO.popen("#{cmd} #{options[:month]} #{options[:year]}") {|f| f.read}
# get calendar lines
io = StringIO.new(output)
lines = io.readlines
lines = lines[2, lines.size-2]
lines.map!(&:chomp)
# strip spaces from each day and group them
days = lines.inject([]) do |holder, line|
0.step(line.size, 3){|n| holder << line[n, 3].squish}
holder
end
# group all records if data is provided
if options[:events]
records = options[:events].inject({}) do |memo, record|
field = record.send(options[:field])
if field
stamp = field.to_date.to_s(:number)
memo[stamp] ||= []
memo[stamp] << record
end
memo
end
end
# building the calendar
contents = content_tag(options[:html_tag].to_sym, :id => options[:id], :class => 'calendar') do
# first, get the header
today = Date.today
date = today.beginning_of_week
date = date - 1.day if RUBY_PLATFORM =~ /darwin/
if options[:html_tag] == "ul"
begin
caption = content_tag(:caption, l(Date.new(options[:year], options[:month]), :format => options[:caption_format]))
rescue
caption = content_tag(:caption, Date.new(options[:year], options[:month]))
end
else
begin
caption = content_tag(:div, l(Date.new(options[:year], options[:month]), :format => options[:caption_format]))
rescue
caption = content_tag(:div, Date.new(options[:year], options[:month]))
end
end
if options[:html_tag] == "ul"
head << content_tag(:tr) do
begin
(0..6).collect { |i| content_tag(:th, l(date + i.days, :format => options[:header_format])); } * ""
rescue
(0..6).collect { |i| content_tag(:th, date + i.days) } * ""
end
end
else
begin
(0..6).collect { |i| content_tag(:li, l(date + i.days, :format => options[:header_format])); } * ""
rescue
(0..6).collect { |i| content_tag(:li, date + i.days) } * ""
end
end
# then get the body
days.in_groups_of(7, "") do |group|
# skip rows that don't have any days
next unless group.inject(false) {|m, x| m || !x.blank?}
rows << content_tag(:tr) do
group.inject("") do |cols, day|
col_options = {:class => 'day'}
events = ""
unless day.blank?
date = Date.new(options[:year], options[:month], day.to_i)
col_options[:class] << ' today' if today == date
col_options[:class] << ' weekend' if [0,6].include?(date.wday)
end
if block_given? && !day.blank?
if options[:events]
events = capture(date, records[date.to_s(:number)], &block)
else
events = capture(date, &block)
end
col_options[:class] << ' events' unless events.blank?
end
cols << content_tag(:td, col_options) do
day = options[:today] if options[:today] && date == today
span = content_tag(:span, day)
span + events
end
end
end
end
caption = CGI.unescapeHTML(caption)
head = CGI.unescapeHTML(head)
rows = CGI.unescapeHTML(rows)
caption + head + rows
end
concat(contents) if block_given?
contents = String.new(contents)
contents = CGI.unescapeHTML(contents)
raw contents
end
private
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment