/**
 * Accessible Tabs - jQuery plugin for accessible, unobtrusive tabs
 * Build to seemlessly work with the CCS-Framework YAML (yaml.de) not depending on YAML though
 * @requires jQuery - tested with 1.4.2 but might as well work with older versions
 *
 * english article: http://blog.ginader.de/archives/2009/02/07/jQuery-Accessible-Tabs-How-to-make-tabs-REALLY-accessible.php
 * german article: http://blog.ginader.de/archives/2009/02/07/jQuery-Accessible-Tabs-Wie-man-Tabs-WIRKLICH-zugaenglich-macht.php
 * 
 * code: http://github.com/ginader/Accessible-Tabs
 * please report issues at: http://github.com/ginader/Accessible-Tabs/issues
 *
 * Copyright (c) 2007 Dirk Ginader (ginader.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Version: 1.7
 * 
**/

(function($) { var debugMode = false; $.fn.extend({ getUniqueId: function(p, q, r){ if (r===undefined) {r='';} else {r='-'+r;} return p + q + r; }, accessibleTabs: function(config) { var defaults = { wrapperClass: 'content', currentClass: 'tabs-selected', tabhead: 'h4', tabheadClass: 'hidden', tabbody: '.tabbody', fx:'show', fxspeed: 'normal', currentInfoText: 'aktueller Tab: ', currentInfoPosition: 'prepend', currentInfoClass: 'hidden', tabsListClass:'tabs-list', syncheights:false, syncHeightMethodName:'syncHeight', cssClassAvailable:false, saveState:false, autoAnchor:false, pagination:false }; var keyCodes = { 37 : -1, 38 : -1, 39 : +1, 40 : +1 }; this.options = $.extend(defaults, config); var o = this; return this.each(function(t) { var el = $(this); var list = ''; var tabCount = 0; ids = []; $(el).wrapInner('<div class="'+o.options.wrapperClass+'"></div>'); $(el).find(o.options.tabhead).each(function(i){ var id = ''; elId = $(this).attr('id'); if(elId){ id =' id="'+elId+'"'; } var tabId = o.getUniqueId('tabs', t, i); ids.push(tabId); $(this).attr({"id": tabId, "class": o.options.tabheadClass, "tabindex": "-1"}); if(o.options.cssClassAvailable === true) { var cssClass = ''; if($(el).attr('class')) { cssClass = $(this).attr('class'); cssClass = ' class="'+cssClass+'"'; list += '<li><a'+id+''+cssClass+' href="#'+tabId+'">'+$(this).html()+'</a></li>'; } } else { list += '<li><a'+id+' href="#'+tabId+'">'+$(this).html()+'</a></li>'; } tabCount++; }); $(el).prepend('<h6 class="hidden">Tab-Auswahl</h6><ul class="tabs-nav '+o.options.tabsListClass+' tabamount'+tabCount+'">'+list+'</ul>'); $(el).find(o.options.tabbody).hide(); $(el).find(o.options.tabbody+':first').show(); $(el).find("ul>li:first").addClass(o.options.currentClass) .find('a')[o.options.currentInfoPosition]('<span class="'+o.options.currentInfoClass+'">'+o.options.currentInfoText+'</span>'); if (o.options.syncheights && $.fn[o.options.syncHeightMethodName]) { $(el).find(o.options.tabbody)[o.options.syncHeightMethodName](); $(window).resize(function(){ $(el).find(o.options.tabbody)[o.options.syncHeightMethodName](); }); } $(el).find('ul.'+o.options.tabsListClass+'>li>a').each(function(i){ $(this).click(function(event){ event.preventDefault(); if(o.options.saveState && $.cookie){ $.cookie('tab_'+el.attr('id')+'_active',i); } $(el).find('ul>li.'+o.options.currentClass).removeClass(o.options.currentClass) .find("span."+o.options.currentInfoClass).remove(); $(this).blur(); $(el).find(o.options.tabbody+':visible').hide(); $(el).find(o.options.tabbody).eq(i)[o.options.fx](o.options.fxspeed); $(this)[o.options.currentInfoPosition]('<span class="'+o.options.currentInfoClass+'">'+o.options.currentInfoText+'</span>') .parent().addClass(o.options.currentClass); $($(this).attr("href")).focus().keyup(function(event){ if(keyCodes[event.keyCode]){ o.showAccessibleTab(i+keyCodes[event.keyCode]); $(this).unbind( "keyup" ); } }); }); $(this).focus(function(event){ $(document).keyup(function(event){ if(keyCodes[event.keyCode]){ o.showAccessibleTab(i+keyCodes[event.keyCode]); } }); }); $(this).blur(function(event){ $(document).unbind( "keyup" ); }); }); if(o.options.saveState && $.cookie){ var savedState = $.cookie('tab_'+el.attr('id')+'_active'); debug($.cookie('tab_'+el.attr('id')+'_active')); if(savedState != null){ o.showAccessibleTab(savedState,el.attr('id')); } }; if(o.options.autoAnchor && window.location.hash){ var anchorTab = $('.'+o.options.tabsListClass).find(window.location.hash); if(anchorTab.size()){ anchorTab.click(); } }; if(o.options.pagination){ var m = '<ul class="pagination">'; m +='    <li class="previous"><a href="#{previousAnchor}"><span>{previousHeadline}</span></a></li>'; m +='    <li class="next"><a href="#{nextAnchor}"><span>{nextHeadline}</span></a></li>'; m +='</ul>'; var tabs = $(el).find('.tabbody'); var tabcount = tabs.size(); tabs.each(function(idx){ $(this).append(m); var next = idx+1; if(next>=tabcount){next = 0;} var previous = idx-1; if(previous<0){previous = tabcount-1;} var p = $(this).find('.pagination'); var previousEl = p.find('.previous'); previousEl.find('span').text($('#'+ids[previous]).text()); previousEl.find('a').attr('href','#'+ids[previous]) .click(function(event){ event.preventDefault(); $(el).find('.tabs-list a[href|=#'+ids[previous]+']').click(); }); var nextEl = p.find('.next'); nextEl.find('span').text($('#'+ids[next]).text()); nextEl.find('a').attr('href','#'+ids[next]) .click(function(event){ event.preventDefault(); $(el).find('.tabs-list a[href|=#'+ids[next]+']').click(); }); }); } }); }, showAccessibleTab: function(index,id){ debug('showAccessibleTab'); var o = this; if(id){ var el = $('#'+id); var links = el.find('ul.'+o.options.tabsListClass+'>li>a'); links.eq(index).click(); }else{ return this.each(function() { var el = $(this); var links = el.find('ul.'+o.options.tabsListClass+'>li>a'); links.eq(index).click(); }); } } }); function debug(msg,info){ if(debugMode && window.console && window.console.log){ if(info){ window.console.log(info+': ',msg); }else{ window.console.log(msg); } } } })(jQuery);