From 2fe8610673e7445860830aad5e6ad49a1c99f2c5 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 12 Sep 2005 05:26:25 +0000 Subject: Added TextHelper#cycle to cycle over an array of values on each hit (useful for alternating row colors etc) #2154 [dave-ml@dribin.org] git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@2213 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- actionpack/lib/action_view/helpers/text_helper.rb | 82 +++++++++++++++++++++++ 1 file changed, 82 insertions(+) (limited to 'actionpack/lib/action_view') diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 217cf6c9f8..413f32532d 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -189,9 +189,91 @@ module ActionView html end + + # Returns a Cycle object whose to_s value cycles through items of an + # array every time it is called. This can be used to alternate classes + # for table rows: + # + # <%- for item in @items do -%> + # "> + # ... use item ... + # + # <%- end -%> + # + # You can use named cycles to prevent clashes in nested loops. You'll + # have to reset the inner cycle, manually: + # + # <%- for item in @items do -%> + # "row_class") + # + # <%- for value in item.values do -%> + # "colors") %>'"> + # item + # + # <%- end -%> + # <%- reset_cycle("colors") -%> + # + # + # <%- end -%> + def cycle(first_value, *values) + if (values.last.instance_of? Hash) + params = values.pop + name = params[:name] + else + name = "default" + end + values.unshift(first_value) + + cycle = get_cycle(name) + if (cycle.nil? || cycle.values != values) + cycle = set_cycle(name, Cycle.new(*values)) + end + return cycle.to_s + end + + # Resets a cycle so that it starts from the first element in the array + # the next time it is used. + def reset_cycle(name = "default") + cycle = get_cycle(name) + return if cycle.nil? + cycle.reset + end + + class Cycle + attr_reader :values + + def initialize(first_value, *values) + @values = values.unshift(first_value) + reset + end + + def reset + @index = 0 + end + + def to_s + value = @values[@index].to_s + @index = (@index + 1) % @values.size + return value + end + end private + # The cycle helpers need to store the cycles in a place that is + # guaranteed to be reset every time a page is rendered, so it + # uses an instance variable of ActionView::Base. + def get_cycle(name) + @_cycles = Hash.new if @_cycles.nil? + return @_cycles[name] + end + + def set_cycle(name, cycle_object) + @_cycles = Hash.new if @_cycles.nil? + @_cycles[name] = cycle_object + end + # Returns a version of the text that's safe to use in a regular expression without triggering engine features. def escape_regexp(text) text.gsub(/([\\|?+*\/\)\(])/) { |m| "\\#{$1}" } -- cgit v1.2.3