PageSourceSearch

https://www.uab.cat/Xcelerate/UAB2013/UABResponsive/PortalUAB/js/jquery.tabs.js

js uab.cat collected 2026-09-24 08:27:22 UTC 14,669 bytes, 266 lines download raw bytes

1/**
2 * Accessible Tabs - jQuery plugin for accessible, unobtrusive tabs
3 * Build to seemlessly work with the CCS-Framework YAML (yaml.de) not depending on YAML though
4 * @requires jQuery - tested with 1.9.1, 1.7 and 1.4.2 but might as well work with older versions
5 *
6 * english article: http://blog.ginader.de/archives/2009/02/07/jQuery-Accessible-Tabs-How-to-make-tabs-REALLY-accessible.php
7 * german article: http://blog.ginader.de/archives/2009/02/07/jQuery-Accessible-Tabs-Wie-man-Tabs-WIRKLICH-zugaenglich-macht.php
8 * 
9 * code: http://github.com/ginader/Accessible-Tabs
10 * please report issues at: http://github.com/ginader/Accessible-Tabs/issues
11 *
12 * Copyright (c) 2007 Dirk Ginader (ginader.de)
13 * Dual licensed under the MIT and GPL licenses:
14 * http://www.opensource.org/licenses/mit-license.php
15 * http://www.gnu.org/licenses/gpl.html
16 *
17 */
18
19(function($) {
20    var debugMode = true;
21    $.fn.extend({
22        // We assume there could be multiple sets of tabs on a page, so,
23        // the unique id for each invididual tab's heading is identified with params q and r (e.g., id="accessibletabscontent0-2")
24        getUniqueId: function(p, q, r){
25            if (r===undefined) {r='';} else {r='-'+r;}
26            return p + q + r;
27        },
28        accessibleTabs: function(config) {
29            var defaults = {
30                wrapperClass: 'contentTabs', // Classname to apply to the div that is wrapped around the original Markup
31                currentClass: 'current', // Classname to apply to the LI of the selected Tab
32                tabhead: 'h3', // Tag or valid Query Selector of the Elements to Transform the Tabs-Navigation from (originals are removed)
33                tabheadClass: 'tabhead', // Classname to apply to the target heading element for each tab div
34                tabbody: '.tabbody', // Tag or valid Query Selector of the Elements to be treated as the Tab Body
35                fx:'show', // can be "fadeIn", "slideDown", "show"
36                fxspeed: 'normal', // speed (String|Number): "slow", "normal", or "fast") or the number of milliseconds to run the animation
37                currentInfoText: 'current tab: ', // text to indicate for screenreaders which tab is the current one
38                currentInfoPosition: 'prepend', // Definition where to insert the Info Text. Can be either "prepend" or "append"
39                currentInfoClass: 'current-info', // Class to apply to the span wrapping the CurrentInfoText
40                tabsListClass:'tabs-list', // Class to apply to the generated list of tabs above the content
41                syncheights:false, // syncs the heights of the tab contents when the SyncHeight plugin is available http://blog.ginader.de/dev/jquery/syncheight/index.php
42                syncHeightMethodName:'syncHeight', // set the Method name of the plugin you want to use to sync the tab contents. Defaults to the SyncHeight plugin: http://github.com/ginader/syncHeight
43                cssClassAvailable:false, // Enable individual css classes for tabs. Gets the appropriate class name of a tabhead element and apply it to the tab list element. Boolean value
44                saveState:false, // save the selected tab into a cookie so it stays selected after a reload. This requires that the wrapping div needs to have an ID (so we know which tab we're saving)
45                autoAnchor:false, // will move over any existing id of a headline in tabs markup so it can be linked to it
46                pagination:false, // adds buttons to each tab to switch to the next/previous tab
47                position:'top', // can be 'top' or 'bottom'. Defines where the tabs list is inserted.
48                wrapInnerNavLinks: '', // inner wrap for a-tags in tab navigation. See http://api.jquery.com/wrapInner/ for further informations
49                firstNavItemClass: 'first', // Classname of the first list item in the tab navigation
50                lastNavItemClass: 'last', // Classname of the last list item in the tab navigation
51                clearfixClass: 'clearfix' // Name of the Class that is used to clear/contain floats
52            };
53            var keyCodes = {
54                37 : -1, //LEFT
55                38 : -1, //UP
56                39 : +1, //RIGHT 
57                40 : +1 //DOWN
58            };
59            var positions = {
60                top : 'prepend',
61                bottom : 'append'
62            };
63            this.options = $.extend(defaults, config);
64
65            var tabsCount = 0;
66            if($("body").data('accessibleTabsCount') !== undefined){
67                tabsCount = $("body").data('accessibleTabsCount');
68            }
69            $("body").data('accessibleTabsCount',this.size()+tabsCount);
70
71            var o = this;
72            return this.each(function(t) {
73                var el = $(this);
74                var list = '';
75                var tabCount = 0;
76                var ids = [];
77
78                $(el).wrapInner('<div class="'+o.options.wrapperClass+'"></div>');
79
80                $(el).find(o.options.tabhead).each(function(i){
81                    var id = '';
82                    var elId = $(this).attr('id');
83                    if(elId){
84                        // Skip this item if it already exists.
85                        if(elId.indexOf('accessibletabscontent') === 0) {
86                            return;
87                        }
88                        id =' id="'+elId+'"';
89                    }
90                    var tabId = o.getUniqueId('accessibletabscontent', tabsCount+t, i);//get a unique id to assign to this tab's heading
91                    var navItemId = o.getUniqueId('accessibletabsnavigation', tabsCount+t, i);//get a unique id for this navigation item
92                    ids.push(tabId);
93                    if(o.options.cssClassAvailable === true) {
94                        var cssClass = '';
95                        if($(this).attr('class')) {
96                            cssClass = $(this).attr('class');
97                            cssClass = ' class="'+cssClass+'"';
98                        }
99                        list += '<li id="'+navItemId+'"><a'+id+''+cssClass+' href="#'+tabId+'">'+$(this).html()+'</a></li>';
100                    } else {
101                      list += '<li id="'+navItemId+'"><a'+id+' href="#'+tabId+'">'+$(this).html()+'</a></li>';
102                    }
103                    $(this).attr({"id": tabId, "class": o.options.tabheadClass, "tabindex": "-1"});//assign the unique id and the tabheadClass class name to this tab's heading
104                    tabCount++;
105                });
106
107                if (o.options.syncheights && $.fn[o.options.syncHeightMethodName]) {
108                    $(el).find(o.options.tabbody)[o.options.syncHeightMethodName]();
109                    $(window).resize(function(){
110                        $(el).find(o.options.tabbody)[o.options.syncHeightMethodName]();
111                    });
112                }
113
114                // Ensure that the call to setup tabs is re-runnable
115                var tabs_selector = '.' + o.options.tabsListClass;
116                if(!$(el).find(tabs_selector).length) {
117                    $(el)[positions[o.options.position]]('<ul class="'+o.options.clearfixClass+' '+o.options.tabsListClass+' tabamount'+tabCount+'"></ul>');
118                }
119
120                $(el).find(tabs_selector).append(list);
121
122                // initial show first content block and hide the others
123                var content = $(el).find(o.options.tabbody);
124                if (content.length > 0) {
125                    $(content).hide();
126                    $(content[0]).show();
127                }
128                $(el).find("ul."+o.options.tabsListClass+">li:first").addClass(o.options.currentClass).addClass(o.options.firstNavItemClass)
129                  .find('a')[o.options.currentInfoPosition]('<span class="'+o.options.currentInfoClass+'">'+o.options.currentInfoText+'</span>')
130                  .parents("ul."+o.options.tabsListClass).children('li:last').addClass(o.options.lastNavItemClass);
131
132                if (o.options.wrapInnerNavLinks) {
133                  $(el).find('ul.'+o.options.tabsListClass+'>li>a').wrapInner(o.options.wrapInnerNavLinks);
134                }
135
136                $(el).find('ul.'+o.options.tabsListClass+'>li>a').each(function(i){
137                    $(this).click(function(event){
138                        event.preventDefault();
139                        el.trigger("showTab.accessibleTabs", [$(event.target)]);
140                        if(o.options.saveState && $.cookie){
141                            $.cookie('accessibletab_'+el.attr('id')+'_active',i);
142                        }
143                        $(el).find('ul.'+o.options.tabsListClass+'>li.'+o.options.currentClass).removeClass(o.options.currentClass)
144                        .find("span."+o.options.currentInfoClass).remove();
145                        $(this).blur();
146                        $(el).find(o.options.tabbody+':visible').hide();
147                        $(el).find(o.options.tabbody).eq(i)[o.options.fx](o.options.fxspeed);
148                        $(this)[o.options.currentInfoPosition]('<span class="'+o.options.currentInfoClass+'">'+o.options.currentInfoText+'</span>')
149                        .parent().addClass(o.options.currentClass);
150                        //now, only after writing the currentInfoText span to the tab list link, set focus to the tab's heading
151
152                        $($(this).attr("href")).focus().keyup(function(event){
153                            if(keyCodes[event.keyCode]){
154                                o.showAccessibleTab(i+keyCodes[event.keyCode]);
155                                $(this).unbind( "keyup" );
156                            }
157                        });
158
159                        // $(el).find('.accessibletabsanchor').keyup(function(event){
160                        //     if(keyCodes[event.keyCode]){
161                        //         o.showAccessibleTab(i+keyCodes[event.keyCode]);
162                        //     }
163                        // });
164                    });
165
166                    $(this).focus(function(){
167                        $(document).keyup(function(event){
168                            if(keyCodes[event.keyCode]){
169                                o.showAccessibleTab(i+keyCodes[event.keyCode]);
170                            }
171                        });
172                    });
173                    $(this).blur(function(){
174                        $(document).unbind( "keyup" );
175                    });
176
177                });
178
179                if(o.options.saveState && $.cookie){
180                    var savedState = $.cookie('accessibletab_'+el.attr('id')+'_active');
181                    debug($.cookie('accessibletab_'+el.attr('id')+'_active'));
182                    if(savedState !== null){
183                        o.showAccessibleTab(savedState,el.attr('id'));
184                    }
185                }
186
187                if(o.options.autoAnchor && window.location.hash){
188                    var anchorTab = $('.'+o.options.tabsListClass).find(window.location.hash);
189                    if(anchorTab.size()){
190                        anchorTab.click();
191                    }
192                }
193
194                if(o.options.pagination){
195                    var m = '<ul class="pagination">';
196                    m +='    <li class="previous"><a href="#{previousAnchor}"><span>{previousHeadline}</span></a></li>';
197                    m +='    <li class="next"><a href="#{nextAnchor}"><span>{nextHeadline}</span></a></li>';
198                    m +='</ul>';
199                    var tabs = $(el).find('.tabbody');
200                    var tabcount = tabs.size();
201                    tabs.each(function(idx){
202                        $(this).append(m);
203                        var next = idx+1;
204                        if(next>=tabcount){next = 0;}
205                        var previous = idx-1;
206                        if(previous<0){previous = tabcount-1;}
207                        var p = $(this).find('.pagination');
208                        var previousEl = p.find('.previous');
209                        previousEl.find('span').text($('#'+ids[previous]).text());
210                        previousEl.find('a').attr('href','#'+ids[previous])
211                        .click(function(event){
212                            event.preventDefault();
213                            $(el).find('.tabs-list a').eq(previous).click();
214                        });
215                        var nextEl = p.find('.next');
216                        nextEl.find('span').text($('#'+ids[next]).text());
217                        nextEl.find('a').attr('href','#'+ids[next])
218                        .click(function(event){
219                            event.preventDefault();
220                            $(el).find('.tabs-list a').eq(next).click();
221                        });
222                    });
223                }
224            });
225        },
226        showAccessibleTab: function(index,id){
227            debug('showAccessibleTab');
228            var o = this;
229            if(id) {
230                var el = $('#'+id);
231                var links = el.find('ul.'+o.options.tabsListClass+'>li>a');
232                el.trigger("showTab.accessibleTabs", [links.eq(index)]);
233                links.eq(index).click();
234            } else {
235                return this.each(function() {
236                    var el = $(this);
237                    el.trigger("showTab.accessibleTabs");
238                    var links = el.find('ul.'+o.options.tabsListClass+'>li>a');
239                    el.trigger("showTab.accessibleTabs", [links.eq(index)]);
240                    links.eq(index).click();
241                });
242            }
243        },
244        showAccessibleTabSelector: function(selector){
245            debug('showAccessibleTabSelector');
246            var el = $(selector);
247            if(el){
248                if(el.get(0).nodeName.toLowerCase() === 'a'){
249                    el.click();
250                }else{
251                    debug('the selector of a showAccessibleTabSelector() call needs to point to a tabs headline!');
252                }
253            }
254        }
255    });
256    // private Methods
257    function debug(msg,info){
258        if(debugMode && window.console && window.console.log){
259            if(info){
260                window.console.log(info+': ',msg);
261            }else{
262                window.console.log(msg);
263            }
264        }
265    }
266})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.