92 lines
2.3 KiB
Ruby
92 lines
2.3 KiB
Ruby
module CarouselHelper
|
|
def carousel_for(images, options = {}, &block)
|
|
Carousel.new(self, images, options, block).html
|
|
end
|
|
|
|
class Carousel
|
|
def initialize(view, images, options, block)
|
|
@view = view
|
|
@images = images
|
|
@options = options
|
|
@block = block
|
|
end
|
|
|
|
def html
|
|
css = ["carousel", "slide"] << options[:class].to_s.split(" ")
|
|
|
|
content = [].tap do |content|
|
|
content << indicators if show_indicators?
|
|
content << slides
|
|
content << controls if show_controls?
|
|
end
|
|
|
|
content_tag(:div, safe_join(content), id: uid, class: css)
|
|
end
|
|
|
|
private
|
|
|
|
attr_accessor :view, :images, :options, :block
|
|
delegate :link_to, :content_tag, :image_tag, :safe_join, :concat, :capture, to: :view
|
|
|
|
def show_controls?
|
|
options.fetch(:controls, true)
|
|
end
|
|
|
|
def show_indicators?
|
|
options.fetch(:indicators, true)
|
|
end
|
|
|
|
def uid
|
|
@uid ||= "carousel_#{SecureRandom.hex(6)}"
|
|
end
|
|
|
|
def indicators
|
|
items = images.count.times.map { |index| indicator_tag(index) }
|
|
content_tag(:ol, safe_join(items), class: 'carousel-indicators')
|
|
end
|
|
|
|
def indicator_tag(index)
|
|
options = {
|
|
class: (index.zero? ? 'active' : ''),
|
|
data: {
|
|
target: "##{uid}",
|
|
slide_to: index
|
|
}
|
|
}
|
|
|
|
content_tag(:li, '', options)
|
|
end
|
|
|
|
def slides
|
|
items = images.map.with_index { |image, index| slide_tag(image, index.zero?) }
|
|
content_tag(:div, safe_join(items), class: 'carousel-inner')
|
|
end
|
|
|
|
def slide_tag(image, is_active)
|
|
options = {
|
|
class: (is_active ? 'carousel-item active' : 'carousel-item'),
|
|
}
|
|
|
|
slide_content = @block.present? ? capture(image, &@block) : image_tag(image)
|
|
content_tag(:div, slide_content, options)
|
|
end
|
|
|
|
def controls
|
|
safe_join([control_tag('prev'), control_tag('next')])
|
|
end
|
|
|
|
def control_tag(direction)
|
|
options = {
|
|
class: "carousel-control-#{direction}",
|
|
data: { slide: direction },
|
|
role: "button"
|
|
}
|
|
|
|
link_to "##{uid}", options do
|
|
concat content_tag(:span, '', class: "carousel-control-#{direction}-icon", aria: { hidden: true })
|
|
concat content_tag(:span, direction.titleize, class: "sr-only")
|
|
end
|
|
end
|
|
end
|
|
end
|