bettertabs 1.0 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +30 -0
- data/EXAMPLES.md +212 -0
- data/README.md +84 -199
- data/bettertabs.gemspec +3 -3
- data/lib/bettertabs/bettertabs_builder.rb +32 -12
- data/lib/bettertabs/bettertabs_helper.rb +47 -3
- data/lib/bettertabs/javascripts/jquery.bettertabs.coffee +5 -3
- data/lib/bettertabs/javascripts/jquery.bettertabs.js +6 -4
- data/lib/bettertabs/stylesheets/README.md +80 -0
- data/lib/bettertabs/version.rb +1 -1
- data/test/ruby_1_9/rails_3_0/Gemfile.lock +4 -4
- data/test/ruby_1_9/rails_3_0/app/views/bettertabs/_ajax.html.haml +2 -2
- data/test/ruby_1_9/rails_3_0/app/views/bettertabs/_link.html.haml +1 -1
- data/test/ruby_1_9/rails_3_0/app/views/layouts/application.html.erb +1 -1
- data/test/ruby_1_9/rails_3_0/public/javascripts/jquery.bettertabs.js +83 -0
- data/test/ruby_1_9/rails_3_0/public/stylesheets/bettertabs.css +1 -0
- data/test/ruby_1_9/rails_3_0/spec/requests/bettertabs_spec.rb +70 -9
- metadata +11 -17
- data/test/ruby_1_9/rails_3_0/public/javascripts/jquery.bettertabs.min.js +0 -4
data/CHANGELOG
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
Bettertabs Changelog
|
2
|
+
====================
|
3
|
+
|
4
|
+
|
5
|
+
2011-04-28 Mario Izquierdo Martinez <tothemario@gmail.com>
|
6
|
+
|
7
|
+
* Tag v1.1
|
8
|
+
* Added :ajax_url option to tab builder, defaults to :url plus the ajax=true param to prevent browser cache issues.
|
9
|
+
* bettertabs helper :class html_option replace the 'bettertabs' default class instead of adding it (there was no way to remove that class).
|
10
|
+
* Bugfix: don't add .hidden CSS class to non active tabs (it should only be added to non active content).
|
11
|
+
* Documentation improvement:
|
12
|
+
* Added jquery.bettertabs documentation (REAMDE.md)
|
13
|
+
* Added some CSS examples and documentation (lib/bettertabs/stylesheets/README.md)
|
14
|
+
* README.md review and clean-up, moved examples to EXAMPLES.md.
|
15
|
+
* Added Routes examples (README.md)
|
16
|
+
* Added bettertabs helper documentation (params and options in the method comment)
|
17
|
+
|
18
|
+
2011-04-22 Mario Izquierdo Martinez <tothemario@gmail.com>
|
19
|
+
|
20
|
+
* Tag v1.0
|
21
|
+
* bettertabs rails helper, with static, link and ajax tabs
|
22
|
+
* jquery.bettertabs plugin, that activate the clicked tab, loads ajax content and change the url using HTML history.replaceState() javascript method.
|
23
|
+
* README.md documentation improved with examples
|
24
|
+
* Rails3 (ruby 1.9.2) test application (in the test folder) with some use cases and some basic rspec tests.
|
25
|
+
|
26
|
+
2011-03-31 Mario Izquierdo Martinez <tothemario@gmail.com>
|
27
|
+
|
28
|
+
* Tag v0.0.1
|
29
|
+
* Initial development and structure for the gem
|
30
|
+
* Initial documentation (README.md file)
|
data/EXAMPLES.md
ADDED
@@ -0,0 +1,212 @@
|
|
1
|
+
# Bettertabs Usage and Examples #
|
2
|
+
|
3
|
+
## Link Tabs Example ##
|
4
|
+
|
5
|
+
A simple tabbed content can be created using linked tabs:
|
6
|
+
|
7
|
+
In view `app/views/home/simple.html.erb`:
|
8
|
+
|
9
|
+
<%= bettertabs :simpletabs do |tab| %>
|
10
|
+
<%= tab.link :tab1, 'Tab One' do %>
|
11
|
+
Hello world.
|
12
|
+
<% end %>
|
13
|
+
<%= tab.link :tab2, 'Tab Two' do %>
|
14
|
+
This is the <b>dark side</b> of the moon.
|
15
|
+
<% end %>
|
16
|
+
<% end %>
|
17
|
+
|
18
|
+
|
19
|
+
This will define a linked two-tabs widget. The second tab ("Tab Two") is a link to the same url, but with the extra param `?simpletabs_selected_tab=tab2`, that will make the bettertabs helper activate the :tab2 tab.
|
20
|
+
|
21
|
+
In this case no JavaScript is required, and a new request will be performed when click the tabs links.
|
22
|
+
|
23
|
+
|
24
|
+
## Static Tabs Example ##
|
25
|
+
|
26
|
+
This example will show three tabs: "Home", "Who am I?" and "Contact Me".
|
27
|
+
The partials and files organization used in this examples are not mandatory but recommended, to make the change to ajax tabs very easy if needed.
|
28
|
+
|
29
|
+
In view `app/views/home/index.html.erb`:
|
30
|
+
|
31
|
+
<h1>Static Tabs Example</h1>
|
32
|
+
<%= render 'mytabs' %>
|
33
|
+
|
34
|
+
In partial `app/views/home/_mytabs.html.erb`:
|
35
|
+
|
36
|
+
<%= bettertabs :mytabs do |tab| %>
|
37
|
+
<%= tab.static :home do %>
|
38
|
+
<h2>Home</h2>
|
39
|
+
<%= raw @content_for_home %>
|
40
|
+
<% end %>
|
41
|
+
<%= tab.static :about, 'Who am I?', :partial => '/shared/about' %>
|
42
|
+
<%= tab.static :contact_me %>
|
43
|
+
<% end %>
|
44
|
+
|
45
|
+
|
46
|
+
The :about and :contact_me tabs will get the content from the referenced partials. Put any content there, for example:
|
47
|
+
|
48
|
+
In partial `app/views/shared/_about.html.erb`:
|
49
|
+
|
50
|
+
Hello, my name is <%= @myname %>.
|
51
|
+
|
52
|
+
In partial `app/views/home/_contact_me.html.erb`:
|
53
|
+
|
54
|
+
<h2>How to contact me:<h2/>
|
55
|
+
<p><%= @contact_info.inspect %></p>
|
56
|
+
|
57
|
+
In controller `app/controllers/home_controller.rb`:
|
58
|
+
|
59
|
+
class HomeController < ApplicationController
|
60
|
+
|
61
|
+
def index
|
62
|
+
# Declare instance variables as usual
|
63
|
+
@content_for_home = very_slow_function()
|
64
|
+
@myname = 'Lucifer'
|
65
|
+
@contact_info = { :address => 'The Hell', :telephone => '666'}
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
This will work with and without JavaScript, anyway, all vars and content should be loaded in the request because all static tabs need to render its content.
|
71
|
+
|
72
|
+
|
73
|
+
## AJAX tabs ##
|
74
|
+
|
75
|
+
Ajax tabs perform an asynchronous call to get the content before showing it. Giving the tab.ajax definition:
|
76
|
+
|
77
|
+
tab.ajax :home, :url => '/home/index', :ajax_url => '/home/ajax_tab'
|
78
|
+
|
79
|
+
supposing the bettertabs_id is :mytabs, it will generate the following markup for the tab item:
|
80
|
+
|
81
|
+
<li id="home_mytabs_tab">
|
82
|
+
<a data-tab-type="ajax"
|
83
|
+
data-show-content-id="home_mytabs_content"
|
84
|
+
data-ajax-url="/home/ajax_tab"
|
85
|
+
href="/home/index">
|
86
|
+
Home
|
87
|
+
</a>
|
88
|
+
</li>
|
89
|
+
|
90
|
+
The attributes *data-tab-type*, *data-show-content-id* and *data-ajax-url* will be used by the jquery.bettertabs plugin.
|
91
|
+
|
92
|
+
So here there are two important options:
|
93
|
+
|
94
|
+
* :url => The tag link href. Is used to change the browser url (html5 browsers only) and as url when JavaScript is off. Default to current url plus the param `#{bettertabs_id}_selected_tab=#{tab_id}`.
|
95
|
+
* :ajax_url => Defaults to :url plus the param `ajax=true`. Is used to perform the ajax request.
|
96
|
+
|
97
|
+
Both options have a default value, so if you just write:
|
98
|
+
|
99
|
+
tab.ajax :home
|
100
|
+
|
101
|
+
supposing the bettertabs_id is :mytabs, and the current url is '/home', it will generate the following markup for the tab item:
|
102
|
+
|
103
|
+
<li id="home_mytabs_tab">
|
104
|
+
<a data-tab-type="ajax"
|
105
|
+
data-show-content-id="home_mytabs_content"
|
106
|
+
data-ajax-url="/home?mytabs_selected_tab=home&ajax=true"
|
107
|
+
href="/home?mytabs_selected_tab=home">
|
108
|
+
Home
|
109
|
+
</a>
|
110
|
+
</li>
|
111
|
+
|
112
|
+
In the controller you can check if you are receiving an ajax request just looking `if params[:ajax].present?`, or also using `request.xhr?` (that is a header that jQuery uses when perform an ajax request).
|
113
|
+
|
114
|
+
**Note**: The :url and :ajax_url values should not be the same because some browsers fetch the cache by url (ignoring the xhr header), and if we use the same url, we may go to a page and see the last ajax response instead of the whole page.
|
115
|
+
|
116
|
+
|
117
|
+
### Improve the Static Tabs Example with ajax ###
|
118
|
+
|
119
|
+
In the previous example, `@content_for_home = very_slow_function()` has to be executed even if the user see another tab content. Using ajax or link tabs, the content is only loaded when needed.
|
120
|
+
|
121
|
+
Lets create some tabs with ajax:
|
122
|
+
|
123
|
+
In view `app/views/home/index.html.erb`:
|
124
|
+
|
125
|
+
<h1>Ajax Tabs Example</h1>
|
126
|
+
<%= render 'mytabs' %>
|
127
|
+
|
128
|
+
In partial `app/views/home/_mytabs.html.erb`:
|
129
|
+
|
130
|
+
<%= bettertabs :mytabs do |tab| %>
|
131
|
+
<%= tab.ajax :home do %>
|
132
|
+
<h2>Home</h2>
|
133
|
+
<%= raw @content_for_home %>
|
134
|
+
<% end %>
|
135
|
+
<%= tab.ajax :about, 'Who am I?', :partial => '/shared/about' %>
|
136
|
+
<%= tab.ajax :contact_me %>
|
137
|
+
<% end %>
|
138
|
+
|
139
|
+
**Note** that the only difference between this example and the *static tabs example* is to use `tab.ajax` declaration instead of `tab.static`.
|
140
|
+
|
141
|
+
Partials `app/views/shared/_about.html.erb` and `app/views/home/_contact_us.html.erb` (same as in the *static tabs example*).
|
142
|
+
|
143
|
+
### The Controller Side ###
|
144
|
+
|
145
|
+
In controller `app/controllers/home_controller.rb`, you can load only the needed data for each tab:
|
146
|
+
|
147
|
+
class HomeController < ApplicationController
|
148
|
+
|
149
|
+
def index
|
150
|
+
# Execute only the selected tab needed code (optimization).
|
151
|
+
case params[:mytabs_selected_tab]
|
152
|
+
when 'home' then
|
153
|
+
@content_for_home = very_slow_function()
|
154
|
+
when 'about' then
|
155
|
+
@myname = 'Lucifer'
|
156
|
+
when 'contact_us' then
|
157
|
+
@contact_info = { :address => 'The Hell', :telephone => '666'}
|
158
|
+
end
|
159
|
+
|
160
|
+
# When ajax, render only the selected tab content (handled by bettertabs helper)
|
161
|
+
render :partial => 'mytabs' and return if request.xhr? # you can also check if params[:ajax].present?
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
The only needed code in the controller to make it work with ajax is the `render :partial => 'mytabs' and return if request.xhr?` line.
|
167
|
+
|
168
|
+
Since the *mytabs* partial just contains the bettertabs helper, and bettertabs helper will just render the selected content when request.xhr?, this line is enough to return the selected content to the ajax call, no matter which tab is selected (because it uses params[:mytabs_selected_tab] to select the right content to render).
|
169
|
+
|
170
|
+
|
171
|
+
### Advantages of having the bettertabs helper alone in a separated partial ###
|
172
|
+
|
173
|
+
* It works without JavaScript out-of-the-box (using default values)
|
174
|
+
* Since the URL is changed in the browser when a tab is clicked and it works without JavaScript, a permalink is defined for each tab, so it allows:
|
175
|
+
* to bookmark the page on any selected tab
|
176
|
+
* to reload the page keeping the selected tab
|
177
|
+
* to send the link to other person and he/she will open the selected tab
|
178
|
+
* Easily change the behavior of a tab to be `ajax`, `static` or `link`. It always work.
|
179
|
+
* Keep your views DRY, clean and readable
|
180
|
+
|
181
|
+
|
182
|
+
## Example using HAML and ruby1.9.2 ##
|
183
|
+
|
184
|
+
Is easy to mix all types of tabs, and customize them using the provided options:
|
185
|
+
|
186
|
+
= bettertabs :bettertabs_example, :selected_tab => :chooseme, :class => 'bettertabs example' do |tab|
|
187
|
+
|
188
|
+
= tab.static :simplest_tab, class: 'awesome-tab' do
|
189
|
+
Click this tab to see this content.
|
190
|
+
|
191
|
+
= tab.static :chooseme, 'Please, Click me!' # as default, renders partial: 'chooseme'
|
192
|
+
|
193
|
+
= tab.static :render_another_partial, partial: 'another_partial'
|
194
|
+
|
195
|
+
= tab.link :link_to_another_place, url: go_to_other_place_url # will make a new request
|
196
|
+
|
197
|
+
= tab.ajax :cool_ajax, ajax_url: remote_call_path, partial: 'cool_partial'
|
198
|
+
-# In this case, you shoud take care of that remote_call_path is using the same partial: 'cool_partial'
|
199
|
+
|
200
|
+
= tab.ajax :album, url: url_for(@album), partial: 'shared/album'
|
201
|
+
-# This one will make the ajax call to the ajax_url: url_for(@album, :ajax => true)
|
202
|
+
|
203
|
+
= tab.ajax :ajax_tab, title: 'Content is loaded only once'
|
204
|
+
|
205
|
+
|
206
|
+
## More documentation ##
|
207
|
+
|
208
|
+
* [Main README document](https://github.com/agoragames/bettertabs/blob/master/README.md)
|
209
|
+
* [Bettertabs Styles reference guide](https://github.com/agoragames/bettertabs/blob/master/lib/bettertabs/stylesheets/README.md)
|
210
|
+
* [Bettertabs helper](https://github.com/agoragames/bettertabs/blob/master/lib/bettertabs/bettertabs_helper.rb) (params and options)
|
211
|
+
* [Rails3 test demo application](https://github.com/agoragames/bettertabs/tree/master/test/ruby_1_9/rails_3_0)
|
212
|
+
* Anyway, don't be afraid of digging into the code, it's very straightforward.
|
data/README.md
CHANGED
@@ -6,18 +6,19 @@ We know that splitting content into several tabs is easy, but doing well, clean,
|
|
6
6
|
Bettertabs is a helper for Rails that renders the markup for a tabbed area in a easy and declarative way, forcing you to keep things simple and ensuring accessibility and usability, no matter if the content is loaded statically or via ajax.
|
7
7
|
|
8
8
|
|
9
|
-
## Features
|
9
|
+
## Features ##
|
10
10
|
|
11
|
-
*
|
11
|
+
* Rails helper to easily generate the tabs and content markup
|
12
|
+
* Provides a jQuery plugin to handle the JavaScript behavior
|
12
13
|
* Simplicity: Easy to install and easy to use
|
14
|
+
* Flexible and customizable
|
13
15
|
* Forces you to DRY-up your views for your tabbed content
|
14
16
|
* Forces you to make it awesome accessible and usable:
|
15
17
|
* Designed to work with and without JavaScript
|
16
|
-
* When click on a tab, the address bar url is changed (
|
18
|
+
* When click on a tab, the address bar url is changed (only in HTML5 browsers), so:
|
17
19
|
* The browser's back and reload buttons will still work as expected
|
18
20
|
* All tabbed sections can be permalinked, keeping the selected tab
|
19
|
-
*
|
20
|
-
* Makes testing views simple. Because it works without javascript, you can assert view components with the rails built-in functional and integration tests.
|
21
|
+
* Makes testing views simple. Because its easy to make it works without javascript, you can assert view components with the rails built-in functional and integration tests.
|
21
22
|
* The CSS styles are up to you.
|
22
23
|
|
23
24
|
|
@@ -26,7 +27,7 @@ Bettertabs is a helper for Rails that renders the markup for a tabbed area in a
|
|
26
27
|
* Rails 3
|
27
28
|
* The [Bettertabs jQuery plugin](https://github.com/agoragames/bettertabs/raw/master/lib/bettertabs/javascripts/jquery.bettertabs.min.js) (that requires [jQuery](http://jquery.com/) 1.3, 1.4 or 1.5)
|
28
29
|
|
29
|
-
Although you can use bettertabs without javascript, and also should be
|
30
|
+
Although you can use bettertabs without javascript, and also it should not be so difficult to create another JavaScript that handle the server side behavior, since the bettertabs helper only generates the appropiate markup.
|
30
31
|
|
31
32
|
|
32
33
|
## Install ##
|
@@ -51,238 +52,122 @@ Bettertabs supports three kinds of tabs:
|
|
51
52
|
* **Static Tabs**: Loads all content of all static tabs, but only show the active content; when click on another tab, activate its related content. When JavaScript disabled, it behaves like *link tabs*.
|
52
53
|
* **Ajax Tabs**: Loads only the active tab contents; when click on another tab, loads its content via ajax and show. When JavaScript disabled, it behaves like *link tabs*.
|
53
54
|
|
55
|
+
An usage example should be self explanatory (using HAML, but it also works with ERB and other template systems):
|
54
56
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
<% end %>
|
65
|
-
<%= tab.link :tab2, 'Tab Two' do %>
|
66
|
-
This is the <b>dark side</b> of the moon.
|
67
|
-
<% end %>
|
68
|
-
<% end %>
|
69
|
-
|
70
|
-
|
71
|
-
This will define a linked two-tabs widget. The second tab ("Tab Two") is a link to the same url, but with the extra param `?simpletabs_selected_tab=tab2`, that will make the bettertabs helper activate the :tab2 tab.
|
72
|
-
|
73
|
-
In this case no JavaScript is required, and a new request will be performed when click the tabs links.
|
74
|
-
To change this to a javascript static tabs, you only need to change `tab.link` declarations for `tab.static`.
|
75
|
-
To change this to ajax tabs, in this case, is only needed to change the `tab.link` declarations for `tab.ajax`.
|
76
|
-
|
77
|
-
|
78
|
-
### Static Tabs Example ###
|
79
|
-
|
80
|
-
This example will show three tabs: "Home", "Who am I?" and "Contact Me".
|
81
|
-
The partials and files organization used in this examples are not mandatory but recommended, it will make easier to change to ajax tabs if needed.
|
82
|
-
|
83
|
-
In view `app/views/home/index.html.erb`:
|
84
|
-
|
85
|
-
<h1>Static Tabs Example</h1>
|
86
|
-
<%= render 'mytabs' %>
|
87
|
-
|
88
|
-
In partial `app/views/home/_mytabs.html.erb`:
|
89
|
-
|
90
|
-
<%= bettertabs :mytabs do |tab| %>
|
91
|
-
<%= tab.static :home do %>
|
92
|
-
<h2>Home</h2>
|
93
|
-
<%= raw @content_for_home %>
|
94
|
-
<% end %>
|
95
|
-
<%= tab.static :about, 'Who am I?', :partial => '/shared/about' %>
|
96
|
-
<%= tab.static :contact_me %>
|
97
|
-
<% end %>
|
98
|
-
|
99
|
-
|
100
|
-
The :about and :contact_me tabs will get the content from the referenced partials. Put any content there, for example:
|
101
|
-
|
102
|
-
In partial `app/views/shared/_about.html.erb`:
|
57
|
+
= bettertabs :profile_tabs do |tab|
|
58
|
+
= tab.static :general, 'My Profile' do
|
59
|
+
%h2 General Info
|
60
|
+
= show_user_general_info(@user)
|
61
|
+
|
62
|
+
= tab.ajax :friends, :partial => 'shared/friends'
|
63
|
+
|
64
|
+
= tab.link :groups do
|
65
|
+
= render :partial => 'groups/user_groups', :locals => {user => @user}
|
103
66
|
|
104
|
-
|
67
|
+
### More examples and documentation: ###
|
105
68
|
|
106
|
-
|
69
|
+
* [EXAMPLES document](https://github.com/agoragames/bettertabs/blob/master/EXAMPLES.md)
|
70
|
+
* [Bettertabs Styles reference guide](https://github.com/agoragames/bettertabs/blob/master/lib/bettertabs/stylesheets/README.md)
|
71
|
+
* [Bettertabs helper](https://github.com/agoragames/bettertabs/blob/master/lib/bettertabs/bettertabs_helper.rb) (params and options)
|
72
|
+
* [Rails3 test demo application](https://github.com/agoragames/bettertabs/tree/master/test/ruby_1_9/rails_3_0)
|
73
|
+
* Anyway, don't be afraid of digging into the code, it's very straightforward.
|
74
|
+
|
107
75
|
|
108
|
-
|
109
|
-
<p><%= @contact_info.inspect %></p>
|
110
|
-
|
111
|
-
In controller `app/controllers/home_controller.rb`:
|
76
|
+
## Tabs Routes ##
|
112
77
|
|
113
|
-
|
78
|
+
By default, all tab links have the current url plus the `{bettertabs_id}_selected_tab` param with the tab_id value.
|
114
79
|
|
115
|
-
|
116
|
-
# Declare instance variables as usual
|
117
|
-
@content_for_home = very_slow_function()
|
118
|
-
@myname = 'Lucifer'
|
119
|
-
@contact_info = { :address => 'The Hell', :telephone => '666'}
|
120
|
-
end
|
80
|
+
For example, if you are rendering the next bettertabs widget:
|
121
81
|
|
122
|
-
|
82
|
+
= bettertabs :profile_tabs do |tab|
|
83
|
+
= tab.static :general
|
84
|
+
= tab.static :friends
|
123
85
|
|
124
|
-
|
86
|
+
in a view accessible by a route like this:
|
125
87
|
|
88
|
+
match 'profile/:nickname', :to => 'profiles#lookup', :as => 'profile'
|
126
89
|
|
127
|
-
|
90
|
+
When you go to `/profile/dude`, your tabs links will have the following hrefs:
|
128
91
|
|
129
|
-
|
92
|
+
* :general tab href: `/profile/dude?profile_tabs_selected_tab=general`
|
93
|
+
* :friends tab href: `/profile/dude?profile_tabs_selected_tab=friends`
|
130
94
|
|
131
|
-
|
95
|
+
If you're in a modern HTML5 browser then when click on a tab, the URL will change for one of the urls listed before (jquery.bettertabs), otherwise, you can turn the JavaScript off and the static tabs will become link tabs, so the URL will change as well.
|
132
96
|
|
133
|
-
|
97
|
+
To show a pretty url, you can just modify your named route to:
|
134
98
|
|
135
|
-
|
99
|
+
match 'profile/:nickname(/:profile_tabs_selected_tab)', :to => 'profiles#lookup', :as => 'profile'
|
136
100
|
|
137
|
-
|
138
|
-
<%= render 'mytabs' %>
|
101
|
+
So now the tabs links will point to the following URLs:
|
139
102
|
|
140
|
-
|
103
|
+
* :general tab href: `/profile/dude/general`
|
104
|
+
* :friends tab href: `/profile/dude/friends`
|
105
|
+
|
106
|
+
|
107
|
+
## JavaScript with the jquery.bettertabs plugin ##
|
141
108
|
|
142
|
-
|
143
|
-
<%= tab.ajax :home do %>
|
144
|
-
<h2>Home</h2>
|
145
|
-
<%= raw @content_for_home %>
|
146
|
-
<% end %>
|
147
|
-
<%= tab.ajax :about, 'Who am I?', :partial => '/shared/about' %>
|
148
|
-
<%= tab.ajax :contact_me %>
|
149
|
-
<% end %>
|
150
|
-
|
151
|
-
**Note** that the only difference between this example and the *static tabs example* is to use `tab.ajax` declaration instead of `tab.static`.
|
109
|
+
Installing the `bettertabs` gem in a rails project makes the bettertabs helper instantly available. This helper will generate markup that is prepared to be modified by JavaScript, and also includes an inline script at the bottom:
|
152
110
|
|
153
|
-
|
154
|
-
|
155
|
-
In controller `app/controllers/home_controller.rb`, you can load only the needed data for each tab:
|
111
|
+
jQuery(function($){ $('#bettertabs_id').bettertabs(); });
|
156
112
|
|
157
|
-
|
113
|
+
Which expects jQuery and jquery.bettertabs plugin to be loaded.
|
158
114
|
|
159
|
-
|
160
|
-
# Execute only the selected tab needed code (optimization).
|
161
|
-
case params[:mytabs_selected_tab]
|
162
|
-
when 'home' then
|
163
|
-
@content_for_home = very_slow_function()
|
164
|
-
when 'about' then
|
165
|
-
@myname = 'Lucifer'
|
166
|
-
when 'contact_us' then
|
167
|
-
@contact_info = { :address => 'The Hell', :telephone => '666'}
|
168
|
-
end
|
169
|
-
|
170
|
-
# When ajax, load only the selected tab content (handled by bettertabs helper)
|
171
|
-
respond_to do |format|
|
172
|
-
format.js { render :partial => 'mytabs' } # when ajax call, bettertabs only renders the active content.
|
173
|
-
end
|
174
|
-
end
|
115
|
+
The jquery.bettertabs plugin can be downloaded directly from the github repo:
|
175
116
|
|
176
|
-
|
117
|
+
* [CoffeeScript version](https://github.com/agoragames/bettertabs/raw/master/lib/bettertabs/javascripts/jquery.bettertabs.coffee)
|
118
|
+
* [JavaScript (generated by coffee) version](https://github.com/agoragames/bettertabs/raw/master/lib/bettertabs/javascripts/jquery.bettertabs.js)
|
119
|
+
* [Compressed JavaScript](https://github.com/agoragames/bettertabs/raw/master/lib/bettertabs/javascripts/jquery.bettertabs.min.js)
|
120
|
+
|
121
|
+
The plugin defines one single jQuery method `jQuery(selector).bettertabs();` that is applied to the generated markup.
|
177
122
|
|
178
|
-
|
123
|
+
This script will take the tab type from each tab link `data-tab-type` attribute (that can be "link", "static" or "ajax"), and will match each tab with its content using the tab link `data-show-content-id` attribute, that is the id of the related content.
|
179
124
|
|
180
|
-
|
125
|
+
Tabs of type "link" will be ignored (no JavaScript), while "static" and "ajax" tabs will change the active content (using the `.active` css class), and also will try to change the current URL.
|
181
126
|
|
182
|
-
#### Advantages if you follow this file structure ####
|
183
127
|
|
184
|
-
|
128
|
+
### Browser history and url manipulation ###
|
185
129
|
|
186
|
-
|
187
|
-
* Since the URL is changed in the browser when a tab is clicked and it works without JavaScript, a permalink is defined for each tab, so it allows:
|
188
|
-
* to bookmark the page on any selected tab
|
189
|
-
* to reload the page keeping the selected tab
|
190
|
-
* Easily change the behavior of a tab to be `ajax`, `static` or `link`. It always work.
|
191
|
-
* Keep your views DRY, clean and readable
|
130
|
+
When activate a tag, the URL is changed using [history.replaceState()](https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history), which only works on modern HTM5 browsers (older browsers can not change the URL, and I prefer not trying to use History.js or any other approach to give them support for them).
|
192
131
|
|
132
|
+
### Manipulating the bettertabs widget from other scripts ###
|
193
133
|
|
194
|
-
|
134
|
+
All parts of the bettertabs generated markup are identified using ids, so it is very easy to identify and modify any part of the inner content (just open your firebug and browse the generated markup).
|
195
135
|
|
196
|
-
|
136
|
+
* To activate a tab, simulate a click on the tab link: `jQuery('#bettertabsid_tabid_tab a').click();`
|
137
|
+
* To hook some behavior when someone clicks on a tab, attach a 'click' handler to the tab link or use any of the provided custom events.
|
138
|
+
* To show a loading clock or any other kind of feedback to the user while ajax is loading, use any of the provided custom events.
|
197
139
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
= tab.ajax :simple_ajax, title: 'Content is loaded when needed and only once.'
|
209
|
-
|
210
|
-
= tab.ajax :album, url: show_remote_album_path, partial: 'shared/album'
|
211
|
-
|
212
|
-
|
213
|
-
#### From the Controller: ####
|
214
|
-
|
215
|
-
The default tab :url option value is the current path but with `param[:"{bettertabs_id}_selected_tab"]` to the current tab id.
|
216
|
-
This means that, by default, you can handle all needed information in the same controller action for all tab contents. Of course you can change this using a different value for the :url option.
|
217
|
-
|
218
|
-
If the tab is ajax, the ajax call will be performed to the same url provided in the :url option.
|
219
|
-
You can know if a call is ajax checking if `controller.request.xhr?` is true.
|
140
|
+
Custom events that are attached to each tab content:
|
141
|
+
|
142
|
+
* 'bettertabs-before-deactivate': fired on content that is active and will be deactivated
|
143
|
+
* 'bettertabs-before-activate': fired on content that will be activated
|
144
|
+
* 'bettertabs-before-ajax-loading': fired on content container that will be activated just before be loaded using ajax
|
145
|
+
* 'bettertabs-after-deactivate': fired on content that was deactivated
|
146
|
+
* 'bettertabs-after-activate': fired on content that was activated
|
147
|
+
* 'bettertabs-after-ajax-loading': fired on content after it was loaded via ajax. Remember that the content is loaded via ajax only once.
|
148
|
+
|
149
|
+
If you want to do something on a content that was just loaded using ajax, you can do something like the following:
|
220
150
|
|
221
|
-
|
151
|
+
$("#bettertabsid_tabid_content").bind('bettertabs-after-ajax-loading', function(){
|
152
|
+
$(this).doSomething();
|
153
|
+
});
|
222
154
|
|
223
|
-
If `request.xhr?` is *false* then you can just render the action as usual, bettertabs helper will auto select the appropriate tab based on `params[:"{bettertabs_id}_selected_tab"]` value.
|
224
155
|
|
225
|
-
|
156
|
+
## CSS Styles ##
|
226
157
|
|
227
|
-
|
158
|
+
Bettertabs provides a rails helper to generate HTML and a jQuery plugin as JavaScript, but not any CSS styles because those are very different for each project and can not be abstracted into a common purpose CSS stylesheet.
|
159
|
+
|
160
|
+
Perhaps the most important CSS rule here is to define `display: none;` for `div.content.hidden`, because contents are never hidden using the jquery.hide() method or similar. The jquery.bettertabs plugin just adds the `.active` class to the active tab and active content, and the `.hidden` class to the non active content. You will need to use a CSS rule like this:
|
228
161
|
|
229
|
-
|
230
|
-
@common_for_all_tabs = code_here
|
231
|
-
|
232
|
-
# A simple way of execute code only for the selected tab.
|
233
|
-
# Note that static tabs are always rendered, even if they are not selected.
|
234
|
-
case params[:example_selected_tab]
|
235
|
-
when 'chooseme' then
|
236
|
-
code_only_for_this_tab
|
237
|
-
else
|
238
|
-
code_for_all_other_tabs
|
239
|
-
end
|
240
|
-
|
241
|
-
# Ready for ajax ...
|
242
|
-
# You can check request.xhr? or use the common method respond_to
|
243
|
-
respond_to do |format|
|
244
|
-
format.js { render :partial => 'bettertabs_example' } # render only the selected content
|
245
|
-
end
|
246
|
-
end
|
162
|
+
div.bettertabs div.content.hidden { display: none; }
|
247
163
|
|
164
|
+
Use the [Bettertabs Styles Reference Guide](https://github.com/agoragames/bettertabs/blob/master/lib/bettertabs/stylesheets/README.md) to get a stylesheet that you can use as a starting point.
|
248
165
|
|
249
166
|
|
250
|
-
##
|
167
|
+
## Future work ##
|
251
168
|
|
252
|
-
* Improve the Rails testing application
|
169
|
+
* Improve the Rails testing application
|
253
170
|
* it should use rspec and capybabra to test even the javascript (http://media.railscasts.com/videos/257_request_specs_and_capybara.mov)
|
254
171
|
* Try to make it work with ruby 1.8.x
|
255
|
-
*
|
172
|
+
* Allow disabling the change-url functionality with an option like `:change_browser_url => false`
|
256
173
|
|
257
|
-
|
258
|
-
## Current Spec sheet (will become automatic tests) ##
|
259
|
-
* Should always work with javascript disabled (using the urls of the tabs links)
|
260
|
-
* The bettertabs hepler should accept:
|
261
|
-
* args: (bettertabs_id, options)
|
262
|
-
* options can be:
|
263
|
-
* :selected_tab => tab_id to select by default
|
264
|
-
* :selected_tab should be overridden with params[:"#{bettertabs_id}_selected_tab"] if present
|
265
|
-
* any other option is used as wrapper html_options (wrapper is the top-level widget dom element).
|
266
|
-
* The bettertabs helper should render clear markup:
|
267
|
-
* A wrapper with class 'bettertabs'
|
268
|
-
* Tabs markup
|
269
|
-
* ul.tabs > li > a
|
270
|
-
* selected tab is ul.tabs > li.active > a
|
271
|
-
* each a element has element attributes:
|
272
|
-
* data-tab-type (for javascript: change click behavior depending on type "static", "link" or "ajax")
|
273
|
-
* data-show-content-id (for javascript: element id to show when select this tab)
|
274
|
-
* sections for each tab content.
|
275
|
-
* use a unique html id (based on bettertabs_id and tab_id) for each Tab and Content
|
276
|
-
* The bettertabs builder ".from" method should accept:
|
277
|
-
* args: (tab_id, tab_name, options, &block)
|
278
|
-
* args: (tab_id, options, &block)
|
279
|
-
* If block_given? the block is used as content related to this tab
|
280
|
-
* options can be:
|
281
|
-
* :partial => to use as content. Defaults to tab_id
|
282
|
-
* if block_given? this option can not be used (if used, raise an error)
|
283
|
-
* :url => for the tab link, that should go to this selected tab when javascript is disabled. Defaults to { :"#{bettertabs_id}_selected_tab" => tab_id }
|
284
|
-
* :tab_type => used in the markup as the link data-tab-type value. Can be :static, :link or :ajax (or the corresponding strings). Raise error otherwise. Defaults to :static.
|
285
|
-
* The bettertabs builder ".static", ".link" and ".ajax" methods are only a convenient way to use ".for" method with :tab_type set to :static, :link or :ajax respectively.
|
286
|
-
* Content is rendered only for active tab, except when tab_type is :static, where content is always rendered (ready to show when select that tab using javascript).
|
287
|
-
* When ajax call (format.js), the bettertabs helper should return ONLY the content of the selected tab (to simplify the controller render partial calls.).
|
288
|
-
|