mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
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
This commit is contained in:
parent
c0e84b811e
commit
2fe8610673
3 changed files with 173 additions and 0 deletions
|
@ -1,5 +1,7 @@
|
|||
*SVN*
|
||||
|
||||
* Added TextHelper#cycle to cycle over an array of values on each hit (useful for alternating row colors etc) #2154 [dave-ml@dribin.org]
|
||||
|
||||
* Ensure that request.path never returns nil. Closes #1675 [Nicholas Seckar]
|
||||
|
||||
* Add ability to specify Route Regexps for controllers. Closes #1917. [Sebastian Kanthak]
|
||||
|
|
|
@ -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 -%>
|
||||
# <tr class="<%= cycle("even", "odd") %>">
|
||||
# ... use item ...
|
||||
# </tr>
|
||||
# <%- 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 -%>
|
||||
# <tr class="<%= cycle("even", "odd", :name => "row_class")
|
||||
# <td>
|
||||
# <%- for value in item.values do -%>
|
||||
# <span style="color:'<%= cycle("red", "green", "blue"
|
||||
# :name => "colors") %>'">
|
||||
# item
|
||||
# </span>
|
||||
# <%- end -%>
|
||||
# <%- reset_cycle("colors") -%>
|
||||
# </td>
|
||||
# </tr>
|
||||
# <%- 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}" }
|
||||
|
|
|
@ -8,6 +8,12 @@ class TextHelperTest < Test::Unit::TestCase
|
|||
include ActionView::Helpers::TextHelper
|
||||
include ActionView::Helpers::TagHelper
|
||||
|
||||
def setup
|
||||
# This simulates the fact that instance variables are reset every time
|
||||
# a view is rendered. The cycle helper depends on this behavior.
|
||||
@_cycles = nil if (defined? @_cycles)
|
||||
end
|
||||
|
||||
def test_simple_format
|
||||
assert_equal "<p>crazy\n<br /> cross\n<br /> platform linebreaks</p>", simple_format("crazy\r\n cross\r platform linebreaks")
|
||||
assert_equal "<p>A paragraph</p>\n\n<p>and another one!</p>", simple_format("A paragraph\n\nand another one!")
|
||||
|
@ -137,4 +143,87 @@ class TextHelperTest < Test::Unit::TestCase
|
|||
assert_equal %{href="javascript:bang" <a name='hello'>foo</a>, <span>bar</span>}, result
|
||||
end
|
||||
|
||||
def test_cycle_class
|
||||
value = Cycle.new("one", 2, "3")
|
||||
assert_equal("one", value.to_s)
|
||||
assert_equal("2", value.to_s)
|
||||
assert_equal("3", value.to_s)
|
||||
assert_equal("one", value.to_s)
|
||||
value.reset
|
||||
assert_equal("one", value.to_s)
|
||||
assert_equal("2", value.to_s)
|
||||
assert_equal("3", value.to_s)
|
||||
end
|
||||
|
||||
def test_cycle_class_with_no_arguments
|
||||
assert_raise(ArgumentError) { value = Cycle.new() }
|
||||
end
|
||||
|
||||
def test_cycle
|
||||
assert_equal("one", cycle("one", 2, "3"))
|
||||
assert_equal("2", cycle("one", 2, "3"))
|
||||
assert_equal("3", cycle("one", 2, "3"))
|
||||
assert_equal("one", cycle("one", 2, "3"))
|
||||
assert_equal("2", cycle("one", 2, "3"))
|
||||
assert_equal("3", cycle("one", 2, "3"))
|
||||
end
|
||||
|
||||
def test_cycle_with_no_arguments
|
||||
assert_raise(ArgumentError) { value = cycle() }
|
||||
end
|
||||
|
||||
def test_cycle_resets_with_new_values
|
||||
assert_equal("even", cycle("even", "odd"))
|
||||
assert_equal("odd", cycle("even", "odd"))
|
||||
assert_equal("even", cycle("even", "odd"))
|
||||
assert_equal("1", cycle(1, 2, 3))
|
||||
assert_equal("2", cycle(1, 2, 3))
|
||||
assert_equal("3", cycle(1, 2, 3))
|
||||
assert_equal("1", cycle(1, 2, 3))
|
||||
end
|
||||
|
||||
def test_named_cycles
|
||||
assert_equal("1", cycle(1, 2, 3, :name => "numbers"))
|
||||
assert_equal("red", cycle("red", "blue", :name => "colors"))
|
||||
assert_equal("2", cycle(1, 2, 3, :name => "numbers"))
|
||||
assert_equal("blue", cycle("red", "blue", :name => "colors"))
|
||||
assert_equal("3", cycle(1, 2, 3, :name => "numbers"))
|
||||
assert_equal("red", cycle("red", "blue", :name => "colors"))
|
||||
end
|
||||
|
||||
def test_default_named_cycle
|
||||
assert_equal("1", cycle(1, 2, 3))
|
||||
assert_equal("2", cycle(1, 2, 3, :name => "default"))
|
||||
assert_equal("3", cycle(1, 2, 3))
|
||||
end
|
||||
|
||||
def test_reset_cycle
|
||||
assert_equal("1", cycle(1, 2, 3))
|
||||
assert_equal("2", cycle(1, 2, 3))
|
||||
reset_cycle
|
||||
assert_equal("1", cycle(1, 2, 3))
|
||||
end
|
||||
|
||||
def test_reset_unknown_cycle
|
||||
reset_cycle("colors")
|
||||
end
|
||||
|
||||
def test_recet_named_cycle
|
||||
assert_equal("1", cycle(1, 2, 3, :name => "numbers"))
|
||||
assert_equal("red", cycle("red", "blue", :name => "colors"))
|
||||
reset_cycle("numbers")
|
||||
assert_equal("1", cycle(1, 2, 3, :name => "numbers"))
|
||||
assert_equal("blue", cycle("red", "blue", :name => "colors"))
|
||||
assert_equal("2", cycle(1, 2, 3, :name => "numbers"))
|
||||
assert_equal("red", cycle("red", "blue", :name => "colors"))
|
||||
end
|
||||
|
||||
def test_cycle_no_instance_variable_clashes
|
||||
@cycles = %w{Specialized Fuji Giant}
|
||||
assert_equal("red", cycle("red", "blue"))
|
||||
assert_equal("blue", cycle("red", "blue"))
|
||||
assert_equal("red", cycle("red", "blue"))
|
||||
assert_equal(%w{Specialized Fuji Giant}, @cycles)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue