bettertabs 1.0 → 1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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{The bettertabs helper 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. }
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
- # Bettertabs helper
4
- # Defines the bettertabs markup in the view.
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] = "bettertabs #{options[:class]}" # keep 'bettertabs' class even when the user adds more classes.
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
- tabs_and_contents.removeClass('active').addClass('hidden')
54
- this_tab.removeClass('hidden').addClass('active')
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('href'), ->
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
- tabs_and_contents.removeClass('active').addClass('hidden');
56
- this_tab.removeClass('hidden').addClass('active');
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('href'), function() {
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
+
@@ -1,3 +1,3 @@
1
1
  module Bettertabs
2
- VERSION = "1.0"
2
+ VERSION = "1.1"
3
3
  end
@@ -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 (0.0.1)
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.0.25)
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.15)
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.26)
95
+ tzinfo (0.3.27)
96
96
 
97
97
  PLATFORMS
98
98
  ruby
@@ -1,6 +1,6 @@
1
1
  = bettertabs :ajax do |tab|
2
2
  = tab.ajax :ajax_tab_1 do
3
- Content for the link tab
3
+ Content for the ajax_tab_1
4
4
  = tab.ajax :ajax_tab_2 do
5
- Content for the static tab
5
+ Content for the ajax_tab_2
6
6
  = tab.ajax :ajax_tab_3, partial: 'tab_content'
@@ -1,4 +1,4 @@
1
- = bettertabs :link, class: 'link_class', selected_tab: selected_tab do |tab|
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.min' %>
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);