PageSourceSearch

https://www.studistorici.com/wp-content/themes/branfordmagazine/js/ui.tabs.js

js studistorici.com collected 2026-10-02 07:52:13 UTC 23,116 bytes, 557 lines download raw bytes

1/*
2 * Tabs 3 - New Wave Tabs
3 *
4 * Copyright (c) 2007 Klaus Hartl (stilbuero.de)
5 * Dual licensed under the MIT (MIT-LICENSE.txt)
6 * and GPL (GPL-LICENSE.txt) licenses.
7 *
8 * http://docs.jquery.com/UI/Tabs
9 */
10
11(function($) {
12
13    // if the UI scope is not availalable, add it
14    $.ui = $.ui || {};
15
16    // tabs API methods
17    $.fn.tabs = function() {
18        var method = typeof arguments[0] == 'string' && arguments[0];
19        var args = method && Array.prototype.slice.call(arguments, 1) || arguments;
20
21        return method == 'length' ?
22            $.data(this[0], 'tabs').$tabs.length :
23            this.each(function() {
24                if (method) {
25                    var tabs = $.data(this, 'tabs');
26                    if (tabs) tabs[method].apply(tabs, args);
27                } else
28                    new $.ui.tabs(this, args[0] || {});
29            });
30    };
31
32    // tabs class
33    $.ui.tabs = function(el, options) {
34        var self = this;
35        
36        this.options = $.extend({}, $.ui.tabs.defaults, options);
37        this.element = el;
38
39        // doesn't extend with null
40        if (options.selected === null)
41            this.options.selected = null;
42
43        this.options.event += '.tabs'; // namespace event
44
45        $(el).bind('setData.tabs', function(event, key, value) {
46            if ((/^selected/).test(key))
47                self.select(value);
48            else {
49                self.options[key] = value;
50                self.tabify();
51            }
52        }).bind('getData.tabs', function(event, key) {
53            return self.options[key];
54        });
55
56        // save instance for later
57        $.data(el, 'tabs', this);
58
59        // create tabs
60        this.tabify(true);
61    };
62    
63    $.ui.tabs.defaults = {
64        // basic setup
65        selected: 0,
66        unselect: false,
67        event: 'click',
68        disabled: [],
69        cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
70        // TODO history: false,
71
72        // Ajax
73        spinner: 'Loading…',
74        cache: false,
75        idPrefix: 'ui-tabs-',
76        ajaxOptions: {},
77
78        // animations
79        fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
80
81        // templates
82        tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>',
83        panelTemplate: '<div></div>',
84
85        // CSS classes
86        navClass: 'ui-tabs-nav',
87        selectedClass: 'ui-tabs-selected',
88        unselectClass: 'ui-tabs-unselect',
89        disabledClass: 'ui-tabs-disabled',
90        panelClass: 'ui-tabs-panel',
91        hideClass: 'ui-tabs-hide',
92        loadingClass: 'ui-tabs-loading'
93    };
94
95    // instance methods
96    $.extend($.ui.tabs.prototype, {
97        tabId: function(a) {
98            return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '')
99                || this.options.idPrefix + $.data(a);
100        },
101        ui: function(tab, panel) {
102            return {
103                instance: this,
104                options: this.options,
105                tab: tab,
106                panel: panel
107            };
108        },
109        tabify: function(init) {
110
111            this.$lis = $('li:has(a[href])', this.element);
112            this.$tabs = this.$lis.map(function() { return $('a', this)[0]; });
113            this.$panels = $([]);
114
115            var self = this, o = this.options;
116
117            this.$tabs.each(function(i, a) {
118                // inline tab
119                if (a.hash && a.hash.replace('#', '')) // Safari 2 reports '#' for an empty hash
120                    self.$panels = self.$panels.add(a.hash);
121                // remote tab
122                else if ($(a).attr('href') != '#') { // prevent loading the page itself if href is just "#"
123                    $.data(a, 'href.tabs', a.href);
123 // required for restore on destroy
124                    $.data(a, 'load.tabs', a.href); // mutable
125                    var id = self.tabId(a);
126                    a.href = '#' + id;
127                    var $panel = $('#' + id);
128                    if (!$panel.length) {
129                        $panel = $(o.panelTemplate).attr('id', id).addClass(o.panelClass)
130                            .insertAfter( self.$panels[i - 1] || self.element );
131                        $panel.data('destroy.tabs', true);
132                    }
133                    self.$panels = self.$panels.add( $panel );
134                }
135                // invalid tab href
136                else
137                    o.disabled.push(i + 1);
138            });
139
140            if (init) {
141
142                // attach necessary classes for styling if not present
143                $(this.element).hasClass(o.navClass) || $(this.element).addClass(o.navClass);
144                this.$panels.each(function() {
145                    var $this = $(this);
146                    $this.hasClass(o.panelClass) || $this.addClass(o.panelClass);
147                });
148
149                // Try to retrieve selected tab:
150                // 1. from fragment identifier in url if present
151                // 2. from cookie
152                // 3. from selected class attribute on <li>
153                // 4. otherwise use given "selected" option
154                // 5. check if tab is disabled
155                this.$tabs.each(function(i, a) {
156                    if (location.hash) {
157                        if (a.hash == location.hash) {
158                            o.selected = i;
159                            // prevent page scroll to fragment
160                            //if (($.browser.msie || $.browser.opera) && !o.remote) {
161                            if ($.browser.msie || $.browser.opera) {
162                                var $toShow = $(location.hash), toShowId = $toShow.attr('id');
163                                $toShow.attr('id', '');
164                                setTimeout(function() {
165                                    $toShow.attr('id', toShowId); // restore id
166                                }, 500);
167                            }
168                            scrollTo(0, 0);
169                            return false; // break
170                        }
171                    } else if (o.cookie) {
172                        var index = parseInt($.cookie('ui-tabs' + $.data(self.element)),10);
173                        if (index && self.$tabs[index]) {
174                            o.selected = index;
175                            return false; // break
176                        }
177                    } else if ( self.$lis.eq(i).hasClass(o.selectedClass) ) {
178                        o.selected = i;
179                        return false; // break
180                    }
181                });
182
183                // highlight selected tab
184                this.$panels.addClass(o.hideClass);
185                this.$lis.removeClass(o.selectedClass);
186                if (o.selected !== null) {
187                    this.$panels.eq(o.selected).show().removeClass(o.hideClass); // use show and remove class to show in any case no matter how it has been hidden before
188                    this.$lis.eq(o.selected).addClass(o.selectedClass);
189                }
190
191                // load if remote tab
192                var href = o.selected !== null && $.data(this.$tabs[o.selected], 'load.tabs');
193                if (href)
194                    this.load(o.selected);
195
196                // Take disabling tabs via class attribute from HTML
197                // into account and update option properly...
198                o.disabled = $.unique(o.disabled.concat(
199                    $.map(this.$lis.filter('.' + o.disabledClass),
200                        function(n, i) { return self.$lis.index(n); } )
201                )).sort();
202                
203                // clean up to avoid memory leaks in certain versions of IE 6
204                $(window).bind('unload', function() {
205                    self.$tabs.unbind('.tabs');
206                    self.$lis = self.$tabs = self.$panels = null;
207                });
208
209            }
210
211            // disable tabs
212            for (var i = 0, li; li = this.$lis[i]; i++)
213                $(li)[$.inArray(i, o.disabled) != -1 && !$(li).hasClass(o.selectedClass) ? 'addClass' : 'removeClass'](o.disabledClass);
214
215            // reset cache if switching from cached to not cached
216            if (o.cache === false)
217                this.$tabs.removeData('cache.tabs');
218            
219            // set up animations
220            var hideFx, showFx, baseFx = { 'min-width': 0, duration: 1 }
220, baseDuration = 'normal';
221            if (o.fx && o.fx.constructor == Array)
222                hideFx = o.fx[0] || baseFx, showFx = o.fx[1] || baseFx;
223            else
224                hideFx = showFx = o.fx || baseFx;
225
226            // reset some styles to maintain print style sheets etc.
227            var resetCSS = { display: '', overflow: '', height: '' };
228            if (!$.browser.msie) // not in IE to prevent ClearType font issue
229                resetCSS.opacity = '';
230
231            // Hide a tab, animation prevents browser scrolling to fragment,
232            // $show is optional.
233            function hideTab(clicked, $hide, $show) {
234                $hide.animate(hideFx, hideFx.duration || baseDuration, function() { //
235                    $hide.addClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc.
236                    if ($.browser.msie && hideFx.opacity)
237                        $hide[0].style.filter = '';
238                    if ($show)
239                        showTab(clicked, $show, $hide);
240                });
241            }
242
243            // Show a tab, animation prevents browser scrolling to fragment,
244            // $hide is optional.
245            function showTab(clicked, $show, $hide) {
246                if (showFx === baseFx)
247                    $show.css('display', 'block'); // prevent occasionally occuring flicker in Firefox cause by gap between showing and hiding the tab panels
248                $show.animate(showFx, showFx.duration || baseDuration, function() {
249                    $show.removeClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc.
250                    if ($.browser.msie && showFx.opacity)
251                        $show[0].style.filter = '';
252
253                    // callback
254                    $(self.element).triggerHandler('tabsshow', [self.ui(clicked, $show[0])], o.show);
255
256                });
257            }
258
259            // switch a tab
260            function switchTab(clicked, $li, $hide, $show) {
261                /*if (o.bookmarkable && trueClick) { // add to history only if true click occured, not a triggered click
262                    $.ajaxHistory.update(clicked.hash);
263                }*/
264                $li.addClass(o.selectedClass)
265                    .siblings().removeClass(o.selectedClass);
266                hideTab(clicked, $hide, $show);
267            }
268
269            // attach tab event handler, unbind to avoid duplicates from former tabifying...
270            this.$tabs.unbind('.tabs').bind(o.event, function() {
271
272                //var trueClick = e.clientX; // add to history only if true click occured, not a triggered click
273                var $li = $(this).parents('li:eq(0)'),
274                    $hide = self.$panels.filter(':visible'),
275                    $show = $(this.hash);
276
277                // If tab is already selected and not unselectable or tab disabled or 
278                // or is already loading or click callback returns false stop here.
279                // Check if click handler returns false last so that it is not executed
280                // for a disabled or loading tab!
281                if (($li.hasClass(o.selectedClass) && !o.unselect)
282                    || $li.hasClass(o.disabledClass) 
283                    || $(this).hasClass(o.loadingClass)
284                    || $(self.element).triggerHandler('tabsselect', [self.ui(this, $show[0])], o.select) === false
285                    ) {
286                    this.blur();
287                    return false;
288                }
289
290                self.options.selected = self.$tabs.index(this);
291
292                // if tab may be closed
293                if (o.unselect) {
294                    if ($li.hasClass(o.selectedClass)) {
295                        self.options.selected = null;
296                        $li.removeClass(o.selectedClass);
297                        self.$panels.stop();
298                        hideTab(this, $hide);
299                        this.blur();
300                        return false;
301                    } else if (!$hide.length) {
302                        self.$panels.stop();
303                        var a = this;
304                        self.load(self.$tabs.index(this), function() {
305                            $li.addClass(o.selectedClass).addClass(o.unselectClass);
306                            showTab(a, $show);
307                        });
308                        this.blur();
309                        return false;
310                    }
311                }
312
313                if (o.cookie)
314                    $.cookie('ui-tabs' + $.data(self.element), self.options.selected, o.cookie);
315
316                // stop possibly running animations
317                self.$panels.stop();
318
319                // show new tab
320                if ($show.length) {
321
322                    // prevent scrollbar scrolling to 0 and than back in IE7, happens only if bookmarking/history is enabled
323                    /*if ($.browser.msie && o.bookmarkable) {
324                        var showId = this.hash.replace('#', '');
325                        $show.attr('id', '');
326                        setTimeout(function() {
327                            $show.attr('id', showId); // restore id
328                        }, 0);
329                    }*/
330
331                    var a = this;
332                    self.load(self.$tabs.index(this), $hide.length ? 
333                        function() {
334                            switchTab(a, $li, $hide, $show);
335                        } :
336                        function() {
337                            $li.addClass(o.selectedClass);
338                            showTab(a, $show);
339                        }
340                    );
341
342                    // Set scrollbar to saved position - need to use timeout with 0 to prevent browser scroll to target of hash
343                    /*var scrollX = window.pageXOffset || document.documentElement && document.documentElement.scrollLeft || document.body.scrollLeft || 0;
344                    var scrollY = window.pageYOffset || document.documentElement && document.documentElement.scrollTop || document.body.scrollTop || 0;
345                    setTimeout(function() {
346                        scrollTo(scrollX, scrollY);
347                    }, 0);*/
348
349                } else
350                    throw 'jQuery UI Tabs: Mismatching fragment identifier.';
351
352                // Prevent IE from keeping other link focussed when using the back button
353                // and remove dotted border from clicked link. This is controlled in modern
354                // browsers via CSS, also blur removes focus from address bar in Firefox
355                // which can become a usability and annoying problem with tabsRotate.
356                if ($.browser.msie)
357                    this.blur();
358
359                //return o.bookmarkable && !!trueClick; // convert trueClick == undefined to Boolean required in IE
360                return false;
361
362            });
363
364            // disable click if event is configured to something else
365            if (!(/^click/).test(o.event))
366                this.$tabs.bind('click.tabs', function() { return false; });
367
368        },
369        add: function(url, label, index) {
370            if (index == undefined) 
371                index = this.$tabs.length; // append by default
372
373            var o = this.options;
374            var $li = $(o.tabTemplate.replace(/#\{href\}/, url).replace(/#\{label\}/, label));
375            $li.data('destroy.tabs', true);
376
377            var id = url.indexOf('#') == 0 ? url.replace('#', '') : this.tabId( $('a:first-child', $li)[0] );
378
379            // try to find an existing element before creating a new one
380            var $panel = $('#' + id);
381            if (!$panel.length) {
382                $panel = $(o.panelTemplate).attr('id', id)
383                    .addClass(o.panelClass).addClass(o.hideClass);
384                $panel.data('destroy.tabs', true);
385            }
386            if (index >= this.$lis.length) {
387                $li.appendTo(this.element);
388                $panel.appendTo(this.element.parentNode);
389            } else {
390                $li.insertBefore(this.$lis[index]);
391                $panel.insertBefore(this.$panels[index]);
392            }
393            
394            o.disabled = $.map(o.disabled,
395                function(n, i) { return n >= index ? ++n : n });
396                
397            this.tabify();
398
399            if (this.$tabs.length == 1) {
400                 $li.addClass(o.selectedClass);
401                 $panel.removeClass(o.hideClass);
402                 var href = $.data(this.$tabs[0], 'load.tabs');
403                 if (href)
404                     this.load(index, href);
405            }
406
407            // callback
408            $(this.element).triggerHandler('tabsadd',
409                [this.ui(this.$tabs[index], this.$panels[index])], o.add
410            );
411        },
412        remove: function(index) {
413            var o = this.options, $li = this.$lis.eq(index).remove(),
414                $panel = this.$panels.eq(index).remove();
415
416            // If selected tab was removed focus tab to the right or
417            // in case the last tab was removed the tab to the left.
418            if ($li.hasClass(o.selectedClass) && this.$tabs.length > 1)
419                this.select(index + (index + 1 < this.$tabs.length ? 1 : -1));
420
421            o.disabled = $.map($.grep(o.disabled, function(n, i) { return n != 
421index; }),
422                function(n, i) { return n >= index ? --n : n });
423
424            this.tabify();
425
426            // callback
427            $(this.element).triggerHandler('tabsremove',
428                [this.ui($li.find('a')[0], $panel[0])], o.remove
429            );
430        },
431        enable: function(index) {
432            var o = this.options;
433            if ($.inArray(index, o.disabled) == -1)
434                return;
435                
436            var $li = this.$lis.eq(index).removeClass(o.disabledClass);
437            if ($.browser.safari) { // fix disappearing tab (that used opacity indicating disabling) after enabling in Safari 2...
438                $li.css('display', 'inline-block');
439                setTimeout(function() {
440                    $li.css('display', 'block');
441                }, 0);
442            }
443
444            o.disabled = $.grep(o.disabled, function(n, i) { return n != index; });
445
446            // callback
447            $(this.element).triggerHandler('tabsenable',
448                [this.ui(this.$tabs[index], this.$panels[index])], o.enable
449            );
450
451        },
452        disable: function(index) {
453            var self = this, o = this.options;
454            if (index != o.selected) { // cannot disable already selected tab
455                this.$lis.eq(index).addClass(o.disabledClass);
456
457                o.disabled.push(index);
458                o.disabled.sort();
459
460                // callback
461                $(this.element).triggerHandler('tabsdisable',
462                    [this.ui(this.$tabs[index], this.$panels[index])], o.disable
463                );
464            }
465        },
466        select: function(index) {
467            if (typeof index == 'string')
468                index = this.$tabs.index( this.$tabs.filter('[href$=' + index + ']')[0] );
469            this.$tabs.eq(index).trigger(this.options.event);
470        },
471        load: function(index, callback) { // callback is for internal usage only
472            
473            var self = this, o = this.options, $a = this.$tabs.eq(index), a = $a[0],
474                    bypassCache = callback == undefined || callback === false, url = $a.data('load.tabs');
475
476            callback = callback || function() {};
477            
478            // no remote or from cache - just finish with callback
479            if (!url || ($.data(a, 'cache.tabs') && !bypassCache)) {
480                callback();
481                return;
482            }
483
484            // load remote from here on
485            if (o.spinner) {
486                var $span = $('span', a);
487                $span.data('label.tabs', $span.html()).html('<em>' + o.spinner + '</em>');
488            }
489            var finish = function() {
490                self.$tabs.filter('.' + o.loadingClass).each(function() {
491                    $(this).removeClass(o.loadingClass);
492                    if (o.spinner) {
493                        var $span = $('span', this);
494                        $span.html($span.data('label.tabs')).removeData('label.tabs');
495                    }
496                });
497                self.xhr = null;
498            };
499            var ajaxOptions = $.extend({}, o.ajaxOptions, {
500                url: url,
501                success: function(r, s) {
502                    $(a.hash).html(r);
503                    finish();
504                    
505                    // This callback is required because the switch has to take
506                    // place after loading has completed.
507                    callback();
508
509                    if (o.cache)
510                        $.data(a, 'cache.tabs', true); // if loaded once do not load them again
511
512                    // callback
513                    $(self.element).triggerHandler('tabsload',
514                        [self.ui(self.$tabs[index], self.$panels[index])], o.load
515                    );
516
517                    o.ajaxOptions.success && o.ajaxOptions.success(r, s);
518                }
519            });
520            if (this.xhr) {
521                // terminate pending requests from other tabs and restore tab label
522                this.xhr.abort();
523                finish();
524            }
525            $a.addClass(o.loadingClass);
526            setTimeout(function() { // timeout is again required in IE, "wait" for id being restored
527                self.xhr = $.ajax(ajaxOptions);
528            }, 0);
529
530        },
531        url: function(index, url) {
532            this.$tabs.eq(index).removeData('cache.tabs').data('load.tabs', url);
533        },
534        destroy: function() {
535            var o = this.options;
536            $(this.element).unbind('.tabs')
537                .removeClass(o.navClass).removeData('tabs');
538            this.$tabs.each(function() {
539                var href = $.data(this, 'href.tabs');
540                if (href)
541                    this.href = href;
542                var $this = $(this).unbind('.tabs');
543                $.each(['href', 'load', 'cache'], function(i, prefix) {
544                      $this.removeData(prefix + '.tabs');
545                });
546            });
547            this.$lis.add(this.$panels).each(function() {
548                if ($.data(this, 'destroy.tabs'))
549                    $(this).remove();
550                else
551                    $(this).removeClass([o.selectedClass, o.unselectClass,
552                        o.disabledClass, o.panelClass, o.hideClass].join(' '));
553            });
554        }
555    });
556
557})(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.