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/bettertabs.gemspec
CHANGED
@@ -8,9 +8,9 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
9
|
s.authors = ["Mario Izquierdo"]
|
10
10
|
s.email = ["tothemario@gmail.com"]
|
11
|
-
s.homepage = ""
|
12
|
-
s.summary = %q{The better (simple, accessible, usable, flexible and fast) way to split content in tabs.}
|
13
|
-
s.description = %q{
|
11
|
+
s.homepage = "https://github.com/agoragames/bettertabs"
|
12
|
+
s.summary = %q{The better (simple, accessible, usable, flexible and fast) way to split content in tabs for Rails.}
|
13
|
+
s.description = %q{Bettertabs Rails helper (and jQuery plugin) defines the markup for a tabbed area in a easy and declarative way, using the appropiate JavaScript but ensuring accessibility and usability, no matter if the content is loaded statically, via ajax or the tabs are links. In the other hand, the CSS styles are up to you. }
|
14
14
|
|
15
15
|
s.rubyforge_project = "bettertabs"
|
16
16
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
class BettertabsBuilder
|
2
|
+
require 'uri' # from standard library
|
2
3
|
|
3
4
|
TAB_TYPE_STATIC = :static
|
4
5
|
TAB_TYPE_LINK = :link
|
@@ -45,6 +46,7 @@ class BettertabsBuilder
|
|
45
46
|
url = options.delete(:url) || { :"#{@bettertabs_id}_selected_tab" => tab_id }
|
46
47
|
tab_type = (options.delete(:tab_type) || TAB_TYPE_STATIC).to_sym
|
47
48
|
raise "Bettertabs: #{tab_type.inspect} tab type not supported. Use one of #{TAB_TYPES.inspect} instead." unless TAB_TYPES.include?(tab_type)
|
49
|
+
ajax_url = options.delete(:ajax_url) || url_for_ajax(url) if tab_type == TAB_TYPE_AJAX
|
48
50
|
@selected_tab_id ||= tab_id # defaults to first tab
|
49
51
|
|
50
52
|
if @render_only_active_content
|
@@ -54,7 +56,7 @@ class BettertabsBuilder
|
|
54
56
|
else
|
55
57
|
# Tabs
|
56
58
|
tab_html_options = options # any other option will be used as tab html_option
|
57
|
-
@tabs << { tab_id: tab_id, text: tab_text, url: url, html_options: tab_html_options, tab_type: tab_type, active: active?(tab_id) }
|
59
|
+
@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) }
|
58
60
|
|
59
61
|
# Content
|
60
62
|
content_html_options = { id: content_html_id_for(tab_id), class: "content #{active?(tab_id) ? 'active' : 'hidden'}" }
|
@@ -65,7 +67,7 @@ class BettertabsBuilder
|
|
65
67
|
end
|
66
68
|
@contents << { tab_id: tab_id, tab_text: tab_text, content: content, html_options: content_html_options, tab_type: tab_type, active: active?(tab_id) }
|
67
69
|
end
|
68
|
-
nil
|
70
|
+
nil # returning nil allows the user to call this using <%= tab.for :xxx %> or <% tab.for :xxx %>
|
69
71
|
end
|
70
72
|
|
71
73
|
# Renders the bettertabs markup.
|
@@ -103,6 +105,7 @@ class BettertabsBuilder
|
|
103
105
|
tag(:li, class: ('active' if tab[:active]), id: tab_html_id_for(tab[:tab_id])) do
|
104
106
|
tab[:html_options][:"data-tab-type"] ||= tab[:tab_type] # for javascript: change click behavior depending on type :static, :link or :ajax
|
105
107
|
tab[:html_options][:"data-show-content-id"] ||= content_html_id_for(tab[:tab_id]) # for javascript: element id to show when select this tab
|
108
|
+
tab[:html_options][:"data-ajax-url"] ||= tab[:ajax_url] if tab[:tab_type] == TAB_TYPE_AJAX # for javascript: url to make ajax call
|
106
109
|
@template.link_to(tab[:text], tab[:url], tab[:html_options])
|
107
110
|
end
|
108
111
|
end.join.html_safe
|
@@ -123,16 +126,6 @@ class BettertabsBuilder
|
|
123
126
|
|
124
127
|
private
|
125
128
|
|
126
|
-
# Alias of @template.content_tag
|
127
|
-
def tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block)
|
128
|
-
@template.content_tag(name, content_or_options_with_block, options, escape, &block)
|
129
|
-
end
|
130
|
-
|
131
|
-
# Wraps javascript code inside a javascript_tag using the jQuery(function($){ ... }); on init call.
|
132
|
-
def jquery_tag(jquery_code)
|
133
|
-
@template.javascript_tag("jQuery(function($){ #{ jquery_code } });")
|
134
|
-
end
|
135
|
-
|
136
129
|
# Get the options hash from an array of args. If options are not present, create them and initialize to {}
|
137
130
|
def get_options(args)
|
138
131
|
args << {} unless args.last.is_a?(Hash)
|
@@ -159,4 +152,31 @@ class BettertabsBuilder
|
|
159
152
|
"#{tab_id}_#{@bettertabs_id}_content"
|
160
153
|
end
|
161
154
|
|
155
|
+
# Alias of @template.content_tag
|
156
|
+
def tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block)
|
157
|
+
@template.content_tag(name, content_or_options_with_block, options, escape, &block)
|
158
|
+
end
|
159
|
+
|
160
|
+
# Wraps javascript code inside a javascript_tag using the jQuery(function($){ ... }); on init call.
|
161
|
+
def jquery_tag(jquery_code)
|
162
|
+
@template.javascript_tag("jQuery(function($){ #{ jquery_code } });")
|
163
|
+
end
|
164
|
+
|
165
|
+
# Uses @template.url_for() to create the string url, and then URI.parse to add the ajax=true extra param.
|
166
|
+
# This "ajax=true" extra param is important for two reasons:
|
167
|
+
# * It makes easier from the controller to know when a request is ajax or not.
|
168
|
+
# * It prevents the browser cache to be populated with the ajax response in the same URL as the complete page,
|
169
|
+
# otherwhise when the user makes an ajax call, goes to another page and click the back button they see only the ajax response (browsers bug?).
|
170
|
+
def url_for_ajax(options)
|
171
|
+
original_url = @template.url_for(options)
|
172
|
+
begin
|
173
|
+
ajax_param = 'ajax=true'
|
174
|
+
uri = URI.parse original_url # URI from ruby standard library
|
175
|
+
uri.query = uri.query.blank? ? ajax_param : "#{uri.query}&#{ajax_param}".html_safe
|
176
|
+
uri.to_s
|
177
|
+
rescue URI::InvalidURIError
|
178
|
+
original_url
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
162
182
|
end
|
@@ -1,11 +1,55 @@
|
|
1
1
|
module BettertabsHelper
|
2
2
|
|
3
|
-
#
|
4
|
-
#
|
3
|
+
# bettertabs(bettertabs_id, options={})
|
4
|
+
# Bettertabs helper that generates tabs and content markup.
|
5
|
+
#
|
6
|
+
# === Example
|
7
|
+
# = bettertabs :bettertabs_id do |tab|
|
8
|
+
# - tab.link :tab1_id, 'Tab1', options1
|
9
|
+
# - tab.static :tab2_id, 'Tab2', options2
|
10
|
+
# - tab.ajax :tab3_id, 'Tab3', options3
|
11
|
+
#
|
12
|
+
# === bettertabs params
|
13
|
+
# * bettertabs_id: will be used as html id of the wrapper element, and as part of the inner ids.
|
14
|
+
# Note: is usually better to use a Symbol (with underscores) here to avoid problems defining routes.
|
15
|
+
# * options:
|
16
|
+
# * :selected_tab => tab_id of the default selected tab.
|
17
|
+
# This is overriden by the appropiate param params[:"#{bettertabs_id}_selected_tab"],
|
18
|
+
# so any tab can be selected using the URL parmas.
|
19
|
+
# :selected_tab only defines which tab is selected when no {bettertabs_id}_selected_tab param is present.
|
20
|
+
# * :render_only_active_content => if true, this helper renders only the selected tab contents (no wrapper, no tabs, only content).
|
21
|
+
# Default to true only if controller.request.xhr? or params[:ajax].present? (true when its an ajax request).
|
22
|
+
# * :class => html class attribute of the wrapper element. By default is 'bettertabs'
|
23
|
+
# * :id => html id attribute of the wrapper element. By default is the bettertabs_id
|
24
|
+
# * Any other option will be used as wrapper elmenet html attribute.
|
25
|
+
#
|
26
|
+
# ==== tab builder params
|
27
|
+
# Tab builder descriptor:
|
28
|
+
# tab.link(tab_id, options={}, &block)
|
29
|
+
# tab.link(tab_id, tab_text, options={}, &block)
|
30
|
+
#
|
31
|
+
# Params:
|
32
|
+
# * tab_id: the tab item html id will be "#{tab_id}_#{bettertabs_id}_tab",
|
33
|
+
# and the content wrapper id will be "#{tab_id}_#{bettertabs_id}_content".
|
34
|
+
# Also the tab_id is used to identify this tab in the bettertabs :selected_tab option.
|
35
|
+
# * tab_text: is the content of the tab link. Defaults to tab_id.to_s.titleize
|
36
|
+
# * options:
|
37
|
+
# * :partial => Partial to render as content. Defaults to *tab_id*, but if &block given it captures the block instead of render partial.
|
38
|
+
# If you need to suply locals to the partial, use a block with a render(:partial => partial, :locals => {locals}) call.
|
39
|
+
# * :url => href of the tab link. For link tabs, this is the href to go when click.
|
40
|
+
# For ajax and static tabs, this is the url to replace in the browser when click (HTML5 history.replaceState()), and also the url
|
41
|
+
# to use if JavaSciprt is disabled.
|
42
|
+
# Defaults to { :"#{bettertabs_id}_selected_tab" => tab_id }, that is the current URL plus the selected tab param.
|
43
|
+
# * :ajax_url => used as data-ajax-url html5 attribute in the link tab, that will be used in the jquery.bettertabs plugin as ajax href where to
|
44
|
+
# make the ajax request to get the tab content.
|
45
|
+
# By default is the same as the provided :url option, plus the { :ajax => true } param.
|
46
|
+
# Note: This extra param makes the :url and :ajax_url different for the browser and prevents a cache mistake,
|
47
|
+
# otherwise the browser may fetch the url cache with the ajax response, producing a bug when visiting again the same page.
|
48
|
+
#
|
5
49
|
def bettertabs(bettertabs_id, options={})
|
6
50
|
bettertabs_id = bettertabs_id.to_s
|
7
51
|
selected_tab_id = params[:"#{bettertabs_id}_selected_tab"] || options.delete(:selected_tab)
|
8
|
-
options[:class]
|
52
|
+
options[:class] ||= "bettertabs"
|
9
53
|
options[:id] ||= bettertabs_id
|
10
54
|
options[:render_only_active_content] = true if controller.request.xhr?
|
11
55
|
builder = BettertabsBuilder.new(bettertabs_id, self, selected_tab_id, options)
|
@@ -21,6 +21,7 @@ $ = jQuery
|
|
21
21
|
|
22
22
|
tab_type_attr = 'data-tab-type' # attribute on tab links that indicate the tab type
|
23
23
|
show_content_id_attr = 'data-show-content-id' # attribute on tab links that indicate the related content id
|
24
|
+
ajax_url_attr = 'data-ajax-url' # attribute on ajax tab liks with the ajax href
|
24
25
|
tab_type_of = ($tab_link) -> $tab_link.attr(tab_type_attr)
|
25
26
|
content_id_from = ($tab_link) -> $tab_link.attr(show_content_id_attr)
|
26
27
|
|
@@ -50,8 +51,9 @@ $.fn.bettertabs = ->
|
|
50
51
|
previous_active_tab = tabs.filter '.active'
|
51
52
|
previous_active_tab_content = tabs_contents.filter '.active'
|
52
53
|
activate_tab_and_content = ->
|
53
|
-
|
54
|
-
|
54
|
+
tabs.removeClass('active')
|
55
|
+
tabs_contents.removeClass('active').addClass('hidden')
|
56
|
+
this_tab.addClass('active')
|
55
57
|
this_tab_content.removeClass('hidden').addClass('active')
|
56
58
|
previous_active_tab_content.trigger 'bettertabs-after-deactivate'
|
57
59
|
this_tab_content.trigger 'bettertabs-after-activate'
|
@@ -63,7 +65,7 @@ $.fn.bettertabs = ->
|
|
63
65
|
if tab_type_of(this_link) is 'ajax' and not this_link.data('content-loaded-already')?
|
64
66
|
this_link.addClass('ajax-loading')
|
65
67
|
this_tab_content.trigger 'bettertabs-before-ajax-loading'
|
66
|
-
this_tab_content.load this_link.attr(
|
68
|
+
this_tab_content.load this_link.attr(ajax_url_attr), ->
|
67
69
|
this_link.removeClass('ajax-loading')
|
68
70
|
this_link.data('content-loaded-already', yes)
|
69
71
|
this_tab_content.trigger 'bettertabs-after-ajax-loading'
|
@@ -16,10 +16,11 @@
|
|
16
16
|
'bettertabs-after-activate': fired on content that was activated
|
17
17
|
'bettertabs-after-ajax-loading': fired on content after it was loaded via ajax
|
18
18
|
|
19
|
-
*/ var $, change_url, content_id_from, show_content_id_attr, tab_type_attr, tab_type_of;
|
19
|
+
*/ var $, ajax_url_attr, change_url, content_id_from, show_content_id_attr, tab_type_attr, tab_type_of;
|
20
20
|
$ = jQuery;
|
21
21
|
tab_type_attr = 'data-tab-type';
|
22
22
|
show_content_id_attr = 'data-show-content-id';
|
23
|
+
ajax_url_attr = 'data-ajax-url';
|
23
24
|
tab_type_of = function($tab_link) {
|
24
25
|
return $tab_link.attr(tab_type_attr);
|
25
26
|
};
|
@@ -52,8 +53,9 @@
|
|
52
53
|
previous_active_tab = tabs.filter('.active');
|
53
54
|
previous_active_tab_content = tabs_contents.filter('.active');
|
54
55
|
activate_tab_and_content = function() {
|
55
|
-
|
56
|
-
|
56
|
+
tabs.removeClass('active');
|
57
|
+
tabs_contents.removeClass('active').addClass('hidden');
|
58
|
+
this_tab.addClass('active');
|
57
59
|
this_tab_content.removeClass('hidden').addClass('active');
|
58
60
|
previous_active_tab_content.trigger('bettertabs-after-deactivate');
|
59
61
|
this_tab_content.trigger('bettertabs-after-activate');
|
@@ -64,7 +66,7 @@
|
|
64
66
|
if (tab_type_of(this_link) === 'ajax' && !(this_link.data('content-loaded-already') != null)) {
|
65
67
|
this_link.addClass('ajax-loading');
|
66
68
|
this_tab_content.trigger('bettertabs-before-ajax-loading');
|
67
|
-
return this_tab_content.load(this_link.attr(
|
69
|
+
return this_tab_content.load(this_link.attr(ajax_url_attr), function() {
|
68
70
|
this_link.removeClass('ajax-loading');
|
69
71
|
this_link.data('content-loaded-already', true);
|
70
72
|
this_tab_content.trigger('bettertabs-after-ajax-loading');
|
@@ -0,0 +1,80 @@
|
|
1
|
+
Bettertabs CSS guidelines
|
2
|
+
=========================
|
3
|
+
|
4
|
+
Bettertabs provides a rails helper and a jQuery plugin. Styles are so different between projects and can not be abstracted into a common purpose CSS stylesheet.
|
5
|
+
|
6
|
+
The best way to style up this is watching at the generated markup and style it according to your application styles.
|
7
|
+
|
8
|
+
The following bettertabs declaration (haml):
|
9
|
+
|
10
|
+
= bettertabs :profile_tabs do |tab|
|
11
|
+
= tab.static :general do
|
12
|
+
General info of this profile
|
13
|
+
|
14
|
+
= tab.ajax :friends, "Dudes" do
|
15
|
+
Friends (loaded using AJAX)
|
16
|
+
|
17
|
+
will expand in the following markup (html):
|
18
|
+
|
19
|
+
<div id="profile_tabs" data-initial-active-tab-id="profile_tabs_general_tab" class="bettertabs">
|
20
|
+
<ul class="tabs">
|
21
|
+
<li id="profile_tabs_general_tab" class="active">
|
22
|
+
<a data-tab-type="static" data-show-content-id="profile_tabs" href="/profile/dude/general">General</a>
|
23
|
+
</li>
|
24
|
+
<li id="profile_tabs_friends_tab">
|
25
|
+
<a data-tab-type="ajax" data-show-content-id="profile_tabs" href="/competition/ladder/1234/rules">RULES</a>
|
26
|
+
</li>
|
27
|
+
</ul>
|
28
|
+
|
29
|
+
<div id="profile_tabs_general_content" class="content active">
|
30
|
+
General info of this profile
|
31
|
+
</div>
|
32
|
+
|
33
|
+
<div id="profile_tabs_friends_content" class="content hidden">
|
34
|
+
</div>
|
35
|
+
</div>
|
36
|
+
|
37
|
+
So you can use this structure to access any bettertabs widget element (CSS):
|
38
|
+
|
39
|
+
div.bettertabs { /* Wrapper DIV (Note: this is the default class, but it can be modified in the helper html_options) */ }
|
40
|
+
|
41
|
+
div.bettertabs ul.tabs { /* tabs list */ }
|
42
|
+
div.bettertabs ul.tabs li { /* tab item */ }
|
43
|
+
div.bettertabs ul.tabs li.active { /* selected tab item */ }
|
44
|
+
div.bettertabs ul.tabs li.active a { /* selected tab link */ }
|
45
|
+
div.bettertabs ul.tabs li a:link,
|
46
|
+
div.bettertabs ul.tabs li a:visited { /* tab link normal state */ }
|
47
|
+
div.bettertabs ul.tabs li a:hover { }
|
48
|
+
div.bettertabs ul.tabs li a:active { }
|
49
|
+
div.bettertabs ul.tabs li a.ajax-loading { /* tab link while ajax loading */ }
|
50
|
+
|
51
|
+
div.bettertabs div.content { }
|
52
|
+
div.bettertabs div.content.hidden { /* hidden content. Here you can use the property display: none; */ }
|
53
|
+
div.bettertabs div.content.active { /* active content */ }
|
54
|
+
|
55
|
+
Here you are a simple example of CSS you can use to style up your bettertabs widgets (CSS):
|
56
|
+
|
57
|
+
div.bettertabs { margin: 1em; width: 500px; }
|
58
|
+
|
59
|
+
div.bettertabs ul.tabs { margin: 0; padding: 0; position: relative; }
|
60
|
+
div.bettertabs ul.tabs li {
|
61
|
+
background-color: #ccc;
|
62
|
+
border: 1px solid #999;
|
63
|
+
display: inline; float: left; height: 24px; line-height: 24px;
|
64
|
+
list-style: none outside none;
|
65
|
+
margin-right: .5em; padding-right: .5em; padding-left: .5em;
|
66
|
+
position: relative; top: 1px;
|
67
|
+
}
|
68
|
+
div.bettertabs ul.tabs li.active { height: 25px; background-color: #eee; border-bottom: none; }
|
69
|
+
div.bettertabs ul.tabs li.active a { color: black; }
|
70
|
+
|
71
|
+
div.bettertabs ul.tabs li a { font-size: 80%; text-decoration: none; float: left; }
|
72
|
+
div.bettertabs ul.tabs li a:link,
|
73
|
+
div.bettertabs ul.tabs li a:visited { color: #444; }
|
74
|
+
div.bettertabs ul.tabs li a:hover { color: #000; }
|
75
|
+
div.bettertabs ul.tabs li a:active { color: #933; }
|
76
|
+
div.bettertabs ul.tabs li a.ajax-loading { color: #666; }
|
77
|
+
|
78
|
+
div.bettertabs div.content { padding: 1em; border: 1px solid #999; background-color: #eee; clear: left; }
|
79
|
+
div.bettertabs div.content.hidden { display: none; }
|
80
|
+
|
data/lib/bettertabs/version.rb
CHANGED
@@ -30,17 +30,17 @@ GEM
|
|
30
30
|
activesupport (3.0.6)
|
31
31
|
archive-tar-minitar (0.5.2)
|
32
32
|
arel (2.0.9)
|
33
|
-
bettertabs (
|
33
|
+
bettertabs (1.1)
|
34
34
|
builder (2.1.2)
|
35
35
|
columnize (0.3.2)
|
36
36
|
diff-lcs (1.1.2)
|
37
37
|
erubis (2.6.6)
|
38
38
|
abstract (>= 1.0.0)
|
39
|
-
haml (3.
|
39
|
+
haml (3.1.1)
|
40
40
|
i18n (0.5.0)
|
41
41
|
linecache19 (0.5.12)
|
42
42
|
ruby_core_source (>= 0.1.4)
|
43
|
-
mail (2.2.
|
43
|
+
mail (2.2.19)
|
44
44
|
activesupport (>= 2.3.6)
|
45
45
|
i18n (>= 0.4.0)
|
46
46
|
mime-types (~> 1.16)
|
@@ -92,7 +92,7 @@ GEM
|
|
92
92
|
thor (0.14.6)
|
93
93
|
treetop (1.4.9)
|
94
94
|
polyglot (>= 0.3.1)
|
95
|
-
tzinfo (0.3.
|
95
|
+
tzinfo (0.3.27)
|
96
96
|
|
97
97
|
PLATFORMS
|
98
98
|
ruby
|
@@ -1,4 +1,4 @@
|
|
1
|
-
= bettertabs :link, class: '
|
1
|
+
= bettertabs :link, class: 'bettertabs link_tabs', selected_tab: selected_tab do |tab|
|
2
2
|
= tab.link :tab1, 'Tab One', url: { action: 'link_tab_1' } do
|
3
3
|
Hello World!
|
4
4
|
= tab.link :tab2, 'Tab Two', partial: 'tab_content', url: { action: 'link_tab_2' }
|
@@ -3,7 +3,7 @@
|
|
3
3
|
<head>
|
4
4
|
<title>Rails30</title>
|
5
5
|
<%= stylesheet_link_tag 'layout', 'bettertabs' %>
|
6
|
-
<%= javascript_include_tag 'jquery-1.5.2.min', 'rails', 'jquery.bettertabs
|
6
|
+
<%= javascript_include_tag 'jquery-1.5.2.min', 'rails', 'jquery.bettertabs' %>
|
7
7
|
<%= csrf_meta_tag %>
|
8
8
|
</head>
|
9
9
|
<body>
|
@@ -0,0 +1,83 @@
|
|
1
|
+
(function() {
|
2
|
+
/*
|
3
|
+
Bettertabs jQuery plugin v1.0
|
4
|
+
|
5
|
+
jQuery(selector).bettertabs(); adds javascript to change content when click on tabs.
|
6
|
+
|
7
|
+
Markup needed, the same that is generated by the rails bettertabs helper, added by the bettertabs plugin
|
8
|
+
https://github.com/agoragames/bettertabs
|
9
|
+
|
10
|
+
Events: Each time a tab is selected, some events are fired, so you can easily activate
|
11
|
+
behavior from another jquery script (using .bind); The available events are:
|
12
|
+
'bettertabs-before-deactivate': fired on content that is active and will be deactivated
|
13
|
+
'bettertabs-before-activate': fired on content that will be activated
|
14
|
+
'bettertabs-before-ajax-loading': fired on content that will be activated and needs ajax loading
|
15
|
+
'bettertabs-after-deactivate': fired on content that was deactivated
|
16
|
+
'bettertabs-after-activate': fired on content that was activated
|
17
|
+
'bettertabs-after-ajax-loading': fired on content after it was loaded via ajax
|
18
|
+
|
19
|
+
*/ var $, ajax_url_attr, change_url, content_id_from, show_content_id_attr, tab_type_attr, tab_type_of;
|
20
|
+
$ = jQuery;
|
21
|
+
tab_type_attr = 'data-tab-type';
|
22
|
+
show_content_id_attr = 'data-show-content-id';
|
23
|
+
ajax_url_attr = 'data-ajax-url';
|
24
|
+
tab_type_of = function($tab_link) {
|
25
|
+
return $tab_link.attr(tab_type_attr);
|
26
|
+
};
|
27
|
+
content_id_from = function($tab_link) {
|
28
|
+
return $tab_link.attr(show_content_id_attr);
|
29
|
+
};
|
30
|
+
change_url = function($link) {
|
31
|
+
var url;
|
32
|
+
if ((typeof history != "undefined" && history !== null) && (history.replaceState != null)) {
|
33
|
+
url = $link.attr('href');
|
34
|
+
return history.replaceState(null, document.title, url);
|
35
|
+
}
|
36
|
+
};
|
37
|
+
$.fn.bettertabs = function() {
|
38
|
+
return this.each(function() {
|
39
|
+
var mytabs, tabs, tabs_and_contents, tabs_contents, tabs_links;
|
40
|
+
mytabs = $(this);
|
41
|
+
tabs = mytabs.find('ul.tabs > li');
|
42
|
+
tabs_links = mytabs.find('ul.tabs > li > a');
|
43
|
+
tabs_contents = mytabs.children('.content');
|
44
|
+
tabs_and_contents = tabs.add(tabs_contents);
|
45
|
+
return tabs_links.click(function(event) {
|
46
|
+
var activate_tab_and_content, previous_active_tab, previous_active_tab_content, this_link, this_tab, this_tab_content;
|
47
|
+
this_link = $(this);
|
48
|
+
if (tab_type_of(this_link) !== 'link') {
|
49
|
+
event.preventDefault();
|
50
|
+
this_tab = this_link.parent();
|
51
|
+
if (!this_tab.is('.active') && !this_link.is('.ajax-loading')) {
|
52
|
+
this_tab_content = tabs_contents.filter("#" + (content_id_from(this_link)));
|
53
|
+
previous_active_tab = tabs.filter('.active');
|
54
|
+
previous_active_tab_content = tabs_contents.filter('.active');
|
55
|
+
activate_tab_and_content = function() {
|
56
|
+
tabs.removeClass('active');
|
57
|
+
tabs_contents.removeClass('active').addClass('hidden');
|
58
|
+
this_tab.addClass('active');
|
59
|
+
this_tab_content.removeClass('hidden').addClass('active');
|
60
|
+
previous_active_tab_content.trigger('bettertabs-after-deactivate');
|
61
|
+
this_tab_content.trigger('bettertabs-after-activate');
|
62
|
+
return change_url(this_link);
|
63
|
+
};
|
64
|
+
previous_active_tab_content.trigger('bettertabs-before-deactivate');
|
65
|
+
this_tab_content.trigger('bettertabs-before-activate');
|
66
|
+
if (tab_type_of(this_link) === 'ajax' && !(this_link.data('content-loaded-already') != null)) {
|
67
|
+
this_link.addClass('ajax-loading');
|
68
|
+
this_tab_content.trigger('bettertabs-before-ajax-loading');
|
69
|
+
return this_tab_content.load(this_link.attr(ajax_url_attr), function() {
|
70
|
+
this_link.removeClass('ajax-loading');
|
71
|
+
this_link.data('content-loaded-already', true);
|
72
|
+
this_tab_content.trigger('bettertabs-after-ajax-loading');
|
73
|
+
return activate_tab_and_content();
|
74
|
+
});
|
75
|
+
} else {
|
76
|
+
return activate_tab_and_content();
|
77
|
+
}
|
78
|
+
}
|
79
|
+
}
|
80
|
+
});
|
81
|
+
});
|
82
|
+
};
|
83
|
+
}).call(this);
|