~jstys-z/helioviewer.org/timeline

« back to all changes in this revision

Viewing changes to lib/jquery/jquery.ui-1.7.1/development-bundle/ui/ui.tabs.js

  • Committer: V. Keith Hughitt
  • Date: 2009-03-26 19:20:57 UTC
  • Revision ID: hughitt1@kore-20090326192057-u0x8rf8sf5lmmnwh
nightly build 03-26-2009: Using alpha-channel JPEG 2000 dataset

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * jQuery UI Tabs 1.7.1
 
3
 *
 
4
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 
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
 * Depends:
 
11
 *      ui.core.js
 
12
 */
 
13
(function($) {
 
14
 
 
15
$.widget("ui.tabs", {
 
16
 
 
17
        _init: function() {
 
18
                if (this.options.deselectable !== undefined) {
 
19
                        this.options.collapsible = this.options.deselectable;
 
20
                }
 
21
                this._tabify(true);
 
22
        },
 
23
 
 
24
        _setData: function(key, value) {
 
25
                if (key == 'selected') {
 
26
                        if (this.options.collapsible && value == this.options.selected) {
 
27
                                return;
 
28
                        }
 
29
                        this.select(value);
 
30
                }
 
31
                else {
 
32
                        this.options[key] = value;
 
33
                        if (key == 'deselectable') {
 
34
                                this.options.collapsible = value;
 
35
                        }
 
36
                        this._tabify();
 
37
                }
 
38
        },
 
39
 
 
40
        _tabId: function(a) {
 
41
                return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '') ||
 
42
                        this.options.idPrefix + $.data(a);
 
43
        },
 
44
 
 
45
        _sanitizeSelector: function(hash) {
 
46
                return hash.replace(/:/g, '\\:'); // we need this because an id may contain a ":"
 
47
        },
 
48
 
 
49
        _cookie: function() {
 
50
                var cookie = this.cookie || (this.cookie = this.options.cookie.name || 'ui-tabs-' + $.data(this.list[0]));
 
51
                return $.cookie.apply(null, [cookie].concat($.makeArray(arguments)));
 
52
        },
 
53
 
 
54
        _ui: function(tab, panel) {
 
55
                return {
 
56
                        tab: tab,
 
57
                        panel: panel,
 
58
                        index: this.anchors.index(tab)
 
59
                };
 
60
        },
 
61
 
 
62
        _cleanup: function() {
 
63
                // restore all former loading tabs labels
 
64
                this.lis.filter('.ui-state-processing').removeClass('ui-state-processing')
 
65
                                .find('span:data(label.tabs)')
 
66
                                .each(function() {
 
67
                                        var el = $(this);
 
68
                                        el.html(el.data('label.tabs')).removeData('label.tabs');
 
69
                                });
 
70
        },
 
71
 
 
72
        _tabify: function(init) {
 
73
 
 
74
                this.list = this.element.children('ul:first');
 
75
                this.lis = $('li:has(a[href])', this.list);
 
76
                this.anchors = this.lis.map(function() { return $('a', this)[0]; });
 
77
                this.panels = $([]);
 
78
 
 
79
                var self = this, o = this.options;
 
80
 
 
81
                var fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
 
82
                this.anchors.each(function(i, a) {
 
83
                        var href = $(a).attr('href');
 
84
 
 
85
                        // For dynamically created HTML that contains a hash as href IE < 8 expands
 
86
                        // such href to the full page url with hash and then misinterprets tab as ajax.
 
87
                        // Same consideration applies for an added tab with a fragment identifier
 
88
                        // since a[href=#fragment-identifier] does unexpectedly not match.
 
89
                        // Thus normalize href attribute...
 
90
                        var hrefBase = href.split('#')[0], baseEl;
 
91
                        if (hrefBase && (hrefBase === location.toString().split('#')[0] ||
 
92
                                        (baseEl = $('base')[0]) && hrefBase === baseEl.href)) {
 
93
                                href = a.hash;
 
94
                                a.href = href;
 
95
                        }
 
96
 
 
97
                        // inline tab
 
98
                        if (fragmentId.test(href)) {
 
99
                                self.panels = self.panels.add(self._sanitizeSelector(href));
 
100
                        }
 
101
 
 
102
                        // remote tab
 
103
                        else if (href != '#') { // prevent loading the page itself if href is just "#"
 
104
                                $.data(a, 'href.tabs', href); // required for restore on destroy
 
105
 
 
106
                                // TODO until #3808 is fixed strip fragment identifier from url
 
107
                                // (IE fails to load from such url)
 
108
                                $.data(a, 'load.tabs', href.replace(/#.*$/, '')); // mutable data
 
109
 
 
110
                                var id = self._tabId(a);
 
111
                                a.href = '#' + id;
 
112
                                var $panel = $('#' + id);
 
113
                                if (!$panel.length) {
 
114
                                        $panel = $(o.panelTemplate).attr('id', id).addClass('ui-tabs-panel ui-widget-content ui-corner-bottom')
 
115
                                                .insertAfter(self.panels[i - 1] || self.list);
 
116
                                        $panel.data('destroy.tabs', true);
 
117
                                }
 
118
                                self.panels = self.panels.add($panel);
 
119
                        }
 
120
 
 
121
                        // invalid tab href
 
122
                        else {
 
123
                                o.disabled.push(i);
 
124
                        }
 
125
                });
 
126
 
 
127
                // initialization from scratch
 
128
                if (init) {
 
129
 
 
130
                        // attach necessary classes for styling
 
131
                        this.element.addClass('ui-tabs ui-widget ui-widget-content ui-corner-all');
 
132
                        this.list.addClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');
 
133
                        this.lis.addClass('ui-state-default ui-corner-top');
 
134
                        this.panels.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom');
 
135
 
 
136
                        // Selected tab
 
137
                        // use "selected" option or try to retrieve:
 
138
                        // 1. from fragment identifier in url
 
139
                        // 2. from cookie
 
140
                        // 3. from selected class attribute on <li>
 
141
                        if (o.selected === undefined) {
 
142
                                if (location.hash) {
 
143
                                        this.anchors.each(function(i, a) {
 
144
                                                if (a.hash == location.hash) {
 
145
                                                        o.selected = i;
 
146
                                                        return false; // break
 
147
                                                }
 
148
                                        });
 
149
                                }
 
150
                                if (typeof o.selected != 'number' && o.cookie) {
 
151
                                        o.selected = parseInt(self._cookie(), 10);
 
152
                                }
 
153
                                if (typeof o.selected != 'number' && this.lis.filter('.ui-tabs-selected').length) {
 
154
                                        o.selected = this.lis.index(this.lis.filter('.ui-tabs-selected'));
 
155
                                }
 
156
                                o.selected = o.selected || 0;
 
157
                        }
 
158
                        else if (o.selected === null) { // usage of null is deprecated, TODO remove in next release
 
159
                                o.selected = -1;
 
160
                        }
 
161
 
 
162
                        // sanity check - default to first tab...
 
163
                        o.selected = ((o.selected >= 0 && this.anchors[o.selected]) || o.selected < 0) ? o.selected : 0;
 
164
 
 
165
                        // Take disabling tabs via class attribute from HTML
 
166
                        // into account and update option properly.
 
167
                        // A selected tab cannot become disabled.
 
168
                        o.disabled = $.unique(o.disabled.concat(
 
169
                                $.map(this.lis.filter('.ui-state-disabled'),
 
170
                                        function(n, i) { return self.lis.index(n); } )
 
171
                        )).sort();
 
172
 
 
173
                        if ($.inArray(o.selected, o.disabled) != -1) {
 
174
                                o.disabled.splice($.inArray(o.selected, o.disabled), 1);
 
175
                        }
 
176
 
 
177
                        // highlight selected tab
 
178
                        this.panels.addClass('ui-tabs-hide');
 
179
                        this.lis.removeClass('ui-tabs-selected ui-state-active');
 
180
                        if (o.selected >= 0 && this.anchors.length) { // check for length avoids error when initializing empty list
 
181
                                this.panels.eq(o.selected).removeClass('ui-tabs-hide');
 
182
                                this.lis.eq(o.selected).addClass('ui-tabs-selected ui-state-active');
 
183
 
 
184
                                // seems to be expected behavior that the show callback is fired
 
185
                                self.element.queue("tabs", function() {
 
186
                                        self._trigger('show', null, self._ui(self.anchors[o.selected], self.panels[o.selected]));
 
187
                                });
 
188
                                
 
189
                                this.load(o.selected);
 
190
                        }
 
191
 
 
192
                        // clean up to avoid memory leaks in certain versions of IE 6
 
193
                        $(window).bind('unload', function() {
 
194
                                self.lis.add(self.anchors).unbind('.tabs');
 
195
                                self.lis = self.anchors = self.panels = null;
 
196
                        });
 
197
 
 
198
                }
 
199
                // update selected after add/remove
 
200
                else {
 
201
                        o.selected = this.lis.index(this.lis.filter('.ui-tabs-selected'));
 
202
                }
 
203
 
 
204
                // update collapsible
 
205
                this.element[o.collapsible ? 'addClass' : 'removeClass']('ui-tabs-collapsible');
 
206
 
 
207
                // set or update cookie after init and add/remove respectively
 
208
                if (o.cookie) {
 
209
                        this._cookie(o.selected, o.cookie);
 
210
                }
 
211
 
 
212
                // disable tabs
 
213
                for (var i = 0, li; (li = this.lis[i]); i++) {
 
214
                        $(li)[$.inArray(i, o.disabled) != -1 &&
 
215
                                !$(li).hasClass('ui-tabs-selected') ? 'addClass' : 'removeClass']('ui-state-disabled');
 
216
                }
 
217
 
 
218
                // reset cache if switching from cached to not cached
 
219
                if (o.cache === false) {
 
220
                        this.anchors.removeData('cache.tabs');
 
221
                }
 
222
 
 
223
                // remove all handlers before, tabify may run on existing tabs after add or option change
 
224
                this.lis.add(this.anchors).unbind('.tabs');
 
225
 
 
226
                if (o.event != 'mouseover') {
 
227
                        var addState = function(state, el) {
 
228
                                if (el.is(':not(.ui-state-disabled)')) {
 
229
                                        el.addClass('ui-state-' + state);
 
230
                                }
 
231
                        };
 
232
                        var removeState = function(state, el) {
 
233
                                el.removeClass('ui-state-' + state);
 
234
                        };
 
235
                        this.lis.bind('mouseover.tabs', function() {
 
236
                                addState('hover', $(this));
 
237
                        });
 
238
                        this.lis.bind('mouseout.tabs', function() {
 
239
                                removeState('hover', $(this));
 
240
                        });
 
241
                        this.anchors.bind('focus.tabs', function() {
 
242
                                addState('focus', $(this).closest('li'));
 
243
                        });
 
244
                        this.anchors.bind('blur.tabs', function() {
 
245
                                removeState('focus', $(this).closest('li'));
 
246
                        });
 
247
                }
 
248
 
 
249
                // set up animations
 
250
                var hideFx, showFx;
 
251
                if (o.fx) {
 
252
                        if ($.isArray(o.fx)) {
 
253
                                hideFx = o.fx[0];
 
254
                                showFx = o.fx[1];
 
255
                        }
 
256
                        else {
 
257
                                hideFx = showFx = o.fx;
 
258
                        }
 
259
                }
 
260
 
 
261
                // Reset certain styles left over from animation
 
262
                // and prevent IE's ClearType bug...
 
263
                function resetStyle($el, fx) {
 
264
                        $el.css({ display: '' });
 
265
                        if ($.browser.msie && fx.opacity) {
 
266
                                $el[0].style.removeAttribute('filter');
 
267
                        }
 
268
                }
 
269
 
 
270
                // Show a tab...
 
271
                var showTab = showFx ?
 
272
                        function(clicked, $show) {
 
273
                                $(clicked).closest('li').removeClass('ui-state-default').addClass('ui-tabs-selected ui-state-active');
 
274
                                $show.hide().removeClass('ui-tabs-hide') // avoid flicker that way
 
275
                                        .animate(showFx, showFx.duration || 'normal', function() {
 
276
                                                resetStyle($show, showFx);
 
277
                                                self._trigger('show', null, self._ui(clicked, $show[0]));
 
278
                                        });
 
279
                        } :
 
280
                        function(clicked, $show) {
 
281
                                $(clicked).closest('li').removeClass('ui-state-default').addClass('ui-tabs-selected ui-state-active');
 
282
                                $show.removeClass('ui-tabs-hide');
 
283
                                self._trigger('show', null, self._ui(clicked, $show[0]));
 
284
                        };
 
285
 
 
286
                // Hide a tab, $show is optional...
 
287
                var hideTab = hideFx ?
 
288
                        function(clicked, $hide) {
 
289
                                $hide.animate(hideFx, hideFx.duration || 'normal', function() {
 
290
                                        self.lis.removeClass('ui-tabs-selected ui-state-active').addClass('ui-state-default');
 
291
                                        $hide.addClass('ui-tabs-hide');
 
292
                                        resetStyle($hide, hideFx);
 
293
                                        self.element.dequeue("tabs");
 
294
                                });
 
295
                        } :
 
296
                        function(clicked, $hide, $show) {
 
297
                                self.lis.removeClass('ui-tabs-selected ui-state-active').addClass('ui-state-default');
 
298
                                $hide.addClass('ui-tabs-hide');
 
299
                                self.element.dequeue("tabs");
 
300
                        };
 
301
 
 
302
                // attach tab event handler, unbind to avoid duplicates from former tabifying...
 
303
                this.anchors.bind(o.event + '.tabs', function() {
 
304
                        var el = this, $li = $(this).closest('li'), $hide = self.panels.filter(':not(.ui-tabs-hide)'),
 
305
                                        $show = $(self._sanitizeSelector(this.hash));
 
306
 
 
307
                        // If tab is already selected and not collapsible or tab disabled or
 
308
                        // or is already loading or click callback returns false stop here.
 
309
                        // Check if click handler returns false last so that it is not executed
 
310
                        // for a disabled or loading tab!
 
311
                        if (($li.hasClass('ui-tabs-selected') && !o.collapsible) ||
 
312
                                $li.hasClass('ui-state-disabled') ||
 
313
                                $li.hasClass('ui-state-processing') ||
 
314
                                self._trigger('select', null, self._ui(this, $show[0])) === false) {
 
315
                                this.blur();
 
316
                                return false;
 
317
                        }
 
318
 
 
319
                        o.selected = self.anchors.index(this);
 
320
 
 
321
                        self.abort();
 
322
 
 
323
                        // if tab may be closed
 
324
                        if (o.collapsible) {
 
325
                                if ($li.hasClass('ui-tabs-selected')) {
 
326
                                        o.selected = -1;
 
327
 
 
328
                                        if (o.cookie) {
 
329
                                                self._cookie(o.selected, o.cookie);
 
330
                                        }
 
331
 
 
332
                                        self.element.queue("tabs", function() {
 
333
                                                hideTab(el, $hide);
 
334
                                        }).dequeue("tabs");
 
335
                                        
 
336
                                        this.blur();
 
337
                                        return false;
 
338
                                }
 
339
                                else if (!$hide.length) {
 
340
                                        if (o.cookie) {
 
341
                                                self._cookie(o.selected, o.cookie);
 
342
                                        }
 
343
                                        
 
344
                                        self.element.queue("tabs", function() {
 
345
                                                showTab(el, $show);
 
346
                                        });
 
347
 
 
348
                                        self.load(self.anchors.index(this)); // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
 
349
                                        
 
350
                                        this.blur();
 
351
                                        return false;
 
352
                                }
 
353
                        }
 
354
 
 
355
                        if (o.cookie) {
 
356
                                self._cookie(o.selected, o.cookie);
 
357
                        }
 
358
 
 
359
                        // show new tab
 
360
                        if ($show.length) {
 
361
                                if ($hide.length) {
 
362
                                        self.element.queue("tabs", function() {
 
363
                                                hideTab(el, $hide);
 
364
                                        });
 
365
                                }
 
366
                                self.element.queue("tabs", function() {
 
367
                                        showTab(el, $show);
 
368
                                });
 
369
                                
 
370
                                self.load(self.anchors.index(this));
 
371
                        }
 
372
                        else {
 
373
                                throw 'jQuery UI Tabs: Mismatching fragment identifier.';
 
374
                        }
 
375
 
 
376
                        // Prevent IE from keeping other link focussed when using the back button
 
377
                        // and remove dotted border from clicked link. This is controlled via CSS
 
378
                        // in modern browsers; blur() removes focus from address bar in Firefox
 
379
                        // which can become a usability and annoying problem with tabs('rotate').
 
380
                        if ($.browser.msie) {
 
381
                                this.blur();
 
382
                        }
 
383
 
 
384
                });
 
385
 
 
386
                // disable click in any case
 
387
                this.anchors.bind('click.tabs', function(){return false;});
 
388
 
 
389
        },
 
390
 
 
391
        destroy: function() {
 
392
                var o = this.options;
 
393
 
 
394
                this.abort();
 
395
                
 
396
                this.element.unbind('.tabs')
 
397
                        .removeClass('ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible')
 
398
                        .removeData('tabs');
 
399
 
 
400
                this.list.removeClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');
 
401
 
 
402
                this.anchors.each(function() {
 
403
                        var href = $.data(this, 'href.tabs');
 
404
                        if (href) {
 
405
                                this.href = href;
 
406
                        }
 
407
                        var $this = $(this).unbind('.tabs');
 
408
                        $.each(['href', 'load', 'cache'], function(i, prefix) {
 
409
                                $this.removeData(prefix + '.tabs');
 
410
                        });
 
411
                });
 
412
 
 
413
                this.lis.unbind('.tabs').add(this.panels).each(function() {
 
414
                        if ($.data(this, 'destroy.tabs')) {
 
415
                                $(this).remove();
 
416
                        }
 
417
                        else {
 
418
                                $(this).removeClass([
 
419
                                        'ui-state-default',
 
420
                                        'ui-corner-top',
 
421
                                        'ui-tabs-selected',
 
422
                                        'ui-state-active',
 
423
                                        'ui-state-hover',
 
424
                                        'ui-state-focus',
 
425
                                        'ui-state-disabled',
 
426
                                        'ui-tabs-panel',
 
427
                                        'ui-widget-content',
 
428
                                        'ui-corner-bottom',
 
429
                                        'ui-tabs-hide'
 
430
                                ].join(' '));
 
431
                        }
 
432
                });
 
433
 
 
434
                if (o.cookie) {
 
435
                        this._cookie(null, o.cookie);
 
436
                }
 
437
        },
 
438
 
 
439
        add: function(url, label, index) {
 
440
                if (index === undefined) {
 
441
                        index = this.anchors.length; // append by default
 
442
                }
 
443
 
 
444
                var self = this, o = this.options,
 
445
                        $li = $(o.tabTemplate.replace(/#\{href\}/g, url).replace(/#\{label\}/g, label)),
 
446
                        id = !url.indexOf('#') ? url.replace('#', '') : this._tabId($('a', $li)[0]);
 
447
 
 
448
                $li.addClass('ui-state-default ui-corner-top').data('destroy.tabs', true);
 
449
 
 
450
                // try to find an existing element before creating a new one
 
451
                var $panel = $('#' + id);
 
452
                if (!$panel.length) {
 
453
                        $panel = $(o.panelTemplate).attr('id', id).data('destroy.tabs', true);
 
454
                }
 
455
                $panel.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide');
 
456
 
 
457
                if (index >= this.lis.length) {
 
458
                        $li.appendTo(this.list);
 
459
                        $panel.appendTo(this.list[0].parentNode);
 
460
                }
 
461
                else {
 
462
                        $li.insertBefore(this.lis[index]);
 
463
                        $panel.insertBefore(this.panels[index]);
 
464
                }
 
465
 
 
466
                o.disabled = $.map(o.disabled,
 
467
                        function(n, i) { return n >= index ? ++n : n; });
 
468
 
 
469
                this._tabify();
 
470
 
 
471
                if (this.anchors.length == 1) { // after tabify
 
472
                        $li.addClass('ui-tabs-selected ui-state-active');
 
473
                        $panel.removeClass('ui-tabs-hide');
 
474
                        this.element.queue("tabs", function() {
 
475
                                self._trigger('show', null, self._ui(self.anchors[0], self.panels[0]));
 
476
                        });
 
477
                                
 
478
                        this.load(0);
 
479
                }
 
480
 
 
481
                // callback
 
482
                this._trigger('add', null, this._ui(this.anchors[index], this.panels[index]));
 
483
        },
 
484
 
 
485
        remove: function(index) {
 
486
                var o = this.options, $li = this.lis.eq(index).remove(),
 
487
                        $panel = this.panels.eq(index).remove();
 
488
 
 
489
                // If selected tab was removed focus tab to the right or
 
490
                // in case the last tab was removed the tab to the left.
 
491
                if ($li.hasClass('ui-tabs-selected') && this.anchors.length > 1) {
 
492
                        this.select(index + (index + 1 < this.anchors.length ? 1 : -1));
 
493
                }
 
494
 
 
495
                o.disabled = $.map($.grep(o.disabled, function(n, i) { return n != index; }),
 
496
                        function(n, i) { return n >= index ? --n : n; });
 
497
 
 
498
                this._tabify();
 
499
 
 
500
                // callback
 
501
                this._trigger('remove', null, this._ui($li.find('a')[0], $panel[0]));
 
502
        },
 
503
 
 
504
        enable: function(index) {
 
505
                var o = this.options;
 
506
                if ($.inArray(index, o.disabled) == -1) {
 
507
                        return;
 
508
                }
 
509
 
 
510
                this.lis.eq(index).removeClass('ui-state-disabled');
 
511
                o.disabled = $.grep(o.disabled, function(n, i) { return n != index; });
 
512
 
 
513
                // callback
 
514
                this._trigger('enable', null, this._ui(this.anchors[index], this.panels[index]));
 
515
        },
 
516
 
 
517
        disable: function(index) {
 
518
                var self = this, o = this.options;
 
519
                if (index != o.selected) { // cannot disable already selected tab
 
520
                        this.lis.eq(index).addClass('ui-state-disabled');
 
521
 
 
522
                        o.disabled.push(index);
 
523
                        o.disabled.sort();
 
524
 
 
525
                        // callback
 
526
                        this._trigger('disable', null, this._ui(this.anchors[index], this.panels[index]));
 
527
                }
 
528
        },
 
529
 
 
530
        select: function(index) {
 
531
                if (typeof index == 'string') {
 
532
                        index = this.anchors.index(this.anchors.filter('[href$=' + index + ']'));
 
533
                }
 
534
                else if (index === null) { // usage of null is deprecated, TODO remove in next release
 
535
                        index = -1;
 
536
                }
 
537
                if (index == -1 && this.options.collapsible) {
 
538
                        index = this.options.selected;
 
539
                }
 
540
 
 
541
                this.anchors.eq(index).trigger(this.options.event + '.tabs');
 
542
        },
 
543
 
 
544
        load: function(index) {
 
545
                var self = this, o = this.options, a = this.anchors.eq(index)[0], url = $.data(a, 'load.tabs');
 
546
 
 
547
                this.abort();
 
548
 
 
549
                // not remote or from cache
 
550
                if (!url || this.element.queue("tabs").length !== 0 && $.data(a, 'cache.tabs')) {
 
551
                        this.element.dequeue("tabs");
 
552
                        return;
 
553
                }
 
554
 
 
555
                // load remote from here on
 
556
                this.lis.eq(index).addClass('ui-state-processing');
 
557
 
 
558
                if (o.spinner) {
 
559
                        var span = $('span', a);
 
560
                        span.data('label.tabs', span.html()).html(o.spinner);
 
561
                }
 
562
 
 
563
                this.xhr = $.ajax($.extend({}, o.ajaxOptions, {
 
564
                        url: url,
 
565
                        success: function(r, s) {
 
566
                                $(self._sanitizeSelector(a.hash)).html(r);
 
567
 
 
568
                                // take care of tab labels
 
569
                                self._cleanup();
 
570
 
 
571
                                if (o.cache) {
 
572
                                        $.data(a, 'cache.tabs', true); // if loaded once do not load them again
 
573
                                }
 
574
 
 
575
                                // callbacks
 
576
                                self._trigger('load', null, self._ui(self.anchors[index], self.panels[index]));
 
577
                                try {
 
578
                                        o.ajaxOptions.success(r, s);
 
579
                                }
 
580
                                catch (e) {}
 
581
 
 
582
                                // last, so that load event is fired before show...
 
583
                                self.element.dequeue("tabs");
 
584
                        }
 
585
                }));
 
586
        },
 
587
 
 
588
        abort: function() {
 
589
                // stop possibly running animations
 
590
                this.element.queue([]);
 
591
                this.panels.stop(false, true);
 
592
 
 
593
                // terminate pending requests from other tabs
 
594
                if (this.xhr) {
 
595
                        this.xhr.abort();
 
596
                        delete this.xhr;
 
597
                }
 
598
 
 
599
                // take care of tab labels
 
600
                this._cleanup();
 
601
 
 
602
        },
 
603
 
 
604
        url: function(index, url) {
 
605
                this.anchors.eq(index).removeData('cache.tabs').data('load.tabs', url);
 
606
        },
 
607
 
 
608
        length: function() {
 
609
                return this.anchors.length;
 
610
        }
 
611
 
 
612
});
 
613
 
 
614
$.extend($.ui.tabs, {
 
615
        version: '1.7.1',
 
616
        getter: 'length',
 
617
        defaults: {
 
618
                ajaxOptions: null,
 
619
                cache: false,
 
620
                cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
 
621
                collapsible: false,
 
622
                disabled: [],
 
623
                event: 'click',
 
624
                fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
 
625
                idPrefix: 'ui-tabs-',
 
626
                panelTemplate: '<div></div>',
 
627
                spinner: '<em>Loading&#8230;</em>',
 
628
                tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>'
 
629
        }
 
630
});
 
631
 
 
632
/*
 
633
 * Tabs Extensions
 
634
 */
 
635
 
 
636
/*
 
637
 * Rotate
 
638
 */
 
639
$.extend($.ui.tabs.prototype, {
 
640
        rotation: null,
 
641
        rotate: function(ms, continuing) {
 
642
 
 
643
                var self = this, o = this.options;
 
644
                
 
645
                var rotate = self._rotate || (self._rotate = function(e) {
 
646
                        clearTimeout(self.rotation);
 
647
                        self.rotation = setTimeout(function() {
 
648
                                var t = o.selected;
 
649
                                self.select( ++t < self.anchors.length ? t : 0 );
 
650
                        }, ms);
 
651
                        
 
652
                        if (e) {
 
653
                                e.stopPropagation();
 
654
                        }
 
655
                });
 
656
                
 
657
                var stop = self._unrotate || (self._unrotate = !continuing ?
 
658
                        function(e) {
 
659
                                if (e.clientX) { // in case of a true click
 
660
                                        self.rotate(null);
 
661
                                }
 
662
                        } :
 
663
                        function(e) {
 
664
                                t = o.selected;
 
665
                                rotate();
 
666
                        });
 
667
 
 
668
                // start rotation
 
669
                if (ms) {
 
670
                        this.element.bind('tabsshow', rotate);
 
671
                        this.anchors.bind(o.event + '.tabs', stop);
 
672
                        rotate();
 
673
                }
 
674
                // stop rotation
 
675
                else {
 
676
                        clearTimeout(self.rotation);
 
677
                        this.element.unbind('tabsshow', rotate);
 
678
                        this.anchors.unbind(o.event + '.tabs', stop);
 
679
                        delete this._rotate;
 
680
                        delete this._unrotate;
 
681
                }
 
682
        }
 
683
});
 
684
 
 
685
})(jQuery);