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

Commit

Permalink
Merge pull request #3 from thecodeassassin/master
Browse files Browse the repository at this point in the history
Upgraded to latest version
  • Loading branch information
Stephen Hoogendijk committed Feb 3, 2014
2 parents a27d615 + 0bcfd50 commit 0f77168
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 62 deletions.
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Bootstrap tabs remote data plugin
Bootstrap remote data plugin
=====================
Author: Stephen Hoogendijk - TheCodeAssassin

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

================================================

Simple boostrap plugin to allow tabs to fetch their data from a remote source
Simple boostrap plugin to allow tabs and accordions to fetch their data from a remote source

*The script is only 1.7k compressed!*
*The script is only 2.5k compressed!*

Requirements
============
Expand Down Expand Up @@ -43,14 +43,20 @@ You can use the following properties to enable remote data tabs:

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

*Note: The properties are still named data-tab due to backwards compatibility*

Note
====
This plugin hooks into the bootstrap tabs 'show' event. In order to use a custom event callback, you can provide data-tab-callback
This plugin hooks into the bootstrap tab/accordion 'show' event. In order to use a custom event callback, you can provide data-tab-callback
to let the plugin execute your custom callback. If you want a callback to be fired after the show event, use the native
shown event.

Changelog
===
Version 1.1.1
------
Added support for accordions


Version 1.1.0
------
Expand Down
45 changes: 44 additions & 1 deletion demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

<style type="text/css">
div.tab-pane {
min-height: 300px;
min-height: 200px;
}
</style>

Expand All @@ -23,7 +23,9 @@
</head>
<body>
<h1>Bootstrap tabs remote data plugin demo</h1>
<hr>

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

<h2>Accordion demo</h2>

<div class="panel-group" id="accordion">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne" data-tab-url="remote/normal.html">Simple remote data</a>
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse in">
<div class="panel-body">&nbsp;</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" data-tab-url="remote/delay.html" data-tab-delay="3000">
Simple remote data (with 3 second delay)
</a>
</h4>
</div>
<div id="collapseTwo" class="panel-collapse collapse">
<div class="panel-body">&nbsp;
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseThree" data-toggle="tab" data-tab-url="remote/callback.html" data-tab-callback="sampleCallback">
Remote data with callback
</a>
</h4>
</div>
<div id="collapseThree" class="panel-collapse collapse">
<div class="panel-body">&nbsp;
</div>
</div>
</div>
</div>

<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="http://codeorigin.jquery.com/jquery-2.0.3.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
Expand Down
167 changes: 112 additions & 55 deletions js/bootstrap-remote-tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ var $ = jQuery;
/*!
*
* Bootstrap remote data tabs plugin
* Version 1.0.1
* Version 1.1.1
*
* Author: Stephen Hoogendijk (TheCodeAssassin)
*
Expand All @@ -15,12 +15,25 @@ var hasLoadingMask = (jQuery().mask ? true : false),
bootstrapVersion2 = (jQuery().typeahead ? true : false);

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

$(function() {
// try to navigate to the tab/accordion last given in the URL
var hash = document.location.hash;
if (hash) {
$('.nav-tabs a[href*='+hash+']').tab(showEvent);
var hasTab = $('[data-toggle=tab][href='+hash+']');
if (hasTab) {
hasTab.tab('show');
}

var hasAccordion = $('[data-toggle=collapse][href='+hash+']');
if (hasAccordion) {
// for some reason we cannot execute the 'show' event for an accordion properly, so here's a workaround
if (hasAccordion[0] != $('[data-toggle=collapse]:first')[0]) {
hasAccordion.click();
}
}
}
});
var RemoteTabs = function() {
Expand All @@ -33,85 +46,128 @@ var RemoteTabs = function() {
* @param tabEvent
* @param hasLoadingMask
*/
load: function(tabEvent, hasLoadingMask) {
load: function(hasLoadingMask) {

var me = this;

me.hasLoadingMask = !!hasLoadingMask;

// enable all remote data tabs
$('[data-toggle=tab]').each(function(k, tab) {
var tabObj = $(tab),
tabDiv,
tabData,
tabCallback,
$('[data-toggle=tab], [data-toggle=collapse]').each(function(k, obj) {
var bsObj = $(obj),
bsDiv,
bsData,
bsCallback,
url,
simulateDelay,
alwaysRefresh;
alwaysRefresh,
hasOpenPanel = false,
originalObj;

// check if the tab has a data-url property
if(tabObj.is('[data-tab-url]')) {
url = tabObj.attr('data-tab-url');
tabDiv = $( '#' + tabObj.attr('href').split('#')[1]);
tabData = tabObj.attr('data-tab-json') || [];
tabCallback = tabObj.attr('data-tab-callback') || null;
simulateDelay = tabObj.attr('data-tab-delay') || null;
alwaysRefresh = (tabObj.is('[data-tab-always-refresh]')
&& tabObj.attr('data-tab-always-refresh') == 'true') || null;

if(tabData.length > 0) {
if(bsObj.is('[data-tab-url]')) {
url = bsObj.attr('data-tab-url');
bsDiv = $( '#' + bsObj.attr('href').split('#')[1]);
bsData = bsObj.attr('data-tab-json') || [];
bsCallback = bsObj.attr('data-tab-callback') || null;
simulateDelay = bsObj.attr('data-tab-delay') || null;
alwaysRefresh = (bsObj.is('[data-tab-always-refresh]')
&& bsObj.attr('data-tab-always-refresh') == 'true') || null,
originalObj = bsObj,
showEvent = (bsObj.attr('data-toggle') == 'tab' ? tabShowEvent : accordionShowEvent);

if(bsData.length > 0) {
try
{
tabData = $.parseJSON(tabData);
bsData = $.parseJSON(bsData);
} catch (exc) {
console.log('Invalid json passed to data-tab-json');
console.log(exc);
}

}

tabObj.on(tabEvent, function(e) {

// change the hash of the location
window.location.hash = e.target.hash;

if ((!tabObj.hasClass("loaded") || alwaysRefresh) &&
!tabObj.hasClass('loading')) {

if(me.hasLoadingMask) {
tabDiv.mask('Loading...');
}
tabObj.addClass('loading');

// delay the json call if it has been given a value
if(simulateDelay) {
clearTimeout(window.timer);
window.timer=setTimeout(function(){
me._executeRemoteCall(url, tabData, tabCallback, tabObj, tabDiv);
}, simulateDelay);
} else {
me._executeRemoteCall(url, tabData, tabCallback, tabObj, tabDiv);
}



if (showEvent == accordionShowEvent) {
hasOpenPanel = bsDiv.hasClass('in');
// when an accordion is triggered, make the div the triggered object instead of the link
if (bootstrapVersion2) {
bsObj = bsObj.parent();
} else {
bsObj = bsObj.parents('.panel');
}


// If there is a panel already opened, make sure the data url is fetched
if (hasOpenPanel) {
me._triggerChange(null, url, bsData, bsCallback, bsObj, bsDiv, simulateDelay, alwaysRefresh, originalObj);
}
}

bsObj.on(showEvent, function(e) {
me._triggerChange(e, url, bsData, bsCallback, bsObj, bsDiv, simulateDelay, alwaysRefresh, originalObj);
});

}
});
},

/**
* Trigger the change
*
* @param e
* @param url
* @param bsData
* @param bsCallback
* @param bsObj
* @param bsDiv
* @param simulateDelay
* @param alwaysRefresh
* @param originalObj
*/
_triggerChange: function(e, url, bsData, bsCallback, bsObj, bsDiv, simulateDelay, alwaysRefresh, originalObj) {
var me = this;

// change the hash of the location
if (e) {
if (typeof e.target.hash != 'undefined') {
window.location.hash = e.target.hash;
} else {
window.location.hash = originalObj.prop('hash');
}
}

if ((!bsObj.hasClass("loaded") || alwaysRefresh) &&
!bsObj.hasClass('loading')) {

if(me.hasLoadingMask) {
bsDiv.mask('Loading...');
}
bsObj.addClass('loading');

// delay the json call if it has been given a value
if(simulateDelay) {
clearTimeout(window.timer);
window.timer=setTimeout(function(){
me._executeRemoteCall(url, bsData, bsCallback, bsObj, bsDiv);
}, simulateDelay);
} else {
me._executeRemoteCall(url, bsData, bsCallback, bsObj, bsDiv);
}


}
},


/**
* Execute the remote call
* @param url
* @param customData
* @param callbackFn
* @param trigger
* @param tabContainer
* @param dataContainer
* @private
*/
_executeRemoteCall: function(url, customData, callbackFn, trigger, tabContainer) {
_executeRemoteCall: function(url, customData, callbackFn, trigger, dataContainer) {
var me = this;


Expand All @@ -121,29 +177,30 @@ var RemoteTabs = function() {
success: function(data) {
trigger.removeClass('loading');
if(me.hasLoadingMask) {
tabContainer.unmask();
dataContainer.unmask();
}
if (data) {
if(typeof window[callbackFn] == 'function') {
window[callbackFn].call(null, data, trigger, tabContainer, customData);
window[callbackFn].call(null, data, trigger, dataContainer, customData);
}
if(!trigger.hasClass("loaded")) {
trigger.addClass("loaded");
}
tabContainer.html(data);
dataContainer.html(data);
}
},
fail: function(data) {
error: function(data, status, error) {
dataContainer.html("An error occured while loading the data: " + error);
trigger.removeClass('loading');
if(me.hasLoadingMask) {
tabContainer.unmask();
dataContainer.unmask();
}
}
});
}
};

obj.load(showEvent, hasLoadingMask);
obj.load( hasLoadingMask);

return obj;
};
Expand Down
4 changes: 2 additions & 2 deletions js/bootstrap-remote-tabs.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 0f77168

Please sign in to comment.