/**
* jQuery.ScrollableTab - Scrolling multiple tabs.
* @copyright (c) 2010 Astun Technology Ltd - http://www.astuntechnology.com
* Dual licensed under MIT and GPL.
* Date: 28/04/2010
* @author Aamir Afridi - aamirafridi(at)gmail(dot)com | http://www.aamirafridi.com
* @version 1.01
*/
;(function($){
//Global plugin settings
var settings = {
'animationSpeed' : 100, //The speed in which the tabs will animate/scroll
'closable' : false, //Make tabs closable
'resizable' : false, //Alow resizing the tabs container
'resizeHandles' : 'e,s,se', //Resizable in North, East and NorthEast directions
'loadLastTab':false, //When tabs loaded, scroll to the last tab - default is the first tab
'easing':'swing' //The easing equation
}
$.fn.scrollabletab = function(options){
//Check if scrollto plugin is available - (pasted the plugin at the end of this plugin)
//if(!$.fn.scrollTo) return alert('Error:\nScrollTo plugin not available.');
return this.each(function(){
var o = $.extend({}, settings, options), //Extend the options if any provided
$tabs = $(this),
$tabsNav = $tabs.find('.ui-tabs-nav'),
$nav;//will save the refrence for the wrapper having next and previous buttons
//Adjust the css class
//$tabsNav.removeClass('ui-corner-all').addClass('ui-corner-top');
$tabs.css({'padding':2, 'position':'relative'});
//$tabsNav.css('position','inherit');
//Wrap inner items
$tabs.wrap('
').find('.ui-tabs-nav').css('overflow','hidden').wrapInner('
');
var $widthChecker = $tabs.find('.stWidthChecker'),
$itemContainer = $tabs.find('.stTabsInnerWrapper'),
$tabsWrapper = $tabs.parents('#stTabswrapper').width($tabs.outerWidth(true));
//Fixing safari bug
if($.browser.safari)
{
$tabsWrapper.width($tabs.width()+6);
}
//alert($tabsWrapper.width());
if(o.resizable)
{
if(!!$.fn.resizable)
{
$tabsWrapper.resizable({
minWidth : $tabsWrapper.width(),
maxWidth : $tabsWrapper.width()*2,
minHeight : $tabsWrapper.height(),
maxHeight : $tabsWrapper.height()*2,
handles : o.resizeHandles,
alsoResize: $tabs,
//start : function(){ },
resize: function(){
$tabs.trigger('resized');
}
//stop: function(){ $tabs.trigger('scrollToTab',$tabsNav.find('li.ui-tabs-selected')); }
});
}
else
{
alert('Error:\nCannot be resizable because "jQuery.resizable" plugin is not available.');
}
}
//Add navigation icons
//Total height of nav/2 - total height of arrow/2
var arrowsTopMargin = (parseInt(parseInt($tabsNav.innerHeight(true)/2)-8)),
arrowsCommonCss={'cursor':'pointer','z-index':1000,'position':'absolute','top':3,'height':$tabsNav.outerHeight()-($.browser.safari ? 2 : 1)};
$tabsWrapper.prepend(
$nav = $("")
.disableSelection()
.css({'position':'relative','z-index':3000,'display':'none'})
.append(
$("")
.disableSelection()
.attr('title','Previous tab')
.css(arrowsCommonCss)
.addClass('ui-state-active ui-corner-tl ui-corner-bl stPrev stNav')
.css('left',3)
.append($("").disableSelection().addClass('ui-icon ui-icon-carat-1-w').html('Previous tab').css('margin-top',arrowsTopMargin))
.click(function(){
//Check if disabled
if($(this).hasClass('ui-state-disabled')) return;
//Just select the previous tab and trigger scrollToTab event
prevIndex = $tabsNav.find('li.ui-tabs-selected').prevAll().length-1
//Now select the tab
$tabsNav.find('li').eq(prevIndex).find('a').trigger('click');
return false;
}),
$("")
.disableSelection()
.attr('title','Next tab')
.css(arrowsCommonCss)
.addClass('ui-state-active ui-corner-tr ui-corner-br stNext stNav')
.css({'right':3})
.append($("").addClass('ui-icon ui-icon-carat-1-e').html('Next tab').css('margin-top',arrowsTopMargin))
.click(function(){
//Just select the previous tab and trigger scrollToTab event
nextIndex = $tabsNav.find('li.ui-tabs-selected').prevAll().length+1
//Now select the tab
$tabsNav.find('li').eq(nextIndex).find('a').trigger('click');
return false;
})
)
);
//Bind events to the $tabs
$tabs
.bind('tabsremove', function(){
$tabs.trigger('scrollToTab').trigger('navHandler').trigger('navEnabler');
})
.bind('addCloseButton',function(){
//Add close button if require
if(!o.closable) return;
$(this).find('.ui-tabs-nav li').each(function(){
if($(this).find('.ui-tabs-close').length>0) return; //Already has close button
var closeTopMargin = parseInt(parseInt($tabsNav.find('li:first').innerHeight()/2,10)-8);
$(this).disableSelection().append(
$('')
.click(function()
{
$tabs.tabs('remove',$(this).parents('li').prevAll().length);
//If one tab remaining than hide the close button
if($tabs.tabs('length')==1)
{
$tabsNav.find('.ui-icon-close').hide();
}
else
{
$tabsNav.find('.ui-icon-close').show();
}
//Call the method when tab is closed (if any)
if($.isFunction(o.onTabClose))
{
o.onTabClose();
}
return false;
})
);
//Show all close buttons if any hidden
$tabsNav.find('.ui-icon-close').show();
});
})
.bind('tabsadd',function(event){
//Select it on Add
$tabs.tabs('select',$tabs.tabs('length')-1);
//Now remove the extra span added to the tab (not needed)
$lastTab = $tabsNav.find('li:last');
if($lastTab.find('a span.stExtraSpan').length>0) $lastTab.find('a').html($lastTab.find('a span').html());
//Move the li to the innerwrapper
$lastTab.appendTo($widthChecker);
//Scroll the navigation to the newly added tab and also add close button to it
$tabs
.trigger('addCloseButton')
.trigger('bindTabClick')
.trigger('navHandler')
.trigger('scrollToTab');
})//End tabsadd
.bind('addTab',function(event,label,content){
//Generate a random id
var tabid = 'stTab-'+(Math.floor(Math.random()*10000));
//Append the content to the body
$('body').append($('').append(content));
//Add the tab
$tabs.tabs('add','#'+tabid,label);
})//End addTab
.bind('bindTabClick',function(){
//Handle scroll when user manually click on a tab
$tabsNav.find('a').click(function(){
var $liClicked = $(this).parents('li');
var navWidth = $nav.find('.stPrev').outerWidth(true);
//debug('left='+($liClicked.offset().left)+' and tabs width = '+ ($tabs.width()-navWidth));
if(($liClicked.position().left-navWidth)<0)
{
$tabs.trigger('scrollToTab',[$liClicked,'tabClicked','left'])
}
else if(($liClicked.outerWidth()+$liClicked.position().left)>($tabs.width()-navWidth))
{
$tabs.trigger('scrollToTab',[$liClicked,'tabClicked','right'])
}
//Enable or disable next and prev arrows
$tabs.trigger('navEnabler');
return false;
});
})
//Bind the event to act when tab is added
.bind('scrollToTab',function(event,$tabToScrollTo,clickedFrom,hiddenOnSide){
//If tab not provided than scroll to the last tab
$tabToScrollTo = (typeof $tabToScrollTo!='undefined') ? $($tabToScrollTo) : $tabsNav.find('li.ui-tabs-selected');
//Scroll the pane to the last tab
var navWidth = $nav.is(':visible') ? $nav.find('.stPrev').outerWidth(true) : 0;
//debug($tabToScrollTo.prevAll().length)
offsetLeft = -($tabs.width()-($tabToScrollTo.outerWidth(true)+navWidth+parseInt($tabsNav.find('li:last').css('margin-right'),10)));
offsetLeft = (clickedFrom=='tabClicked' && hiddenOnSide=='left') ? -navWidth : offsetLeft;
offsetLeft = (clickedFrom=='tabClicked' && hiddenOnSide=='right') ? offsetLeft : offsetLeft;
//debug(offsetLeft);
var scrollSettings = { 'axis':'x', 'margin':true, 'offset': {'left':offsetLeft}, 'easing':o.easing||'' }
//debug(-($tabs.width()-(116+navWidth)));
$tabsNav.scrollTo($tabToScrollTo,o.animationSpeed,scrollSettings);
})
.bind('navEnabler',function(){
setTimeout(function(){
//Check if last or first tab is selected than disable the navigation arrows
var isLast = $tabsNav.find('.ui-tabs-selected').is(':last-child'),
isFirst = $tabsNav.find('.ui-tabs-selected').is(':first-child'),
$ntNav = $tabsWrapper.find('.stNext'),
$pvNav = $tabsWrapper.find('.stPrev');
//debug('isLast = '+isLast+' - isFirst = '+isFirst);
if(isLast)
{
$pvNav.removeClass('ui-state-disabled');
$ntNav.addClass('ui-state-disabled');
}
else if(isFirst)
{
$ntNav.removeClass('ui-state-disabled');
$pvNav.addClass('ui-state-disabled');
}
else
{
$ntNav.removeClass('ui-state-disabled');
$pvNav.removeClass('ui-state-disabled');
}
},o.animationSpeed);
})
//Now check if tabs need navigation (many tabs out of sight)
.bind('navHandler',function(){
//Check the width of $widthChecker against the $tabsNav. If widthChecker has bigger width than show the $nav else hide it
if($widthChecker.width()>$tabsNav.width())
{
$nav.show();
//Put some margin to the first tab to make it visible if selected
$tabsNav.find('li:first').css('margin-left',$nav.find('.stPrev').outerWidth(true));
}
else
{
$nav.hide();
//Remove the margin from the first element
$tabsNav.find('li:first').css('margin-left',0);
}
})
.bind('tabsselect', function() {
//$tabs.trigger('navEnabler');
})
.bind('resized', function() {
$tabs.trigger('navHandler');
$tabs.trigger('scrollToTab',$tabsNav.find('li.ui-tabs-selected'));
})
//To add close buttons to the already existing tabs
.trigger('addCloseButton')
.trigger('bindTabClick')
//For the tabs that already exists
.trigger('navHandler')
.trigger('navEnabler');
//Select last tab if option is true
if(o.loadLastTab)
{
setTimeout(function(){$tabsNav.find('li:last a').trigger('click')},o.animationSpeed);
}
});
//Just for debuging
function debug(obj)
{console.log(obj)}
}
})(jQuery);