bettertabs 1.3.6 → 1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,11 +9,14 @@ Bettertabs rails helper depends on the jquery.bettertabs plugin to work properly
9
9
  The jquery.bettertabs plugin is written using CoffeeScript.
10
10
  How to install CoffeeScript: http://jashkenas.github.com/coffee-script/#installation
11
11
 
12
- To install, first make sure you have a working copy of the latest stable version of Node.js, and npm (the Node Package Manager).
12
+ *OR* if you're lazzy and only care about a single compilation, use the online coffee compiler, copy-paste the js code and get back the coffee code, just in the [coffeescript web site](http://jashkenas.github.com/coffee-script/#installation). (if you do this way, please wrap the generated code with `(function() { --code-- }).call(this);`)
13
+
14
+ To install the coffee comand, first make sure you have a working copy of the latest stable version of Node.js, and npm (the Node Package Manager).
15
+
13
16
  You can then install CoffeeScript with npm:
14
17
 
15
18
  npm install coffee-script
16
-
19
+
17
20
 
18
21
  Then you will be able to compile `jquery.bettertabs.js.coffee` into `jquery.bettertabs.js` using the coffee command:
19
22
 
@@ -34,4 +37,4 @@ Online compressors:
34
37
  * http://refresh-sf.com/yui/
35
38
  * http://yui.2clics.net/
36
39
  * http://closure-compiler.appspot.com/home
37
- * http://compressorrater.thruhere.net/
40
+ * http://compressorrater.thruhere.net/
@@ -1,2 +1,15 @@
1
+ require 'bettertabs/configuration'
1
2
  require 'bettertabs/engine'
2
- require 'bettertabs/bettertabs_builder'
3
+ require 'bettertabs/bettertabs_builder'
4
+
5
+ module Bettertabs
6
+ class << self
7
+ def configuration
8
+ @configuration ||= Configuration.new
9
+ end
10
+
11
+ def configure
12
+ yield configuration
13
+ end
14
+ end
15
+ end
@@ -1,37 +1,48 @@
1
1
  class BettertabsBuilder
2
2
  require 'uri' # from standard library
3
-
3
+
4
4
  TAB_TYPES = [:static, :link, :ajax]
5
-
5
+
6
6
  def initialize(bettertabs_id, template, selected_tab_id = nil, options = {})
7
7
  @bettertabs_id = bettertabs_id
8
8
  @template = template
9
9
  @selected_tab_id = selected_tab_id
10
+ @list_html_options = options.delete(:list_html_options) # sets html_options on the :ul element
10
11
  @render_only_active_content = options.delete(:render_only_active_content) # used in ajax calls
11
12
  @wrapper_html_options = options
12
-
13
+
13
14
  @tabs = []
14
15
  @contents = []
15
16
  end
16
-
17
+
17
18
  # Static tabs generator
18
19
  def static(tab_id, *args, &block)
19
20
  get_options(args)[:tab_type] = :static
20
21
  self.for(tab_id, *args, &block)
21
22
  end
22
-
23
+
23
24
  # Linked tabs generator
24
25
  def link(tab_id, *args, &block)
25
26
  get_options(args)[:tab_type] = :link
26
27
  self.for(tab_id, *args, &block)
27
28
  end
28
-
29
+
29
30
  # Ajax tabs generator
30
31
  def ajax(tab_id, *args, &block)
31
32
  get_options(args)[:tab_type] = :ajax
32
33
  self.for(tab_id, *args, &block)
33
34
  end
34
-
35
+
36
+ # No tab generator, to add only content
37
+ def only_content_block(options = {}, &block)
38
+ content_html_options = {class: 'content content-only-block'}
39
+ unless @render_only_active_content
40
+ content = block_given? ? @template.capture(&block) : @template.render(:partial => options[:partial], :locals => options[:locals])
41
+ @contents << { content: content, html_options: content_html_options, tab_type: :only_content_block }
42
+ end
43
+ nil # returning nil allows the user to call this using <%= tab.only_content_block %> or <% tab.only_content_block %>
44
+ end
45
+
35
46
  # Generic tab and content generator
36
47
  def for(tab_id, *args, &block)
37
48
  # Initialize vars and options
@@ -40,25 +51,27 @@ class BettertabsBuilder
40
51
  tab_text = get_tab_text(tab_id, args)
41
52
  raise "Bettertabs: #{tab_html_id_for(tab_id)} error. Used :partial option and a block of content at the same time." if block_given? and options[:partial]
42
53
  partial = options.delete(:partial) || tab_id.to_s unless block_given?
54
+ raise "Bettertabs: #{tab_html_id_for(tab_id)} error. Used :locals option and a block of content at the same time." if block_given? and options[:locals]
55
+ locals = options.delete(:locals) unless block_given?
43
56
  url = options.delete(:url) || @template.params.merge(:"#{@bettertabs_id}_selected_tab" => tab_id)
44
57
  tab_type = (options.delete(:tab_type) || :static).to_sym
45
58
  raise "Bettertabs: #{tab_type.inspect} tab type not supported. Use one of #{TAB_TYPES.inspect} instead." unless TAB_TYPES.include?(tab_type)
46
59
  ajax_url = options.delete(:ajax_url) || url_for_ajax(url) if tab_type == :ajax
47
60
  @selected_tab_id ||= tab_id # defaults to first tab
48
-
61
+
49
62
  if @render_only_active_content
50
63
  if active?(tab_id)
51
- @only_active_content = block_given? ? @template.capture(&block) : @template.render(:partial => partial)
64
+ @only_active_content = block_given? ? @template.capture(&block) : @template.render(:partial => partial, :locals => locals)
52
65
  end
53
66
  else
54
67
  # Tabs
55
68
  tab_html_options = options # any other option will be used as tab html_option
56
69
  @tabs << { tab_id: tab_id, text: tab_text, url: url, ajax_url: ajax_url, html_options: tab_html_options, tab_type: tab_type, active: active?(tab_id) }
57
-
70
+
58
71
  # Content
59
72
  content_html_options = { id: content_html_id_for(tab_id), class: "content #{active?(tab_id) ? 'active' : 'hidden'}" }
60
73
  if active?(tab_id) or tab_type == :static # Only render content for selected tab (static content is always rendered).
61
- content = block_given? ? @template.capture(&block) : @template.render(:partial => partial)
74
+ content = block_given? ? @template.capture(&block) : @template.render(:partial => partial, :locals => locals)
62
75
  else
63
76
  content = ''
64
77
  end
@@ -66,7 +79,7 @@ class BettertabsBuilder
66
79
  end
67
80
  nil # returning nil allows the user to call this using <%= tab.for :xxx %> or <% tab.for :xxx %>
68
81
  end
69
-
82
+
70
83
  # Renders the bettertabs markup.
71
84
  # The following instance variables are available:
72
85
  # * @tabs: list of tabs. Each one is a hash with the followin keys:
@@ -90,16 +103,19 @@ class BettertabsBuilder
90
103
  if @render_only_active_content
91
104
  @only_active_content.html_safe
92
105
  else
93
-
106
+
94
107
  # Wrapper
95
108
  @wrapper_html_options ||= {}
96
109
  @wrapper_html_options[:"data-initial-active-tab-id"] = tab_html_id_for @selected_tab_id
97
- tag(:div, @wrapper_html_options) do
98
-
110
+ content_tag(:div, @wrapper_html_options) do
111
+
99
112
  # Tabs list
100
- tag(:ul, class: 'tabs') do
113
+ @list_html_options ||= {}
114
+ @list_html_options[:class] ||= ''
115
+ @list_html_options[:class] += @list_html_options[:class].empty? ? 'tabs' : ' tabs'
116
+ content_tag(:ul, @list_html_options) do
101
117
  @tabs.map do |tab|
102
- tag(:li, class: ('active' if tab[:active]), id: tab_html_id_for(tab[:tab_id])) do
118
+ content_tag(:li, class: ('active' if tab[:active]), id: tab_html_id_for(tab[:tab_id])) do
103
119
  tab[:html_options][:"data-tab-type"] ||= tab[:tab_type] # for javascript: change click behavior depending on type :static, :link or :ajax
104
120
  tab[:html_options][:"data-show-content-id"] ||= content_html_id_for(tab[:tab_id]) # for javascript: element id to show when select this tab
105
121
  tab[:html_options][:"data-ajax-url"] ||= tab[:ajax_url] if tab[:tab_type] == :ajax # for javascript: url to make ajax call
@@ -109,52 +125,52 @@ class BettertabsBuilder
109
125
  end
110
126
  end.join.html_safe
111
127
  end +
112
-
128
+
113
129
  # Content sections
114
130
  @contents.map do |content|
115
- tag(:div, content[:html_options]) do
131
+ content_tag(:div, content[:html_options]) do
116
132
  content[:content] # this should be blank unless content[:active] or content[:tab_type] == :static
117
133
  end
118
134
  end.join.html_safe
119
135
  end.html_safe
120
-
136
+
121
137
  end
122
138
  end
123
-
124
-
139
+
140
+
125
141
  private
126
-
142
+
127
143
  # Get the options hash from an array of args. If options are not present, create them and initialize to {}
128
144
  def get_options(args)
129
145
  args << {} unless args.last.is_a?(Hash)
130
146
  args.last
131
147
  end
132
-
148
+
133
149
  # Get the default name of the tab, from the args list.
134
150
  def get_tab_text(tab_id, args)
135
151
  String === args.first ? args.first : tab_id.to_s.titleize
136
152
  end
137
-
153
+
138
154
  # Check if this tab_id is the same as @selected_tab_id
139
155
  def active?(tab_id)
140
156
  @selected_tab_id.to_s == tab_id.to_s
141
157
  end
142
-
158
+
143
159
  # Tab html id
144
160
  def tab_html_id_for(tab_id)
145
161
  "#{tab_id}_#{@bettertabs_id}_tab"
146
162
  end
147
-
163
+
148
164
  # Content html id
149
165
  def content_html_id_for(tab_id)
150
166
  "#{tab_id}_#{@bettertabs_id}_content"
151
167
  end
152
-
153
- # Alias of @template.content_tag
154
- def tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block)
168
+
169
+ # Delegate @template.content_tag
170
+ def content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block)
155
171
  @template.content_tag(name, content_or_options_with_block, options, escape, &block)
156
172
  end
157
-
173
+
158
174
  # Uses @template.url_for() to create the string url, and then URI.parse to add the ajax=true extra param.
159
175
  # This "ajax=true" extra param is important for two reasons:
160
176
  # * It makes easier from the controller to know when a request is ajax or not.
@@ -171,5 +187,5 @@ class BettertabsBuilder
171
187
  original_url
172
188
  end
173
189
  end
174
-
175
- end
190
+
191
+ end
@@ -0,0 +1,10 @@
1
+ module Bettertabs
2
+ class Configuration
3
+ attr_accessor :attach_jquery_bettertabs_inline
4
+
5
+ def initialize
6
+ # defaults
7
+ @attach_jquery_bettertabs_inline = false
8
+ end
9
+ end
10
+ end
@@ -1,3 +1,3 @@
1
1
  module Bettertabs
2
- VERSION = "1.3.6"
3
- end
2
+ VERSION = "1.4"
3
+ end
@@ -1,24 +1,27 @@
1
1
  class BettertabsController < ApplicationController
2
-
2
+
3
3
  def static
4
4
  end
5
-
5
+
6
6
  def link_tab_1
7
7
  end
8
-
8
+
9
9
  def link_tab_2
10
10
  end
11
-
11
+
12
12
  def ajax
13
13
  render partial: 'ajax' and return if request.xhr?
14
14
  end
15
-
15
+
16
+ def only_content_block
17
+ end
18
+
16
19
  def mixed
17
20
  render partial: 'mixed' and return if request.xhr?
18
21
  end
19
-
22
+
20
23
  def mixed_with_erb
21
24
  render partial: 'tab_content' and return if request.xhr? and params[:erb_test_selected_tab] == 'ajax_tab'
22
25
  end
23
-
26
+
24
27
  end
@@ -3,4 +3,6 @@
3
3
  Content for the link tab
4
4
  = tab.static :static_tab do
5
5
  Content for the static tab
6
- = tab.ajax :ajax_tab, partial: 'tab_content'
6
+ = tab.ajax :ajax_tab, partial: 'tab_content'
7
+ = tab.only_content_block do
8
+ This block is always visible (has not tab)
@@ -1 +1,4 @@
1
- tab_content partial content.
1
+ - if local_assigns.has_key? :local_var
2
+ = local_var
3
+ - else
4
+ tab_content partial content.
@@ -5,4 +5,7 @@
5
5
  <% end %>
6
6
  <%= tab.static :static_tab, partial: 'tab_content' %>
7
7
  <%= tab.ajax :ajax_tab, partial: 'tab_content' %>
8
- <% end %>
8
+ <%= tab.only_content_block do %>
9
+ This block is always visible (has not tab)
10
+ <% end %>
11
+ <% end %>
@@ -0,0 +1,12 @@
1
+ %h2 Testing Content Blocks (that have with no tab) mixed with static tabs
2
+ = bettertabs :static, :class => 'bettertabs example', :list_html_options => {:class => 'list_class'} do |tab|
3
+ = tab.only_content_block do
4
+ Content for only_content_block_1
5
+
6
+ = tab.static :static_tab_1 do
7
+ Content for static_tab_1
8
+
9
+ = tab.only_content_block :partial => 'tab_content', :locals => {:local_var => 'Content for only_content_block_2'}
10
+
11
+ = tab.static :static_tab_2 do
12
+ Content for static_tab_2
@@ -1,7 +1,10 @@
1
1
  %h2 Testing static tabs
2
- = bettertabs :static do |tab|
2
+ = bettertabs :static, :class => 'bettertabs example', :list_html_options => {:class => 'list_class'} do |tab|
3
+
3
4
  = tab.static :static_tab_1 do
4
5
  Content for static_tab_1
6
+
5
7
  = tab.static :static_tab_2 do
6
8
  Content for static_tab_2
7
- = tab.static :tab_content, 'Static Tab 3' # should render partial 'tab_content'
9
+
10
+ = tab.static :tab_content, 'Static Tab 3', :locals => {:local_var => 'Content for static_tab_3'} # should render partial 'tab_content'
@@ -14,13 +14,14 @@
14
14
  <%= link_to 'see code in Github', 'http://github.com/agoragames/bettertabs/tree/master/spec/dummy' %></br>
15
15
  For this demo, the hidden content is shown inside a dashed border to see what is loaded when you click a tab,</br>
16
16
  click on the links below to see different types of tabs (static, link or ajax).
17
-
17
+
18
18
  </p>
19
19
  <div class="nav">
20
- <%= link_to 'static', { action: 'static'}, title: 'Using only static tabs' %> |
21
- <%= link_to 'link', { action: 'link_tab_1'}, title: 'Using only link tabs' %> |
22
- <%= link_to 'ajax', { action: 'ajax'}, title: 'Using only ajax tabs' %> |
23
- <%= link_to 'mixed', { action: 'mixed'}, title: 'Using static, link and ajax tabs in the same widget' %> |
20
+ <%= link_to 'static', { action: 'static'}, title: 'Using only static tabs' %> |
21
+ <%= link_to 'link', { action: 'link_tab_1'}, title: 'Using only link tabs' %> |
22
+ <%= link_to 'ajax', { action: 'ajax'}, title: 'Using only ajax tabs' %> |
23
+ <%= link_to 'content blocks', { action: 'only_content_block'}, title: 'Also content with no tabs' %> |
24
+ <%= link_to 'mixed', { action: 'mixed'}, title: 'Using static, link and ajax tabs in the same widget' %> |
24
25
  <%= link_to 'mixed (erb)', { action: 'mixed_with_erb'}, title: 'Using static, link and ajax tabs in a ERB template' %>
25
26
  </div>
26
27
 
@@ -0,0 +1,6 @@
1
+ Bettertabs.configure do |config|
2
+ # Render a Javascript snippet to initialize the tabs automatically after rendering the tabs.
3
+ # This requires that you include jQuery before the tabs are rendered.
4
+ # Default: false
5
+ config.attach_jquery_bettertabs_inline = true
6
+ end
@@ -6,11 +6,12 @@
6
6
  # * options can be:
7
7
  # * :selected_tab => tab_id to select by default
8
8
  # * :selected_tab should be overridden with params[:"#{bettertabs_id}_selected_tab"] if present
9
+ # * :list_html_options => html_options for the :ul element
9
10
  # * any other option is used as wrapper html_options (wrapper is the top-level widget dom element).
10
11
  # * The bettertabs helper should render clear markup:
11
12
  # * A wrapper with class 'bettertabs'
12
13
  # * Tabs markup
13
- # * ul.tabs > li > a
14
+ # * ul.tabs > li > a
14
15
  # * selected tab is ul.tabs > li.active > a
15
16
  # * each a element has element attributes:
16
17
  # * data-tab-type (for javascript: change click behavior depending on type "static", "link" or "ajax")
@@ -34,82 +35,105 @@
34
35
  require 'spec_helper'
35
36
 
36
37
  describe "Bettertabs requests" do
38
+
37
39
  describe "GET /bettertabs/static" do
38
- before(:all) { get '/bettertabs/static' }
39
-
40
+ before(:all) { get '/bettertabs/static' }
41
+
40
42
  it "has a 200 status code" do
41
43
  response.status.should be(200)
42
44
  end
43
-
45
+
44
46
  it "should render all content even for hidden tabs" do
45
47
  response.body.should include("Content for static_tab_1")
46
48
  response.body.should include("Content for static_tab_2")
47
- response.body.should include("tab_content partial content")
49
+ response.body.should include("Content for static_tab_3")
48
50
  end
49
-
51
+
50
52
  it "should not include the attribute data-ajax-url in static tabs" do
51
53
  response.body.should_not include("data-ajax-url")
52
54
  end
55
+
56
+ it "should set the requested wrapper class" do
57
+ response.body.should have_selector("div.bettertabs.example")
58
+ end
59
+
60
+ it "should set the requested list class" do
61
+ response.body.should have_selector("ul.list_class")
62
+ end
53
63
  end
54
-
64
+
55
65
  describe "GET /bettertabs/link_tab_1" do
56
- before(:all) { get '/bettertabs/link_tab_1' }
66
+ before(:all) { get '/bettertabs/link_tab_1' }
57
67
  it "has a 200 status code" do
58
68
  response.status.should be(200)
59
69
  end
60
-
70
+
61
71
  it "should not include the attribute data-ajax-url in link tabs" do
62
72
  response.body.should_not include("data-ajax-url")
63
73
  end
64
-
74
+
65
75
  end
66
76
 
67
77
  describe "GET /bettertabs/link_tab_2" do
68
- before(:all) { get '/bettertabs/link_tab_2' }
78
+ before(:all) { get '/bettertabs/link_tab_2' }
69
79
  it "has a 200 status code" do
70
80
  response.status.should be(200)
71
81
  end
72
82
  end
73
83
 
74
84
  describe "GET /bettertabs/ajax" do
75
- before(:all) { get '/bettertabs/ajax' }
85
+ before(:all) { get '/bettertabs/ajax' }
76
86
  it "has a 200 status code" do
77
87
  response.status.should be(200)
78
88
  end
79
-
89
+
80
90
  it "should include the attribute data-ajax-url in ajax tabs" do
81
91
  response.body.should include("data-ajax-url")
82
92
  end
83
-
93
+
84
94
  it "should include the default ajax=true extra param in the data-ajax-url" do
85
95
  response.body.should include("data-ajax-url=\"/bettertabs/ajax/ajax_tab_2?ajax=true\"")
86
96
  end
87
-
97
+
88
98
  it "should render only the selected tab content" do
89
99
  response.body.should include("Content for the ajax_tab_1")
90
100
  response.body.should_not include("Content for the ajax_tab_2")
91
101
  end
92
-
102
+
93
103
  it "should select another tab if requested in the URL" do
94
104
  get '/bettertabs/ajax?ajax_selected_tab=ajax_tab_2'
95
105
  response.body.should_not include("Content for the ajax_tab_1")
96
106
  response.body.should include("Content for the ajax_tab_2")
97
107
  end
98
108
  end
99
-
109
+
110
+ describe "GET /bettertabs/only_content_block" do
111
+ before(:all) { get '/bettertabs/only_content_block' }
112
+
113
+ it "has a 200 status code" do
114
+ response.status.should be(200)
115
+ end
116
+
117
+ it "should render all content including content blocks" do
118
+ response.body.should include("Content for only_content_block_1")
119
+ response.body.should include("Content for static_tab_1")
120
+ response.body.should include("Content for only_content_block_2")
121
+ response.body.should include("Content for static_tab_2")
122
+ end
123
+ end
124
+
100
125
  describe "GET /bettertabs/mixed" do
101
- before(:all) { get '/bettertabs/mixed' }
126
+ before(:all) { get '/bettertabs/mixed' }
102
127
  it "has a 200 status code" do
103
128
  response.status.should be(200)
104
129
  end
105
130
  end
106
-
131
+
107
132
  describe "GET /bettertabs/mixed_with_erb" do
108
- before(:all) { get '/bettertabs/mixed_with_erb' }
133
+ before(:all) { get '/bettertabs/mixed_with_erb' }
109
134
  it "has a 200 status code" do
110
135
  response.status.should be(200)
111
136
  end
112
- end
137
+ end
113
138
 
114
-
115
139
  end