Skip to content
This repository was archived by the owner on Oct 28, 2020. It is now read-only.

Commit 0f77168

Browse files
author
Stephen Hoogendijk
committed
Merge pull request #3 from thecodeassassin/master
Upgraded to latest version
2 parents a27d615 + 0bcfd50 commit 0f77168

File tree

4 files changed

+168
-62
lines changed

4 files changed

+168
-62
lines changed

README.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Bootstrap tabs remote data plugin
1+
Bootstrap remote data plugin
22
=====================
33
Author: Stephen Hoogendijk - TheCodeAssassin
44

@@ -8,9 +8,9 @@ This plugin uses the jQuery loadmask plugin by Sergiy Kovalchuk.
88

99
================================================
1010

11-
Simple boostrap plugin to allow tabs to fetch their data from a remote source
11+
Simple boostrap plugin to allow tabs and accordions to fetch their data from a remote source
1212

13-
*The script is only 1.7k compressed!*
13+
*The script is only 2.5k compressed!*
1414

1515
Requirements
1616
============
@@ -43,14 +43,20 @@ You can use the following properties to enable remote data tabs:
4343

4444
Check the demo for details on how to use this plugin.
4545

46+
*Note: The properties are still named data-tab due to backwards compatibility*
47+
4648
Note
4749
====
48-
This plugin hooks into the bootstrap tabs 'show' event. In order to use a custom event callback, you can provide data-tab-callback
50+
This plugin hooks into the bootstrap tab/accordion 'show' event. In order to use a custom event callback, you can provide data-tab-callback
4951
to let the plugin execute your custom callback. If you want a callback to be fired after the show event, use the native
5052
shown event.
5153

5254
Changelog
5355
===
56+
Version 1.1.1
57+
------
58+
Added support for accordions
59+
5460

5561
Version 1.1.0
5662
------

demo/index.html

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
<style type="text/css">
1111
div.tab-pane {
12-
min-height: 300px;
12+
min-height: 200px;
1313
}
1414
</style>
1515

@@ -23,7 +23,9 @@
2323
</head>
2424
<body>
2525
<h1>Bootstrap tabs remote data plugin demo</h1>
26+
<hr>
2627

28+
<h2>Tabs demo</h2>
2729
<!-- Nav tabs -->
2830
<ul class="nav nav-tabs">
2931
<li class="active"><a href="#home" data-toggle="tab">No remote data</a></li>
@@ -45,6 +47,47 @@ <h1>Bootstrap tabs remote data plugin demo</h1>
4547
<div class="tab-pane" id="jsondata"></div>
4648
</div>
4749

50+
<h2>Accordion demo</h2>
51+
52+
<div class="panel-group" id="accordion">
53+
<div class="panel panel-default">
54+
<div class="panel-heading">
55+
<h4 class="panel-title">
56+
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne" data-tab-url="remote/normal.html">Simple remote data</a>
57+
</h4>
58+
</div>
59+
<div id="collapseOne" class="panel-collapse collapse in">
60+
<div class="panel-body">&nbsp;</div>
61+
</div>
62+
</div>
63+
<div class="panel panel-default">
64+
<div class="panel-heading">
65+
<h4 class="panel-title">
66+
<a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" data-tab-url="remote/delay.html" data-tab-delay="3000">
67+
Simple remote data (with 3 second delay)
68+
</a>
69+
</h4>
70+
</div>
71+
<div id="collapseTwo" class="panel-collapse collapse">
72+
<div class="panel-body">&nbsp;
73+
</div>
74+
</div>
75+
</div>
76+
<div class="panel panel-default">
77+
<div class="panel-heading">
78+
<h4 class="panel-title">
79+
<a data-toggle="collapse" data-parent="#accordion" href="#collapseThree" data-toggle="tab" data-tab-url="remote/callback.html" data-tab-callback="sampleCallback">
80+
Remote data with callback
81+
</a>
82+
</h4>
83+
</div>
84+
<div id="collapseThree" class="panel-collapse collapse">
85+
<div class="panel-body">&nbsp;
86+
</div>
87+
</div>
88+
</div>
89+
</div>
90+
4891
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
4992
<script src="http://codeorigin.jquery.com/jquery-2.0.3.min.js"></script>
5093
<!-- Include all compiled plugins (below), or include individual files as needed -->

js/bootstrap-remote-tabs.js

Lines changed: 112 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ var $ = jQuery;
22
/*!
33
*
44
* Bootstrap remote data tabs plugin
5-
* Version 1.0.1
5+
* Version 1.1.1
66
*
77
* Author: Stephen Hoogendijk (TheCodeAssassin)
88
*
@@ -15,12 +15,25 @@ var hasLoadingMask = (jQuery().mask ? true : false),
1515
bootstrapVersion2 = (jQuery().typeahead ? true : false);
1616

1717
// hook the event based on the version of bootstrap
18-
var showEvent = (bootstrapVersion2 ? 'show' : 'show.bs.tab');
18+
var tabShowEvent = (bootstrapVersion2 ? 'show' : 'show.bs.tab');
19+
var accordionShowEvent = (bootstrapVersion2 ? 'show' : 'show.bs.collapse');
1920

2021
$(function() {
22+
// try to navigate to the tab/accordion last given in the URL
2123
var hash = document.location.hash;
2224
if (hash) {
23-
$('.nav-tabs a[href*='+hash+']').tab(showEvent);
25+
var hasTab = $('[data-toggle=tab][href='+hash+']');
26+
if (hasTab) {
27+
hasTab.tab('show');
28+
}
29+
30+
var hasAccordion = $('[data-toggle=collapse][href='+hash+']');
31+
if (hasAccordion) {
32+
// for some reason we cannot execute the 'show' event for an accordion properly, so here's a workaround
33+
if (hasAccordion[0] != $('[data-toggle=collapse]:first')[0]) {
34+
hasAccordion.click();
35+
}
36+
}
2437
}
2538
});
2639
var RemoteTabs = function() {
@@ -33,85 +46,128 @@ var RemoteTabs = function() {
3346
* @param tabEvent
3447
* @param hasLoadingMask
3548
*/
36-
load: function(tabEvent, hasLoadingMask) {
49+
load: function(hasLoadingMask) {
3750

3851
var me = this;
3952

4053
me.hasLoadingMask = !!hasLoadingMask;
4154

4255
// enable all remote data tabs
43-
$('[data-toggle=tab]').each(function(k, tab) {
44-
var tabObj = $(tab),
45-
tabDiv,
46-
tabData,
47-
tabCallback,
56+
$('[data-toggle=tab], [data-toggle=collapse]').each(function(k, obj) {
57+
var bsObj = $(obj),
58+
bsDiv,
59+
bsData,
60+
bsCallback,
4861
url,
4962
simulateDelay,
50-
alwaysRefresh;
63+
alwaysRefresh,
64+
hasOpenPanel = false,
65+
originalObj;
5166

5267
// check if the tab has a data-url property
53-
if(tabObj.is('[data-tab-url]')) {
54-
url = tabObj.attr('data-tab-url');
55-
tabDiv = $( '#' + tabObj.attr('href').split('#')[1]);
56-
tabData = tabObj.attr('data-tab-json') || [];
57-
tabCallback = tabObj.attr('data-tab-callback') || null;
58-
simulateDelay = tabObj.attr('data-tab-delay') || null;
59-
alwaysRefresh = (tabObj.is('[data-tab-always-refresh]')
60-
&& tabObj.attr('data-tab-always-refresh') == 'true') || null;
61-
62-
if(tabData.length > 0) {
68+
if(bsObj.is('[data-tab-url]')) {
69+
url = bsObj.attr('data-tab-url');
70+
bsDiv = $( '#' + bsObj.attr('href').split('#')[1]);
71+
bsData = bsObj.attr('data-tab-json') || [];
72+
bsCallback = bsObj.attr('data-tab-callback') || null;
73+
simulateDelay = bsObj.attr('data-tab-delay') || null;
74+
alwaysRefresh = (bsObj.is('[data-tab-always-refresh]')
75+
&& bsObj.attr('data-tab-always-refresh') == 'true') || null,
76+
originalObj = bsObj,
77+
showEvent = (bsObj.attr('data-toggle') == 'tab' ? tabShowEvent : accordionShowEvent);
78+
79+
if(bsData.length > 0) {
6380
try
6481
{
65-
tabData = $.parseJSON(tabData);
82+
bsData = $.parseJSON(bsData);
6683
} catch (exc) {
6784
console.log('Invalid json passed to data-tab-json');
6885
console.log(exc);
6986
}
7087

7188
}
72-
73-
tabObj.on(tabEvent, function(e) {
74-
75-
// change the hash of the location
76-
window.location.hash = e.target.hash;
77-
78-
if ((!tabObj.hasClass("loaded") || alwaysRefresh) &&
79-
!tabObj.hasClass('loading')) {
80-
81-
if(me.hasLoadingMask) {
82-
tabDiv.mask('Loading...');
83-
}
84-
tabObj.addClass('loading');
85-
86-
// delay the json call if it has been given a value
87-
if(simulateDelay) {
88-
clearTimeout(window.timer);
89-
window.timer=setTimeout(function(){
90-
me._executeRemoteCall(url, tabData, tabCallback, tabObj, tabDiv);
91-
}, simulateDelay);
92-
} else {
93-
me._executeRemoteCall(url, tabData, tabCallback, tabObj, tabDiv);
94-
}
95-
96-
89+
90+
if (showEvent == accordionShowEvent) {
91+
hasOpenPanel = bsDiv.hasClass('in');
92+
// when an accordion is triggered, make the div the triggered object instead of the link
93+
if (bootstrapVersion2) {
94+
bsObj = bsObj.parent();
95+
} else {
96+
bsObj = bsObj.parents('.panel');
9797
}
98-
98+
99+
// If there is a panel already opened, make sure the data url is fetched
100+
if (hasOpenPanel) {
101+
me._triggerChange(null, url, bsData, bsCallback, bsObj, bsDiv, simulateDelay, alwaysRefresh, originalObj);
102+
}
103+
}
104+
105+
bsObj.on(showEvent, function(e) {
106+
me._triggerChange(e, url, bsData, bsCallback, bsObj, bsDiv, simulateDelay, alwaysRefresh, originalObj);
99107
});
100108

101109
}
102110
});
103111
},
104112

113+
/**
114+
* Trigger the change
115+
*
116+
* @param e
117+
* @param url
118+
* @param bsData
119+
* @param bsCallback
120+
* @param bsObj
121+
* @param bsDiv
122+
* @param simulateDelay
123+
* @param alwaysRefresh
124+
* @param originalObj
125+
*/
126+
_triggerChange: function(e, url, bsData, bsCallback, bsObj, bsDiv, simulateDelay, alwaysRefresh, originalObj) {
127+
var me = this;
128+
129+
// change the hash of the location
130+
if (e) {
131+
if (typeof e.target.hash != 'undefined') {
132+
window.location.hash = e.target.hash;
133+
} else {
134+
window.location.hash = originalObj.prop('hash');
135+
}
136+
}
137+
138+
if ((!bsObj.hasClass("loaded") || alwaysRefresh) &&
139+
!bsObj.hasClass('loading')) {
140+
141+
if(me.hasLoadingMask) {
142+
bsDiv.mask('Loading...');
143+
}
144+
bsObj.addClass('loading');
145+
146+
// delay the json call if it has been given a value
147+
if(simulateDelay) {
148+
clearTimeout(window.timer);
149+
window.timer=setTimeout(function(){
150+
me._executeRemoteCall(url, bsData, bsCallback, bsObj, bsDiv);
151+
}, simulateDelay);
152+
} else {
153+
me._executeRemoteCall(url, bsData, bsCallback, bsObj, bsDiv);
154+
}
155+
156+
157+
}
158+
},
159+
160+
105161
/**
106162
* Execute the remote call
107163
* @param url
108164
* @param customData
109165
* @param callbackFn
110166
* @param trigger
111-
* @param tabContainer
167+
* @param dataContainer
112168
* @private
113169
*/
114-
_executeRemoteCall: function(url, customData, callbackFn, trigger, tabContainer) {
170+
_executeRemoteCall: function(url, customData, callbackFn, trigger, dataContainer) {
115171
var me = this;
116172

117173

@@ -121,29 +177,30 @@ var RemoteTabs = function() {
121177
success: function(data) {
122178
trigger.removeClass('loading');
123179
if(me.hasLoadingMask) {
124-
tabContainer.unmask();
180+
dataContainer.unmask();
125181
}
126182
if (data) {
127183
if(typeof window[callbackFn] == 'function') {
128-
window[callbackFn].call(null, data, trigger, tabContainer, customData);
184+
window[callbackFn].call(null, data, trigger, dataContainer, customData);
129185
}
130186
if(!trigger.hasClass("loaded")) {
131187
trigger.addClass("loaded");
132188
}
133-
tabContainer.html(data);
189+
dataContainer.html(data);
134190
}
135191
},
136-
fail: function(data) {
192+
error: function(data, status, error) {
193+
dataContainer.html("An error occured while loading the data: " + error);
137194
trigger.removeClass('loading');
138195
if(me.hasLoadingMask) {
139-
tabContainer.unmask();
196+
dataContainer.unmask();
140197
}
141198
}
142199
});
143200
}
144201
};
145202

146-
obj.load(showEvent, hasLoadingMask);
203+
obj.load( hasLoadingMask);
147204

148205
return obj;
149206
};

js/bootstrap-remote-tabs.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)