#coding: utf-8 module BootstrapTabHelper extend ActiveSupport::Concern include BootstrapHelper class TabBuilder attr_accessor :tabs, :default_index, :options, :template def initialize(index, template, options={}) @default_index, @options, @template = index, options, template @tabs = {} end # tab label and content of tabs # # label - label of tab # options - # disabled - true, false default: false # clickable - true, false default: true # other options that can be accpted by li # pane_options - # every option that can be accepted by div def tab(label, options={}, &proc) default_options = {disabled: false, clickable: true} pane_options = options.delete(:pane_options) || {} @tabs[label] = [options.reverse_merge!(default_options), pane_options, proc] end def to_s style = @options.delete(:style) inline = @options.delete(:inline) position = @options.delete(:position) #align = @options.delete(:align) stacked = @options.delete(:stacked) @options[:class] ||= '' @options[:class] << ' nav-stacked' if stacked #@options[:class] << " pull-#{align}" if align @options[:class] << ' nav nav-tabs' if style == 'tab' @options[:class] << ' nav nav-pills' if style == 'pill' wrap_options = {style: "display: #{inline ? 'inline-block' : 'block'};", class: " tabbable tabs-#{position}"} content_options = @options.delete(:content_options) || {} content_options[:class] ||= '' content_options[:class] << ' tab-content' @template.div(wrap_options) do tab_content = '' tab_content << @template.list(@options) do |li| @tabs.keys.each do |k| render_label(li, style, k, @tabs.keys.index(k) == @default_index.to_i, "#{@options[:id]}-tab-#{@tabs.keys.index(k)}", @tabs[k][0]) end end tab_content << @template.div(content_options) do tab_panes = '' @tabs.values.each do |v| tab_panes << render_content(@tabs.values.index(v) == @default_index.to_i, "#{@options[:id]}-tab-#{@tabs.values.index(v)}", v[1], &v[2]) end tab_panes.html_safe end tab_content.html_safe end end private def render_label(li, style, title, show, link_id, options={}) tab_class = show ? 'active' : '' tab_class << ' disabled' if options.delete(:disabled) clickable = options.delete(:clickable) li.add @template.link_to(title.html_safe, "##{clickable ? link_id : ''}", data: {toggle: style}), options.merge!({class: tab_class}) end def render_content(show, link_id, options={}, &proc) options[:class] ||= '' options[:class] << " tab-pane #{show ? 'active' : ''}" options[:id] = link_id @template.div(options) do @template.capture(&proc) if proc end end end #显示tab页 #index: 默认显示第几个标签 #options: # style: pill, tab default: tab # position: below, left, right direction of tab # align: left, right. the alignment of tab, NOT AVAILABLE NOW # inline: true ,false default: false # stacked: true, false default: false # content_options # every option that can be accepted by div def tabs(index=0, options={}, &proc) default_options = {inline: false, stacked: false, id: 'tabs', style: 'tab'} index, options = 0, index if index.is_a?(Hash) builder = TabBuilder.new(index, self, options.reverse_merge!(default_options)) capture(builder, &proc) builder.to_s end end