/* wsFlexitabs 1.2 for jQuery - simple unobtrusive and very flexible tabbing solution * * @author Fedor Pudeyan * * HTML: * Just add this script in HEAD, then * add class "flexitabs" to element containing all tabs * add class "tab" to any tab * add class "content" to elements with tab's contents * ATTENTION! Order and quantity of tab elements and their content elements must be the same! * * CSS: * "active" and "inactive" classes will be added dinamycally to tabs and contents. * * JS: * You can create your own instance of object with custom options: * new wsFlexitabs(options); - this creates new object with custom JSON params - see strings 22-28 in this file. * * Release notes: * 1.1 - previous and next buttons functionality, ability to serve multiple nested tabulators, fixed bug in activate method * 1.1.1 - activate and deactivate handlers added to tabs * 1.2 - AJAX-content loading and caching functionality */ var wsFlexitabs = function(options) { this.defaults = { // CSS-selectors of target elements in DOM for unobtrusive attaching containerSelector: '.flexitabs', tabSelector: '.tab', contentSelector: '.content', previousButtonSelector: 'a.previous', nextButtonSelector: 'a.next', // Getting and inserting AJAX-content getContentUrl: function(tab) { // should return url string for AJAX-loading content if($(tab).hasClass('ajax')) return $(tab).attr('href'); }, newTab: function() { // should return new tab-element return $('
'); }, contentContainerSelector: '.contents', // only to insert first tab // Caching AJAX-content enableCaching: true, noCacheClass: 'nocache', cacheClass: 'cache', cachedClass: 'cached', // CSS classes for indicate active and inactive tabs and contents of tabs activeClass: 'active', inactiveClass: 'inactive', // Handler functions activateHandler: function(storage){}, // Storage name storageName: 'wsFlexitabs' } this.initialize = function() { var flexitabs_object = this, i=0; $(this.containerSelector).each(function() { if($(this).data(flexitabs_object.storageName)){ try{ console.log(flexitabs_object.storageName + ": Can't init, this object already initialized before:", this); }catch(e){} return false; } var storage = {}; storage.object = this; storage.tabs = $(this).find(flexitabs_object.tabSelector).filter(function(){return $(this).parents(flexitabs_object.containerSelector)[0] == storage.object}); //array of links to DOM-elements of tabs storage.contents = $(this).find(flexitabs_object.contentSelector).filter(function(){return $(this).parents(flexitabs_object.containerSelector)[0] == storage.object}); //array of links to DOM-elements of tab contents storage.contents = $.map(storage.tabs, function(tab, i) { var content, contents = $(storage.object).find(flexitabs_object.contentSelector).filter(function(){return $(this).parents(flexitabs_object.containerSelector)[0] == storage.object}); if (flexitabs_object.getContentUrl(tab) && !i) { //if first tab is dynamic content = $(storage.object).find(flexitabs_object.contentContainerSelector).filter(function(){return $(this).parents(flexitabs_object.containerSelector)[0] == storage.object}).prepend(flexitabs_object.newTab()).children().first().get() }else if(flexitabs_object.getContentUrl(tab)){ content = $(contents[i-1]).after(flexitabs_object.newTab()).next().get() }else{ content = contents[i] } return content; }) storage.previousButtons = $(this).find(flexitabs_object.previousButtonSelector).filter(function(){return $(this).parents(flexitabs_object.containerSelector)[0] == storage.object}); //array of links to DOM-elements of previous buttons storage.nextButtons = $(this).find(flexitabs_object.nextButtonSelector).filter(function(){return $(this).parents(flexitabs_object.containerSelector)[0] == storage.object}); //array of links to DOM-elements of next buttons if (storage.tabs.length <= storage.contents.length) { var active = 0, container = $(this); $(storage.tabs).each(function(i){ //initializing storage for tabs and contents var tab_storage = {}; var content_storage = {}; tab_storage.object = content_storage.object = container; tab_storage.index = content_storage.index = i; $(this).click(function() { //bind click handler to tabs flexitabs_object.activate(this); return false; }); if ($(this).hasClass(flexitabs_object.activeClass)) active = i; $(storage.tabs[i]).data(flexitabs_object.storageName, tab_storage); //storing data in tabs storage $(storage.contents[i]).data(flexitabs_object.storageName, content_storage); //storing data in tab contents storage }); storage.previousButtons.data(flexitabs_object.storageName, storage).click(function() { //bind click handler to previous buttons flexitabs_object.previous(this); return false; }); storage.nextButtons.data(flexitabs_object.storageName, storage).click(function() { //bind click handler to next buttons flexitabs_object.next(this); return false; }); storage.active = active; container.data(flexitabs_object.storageName, storage); //storing whole tabulator data in container storage flexitabs_object.activate(storage.tabs[active]); //initial tab activation }else{ try{ console.log(flexitabs_object.storageName + ": Can't init, there are brocken tabs in this instance:", this); }catch(e){} } }); } this.activate = function(tab) { var tab_storage = $(tab).data(this.storageName), storage = $(tab_storage.object).data(this.storageName); //deactivation of current active tab and content $(storage.tabs).removeClass(this.activeClass).addClass(this.inactiveClass); $(storage.contents).removeClass(this.activeClass).addClass(this.inactiveClass); //activation of clicked tab and content $(tab).removeClass(this.inactiveClass).addClass(this.activeClass); $(storage.contents[tab_storage.index]).removeClass(this.inactiveClass).addClass(this.activeClass); if (!tab_storage.index) $(storage.previousButtons).addClass(this.inactiveClass).removeClass(this.activeClass); else $(storage.previousButtons).addClass(this.activeClass).removeClass(this.inactiveClass); if (tab_storage.index == (storage.tabs.length - 1)) $(storage.nextButtons).addClass(this.inactiveClass).removeClass(this.activeClass); else $(storage.nextButtons).addClass(this.activeClass).removeClass(this.inactiveClass); storage.active = tab_storage.index; if(!$(tab).hasClass(this.cachedClass) && this.getContentUrl(tab)) $(storage.contents[storage.active]).load(this.getContentUrl(tab)); if((this.enableCaching && !$(tab).hasClass(this.noCacheClass)) || (!this.enableCaching && $(tab).hasClass(this.cacheClass))) $(tab).addClass(this.cachedClass); this.activateHandler(storage); } this.previous = function(link) { var storage = $(link).data(this.storageName); if(storage.active) $(storage.tabs[storage.active - 1]).click(); } this.next = function(link) { var storage = $(link).data(this.storageName); if(storage.active < (storage.tabs.length - 1)) $(storage.tabs[storage.active + 1]).click(); } $.extend(this, this.defaults, options); this.initialize(); }; $(function() { new wsFlexitabs(); })