]> source.dussan.org Git - jquery-ui.git/commitdiff
Tabs: solved spinner issues and ajax loading not being stopped when selecting a stati...
authorKlaus Hartl <klaus.hartl@googlemail.com>
Wed, 18 Feb 2009 21:44:34 +0000 (21:44 +0000)
committerKlaus Hartl <klaus.hartl@googlemail.com>
Wed, 18 Feb 2009 21:44:34 +0000 (21:44 +0000)
tests/unit/tabs/spinner.gif [new file with mode: 0644]
tests/unit/tabs/tabs.html
tests/unit/tabs/tabs_core.js
tests/unit/tabs/tabs_defaults.js
tests/unit/tabs/test.html [new file with mode: 0644]
themes/base/ui.tabs.css
ui/ui.tabs.js

diff --git a/tests/unit/tabs/spinner.gif b/tests/unit/tabs/spinner.gif
new file mode 100644 (file)
index 0000000..85b99d4
Binary files /dev/null and b/tests/unit/tabs/spinner.gif differ
index d9cb4d138f48c02b7d45ebc9af70bce0e1d8f752..69cd8f481a1f5991d21305daa551d6bd046788d5 100644 (file)
@@ -24,9 +24,9 @@
        <div id="main">
                <div id="tabs1">
                        <ul>
-                               <li><a href="#fragment-1">1</a></li>
-                               <li><a href="#fragment-2">2</a></li>
-                               <li><a href="#fragment-3">3</a></li>
+                               <li><a href="#fragment-1"><span>1</span></a></li>
+                               <li><a href="#fragment-2"><span>2</span></a></li>
+                               <li><a href="#fragment-3"><span>3</span></a></li>
                        </ul>
                        <div id="fragment-1"></div>
                        <div id="fragment-2"></div>
@@ -34,9 +34,9 @@
                </div>
                <div id="tabs2">
                        <ul>
-                               <li><a href="#colon:test">1</a></li>
-                               <li><a href="#inline-style">2</a></li>
-                               <li><a href="test.html#test">1</a></li>
+                               <li><a href="#colon:test"><span>1</span></a></li>
+                               <li><a href="#inline-style"><span>2</span></a></li>
+                               <li><a href="test.html#test"><span>3</span></a></li>
                        </ul>
                        <div id="colon:test"></div>
                        <div style="height: 300px;" id="inline-style"></div>
index ba5f3d014c69e805ca022bbd6aabb0c611d84d89..79e95ea4175dadb22a622bc6901c314405e0eac0 100644 (file)
@@ -7,4 +7,33 @@ var el;
 
 module("tabs: core");
 
+test('ajax', function() {
+       expect(4);
+       stop();
+       
+       el = $('#tabs2');
+       
+       el.tabs({
+               selected: 2,
+               load: function() {
+                       // spinner: default spinner
+                       equals($('li:eq(2) > a > span', el).length, 1, "should restore tab markup after spinner is removed");
+                       equals($('li:eq(2) > a > span', el).html(), '3', "should restore tab label after spinner is removed");
+                       el.tabs('destroy');
+                       el.tabs({
+                               selected: 2,
+                               spinner: '<img src="spinner.gif" alt="">',
+                               load: function() {
+                                       // spinner: image
+                                       equals($('li:eq(2) > a > span', el).length, 1, "should restore tab markup after spinner is removed");
+                                       equals($('li:eq(2) > a > span', el).html(), '3', "should restore tab label after spinner is removed");
+                                       start();
+                               }
+                       });                     
+               }
+       });
+       
+});
+       
+       
 })(jQuery);
index 306e8c86eea42431605214857099d9cabae83510..f5a583e2c3e9b6396fd44d4275dfb31dad77267c 100644 (file)
@@ -12,7 +12,7 @@ var tabs_defaults = {
        fx: null,
        idPrefix: 'ui-tabs-',
        panelTemplate: '<div></div>',
-       spinner: 'Loading&#8230;',
+       spinner: '<em>Loading&#8230;</em>',
        tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>'
 };
 
diff --git a/tests/unit/tabs/test.html b/tests/unit/tabs/test.html
new file mode 100644 (file)
index 0000000..cd59e64
--- /dev/null
@@ -0,0 +1 @@
+<p>&#8230;content loaded via Ajax.</p>
\ No newline at end of file
index ae67ad57ac4eb17fa4788e4bf5d77008f9a9147b..dcd51b04879f08631737c90b786b56c28de67c65 100644 (file)
@@ -5,7 +5,7 @@
 .ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; }
 .ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
 .ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: .1em; border-bottom-width: 0; }
-.ui-tabs .ui-tabs-nav li.ui-tabs-selected a { cursor: text; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
 .ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
 .ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; }
 .ui-tabs .ui-tabs-hide { display: none !important; }
index 3208d60b50e320d32f3b491f1009b49cc9309681..57ff72f94e87927d470b655ac61ce06367b83c01 100644 (file)
@@ -24,14 +24,14 @@ $.widget("ui.tabs", {
                if (key == 'selected') {
                        if (this.options.collapsible
                                && value == this.options.selected) return;
-                       
+
                        this.select(value);
                }
                else {
                        this.options[key] = value;
                        if (key == 'deselectable')
                                this.options.collapsible = value;
-                       
+
                        this._tabify();
                }
        },
@@ -58,6 +58,16 @@ $.widget("ui.tabs", {
                };
        },
 
+       _cleanup: function() {
+               // restore all former loading tabs labels
+               this.$lis.filter('.ui-state-processing').removeClass('ui-state-processing')
+                               .find('span:data(label.tabs)')
+                               .each(function() {
+                                       var el = $(this);
+                                       el.html(el.data('label.tabs'));
+                               });
+       },
+
        _tabify: function(init) {
 
                this.list = this.element.children('ul:first, ol:first').eq(0);
@@ -70,7 +80,7 @@ $.widget("ui.tabs", {
                var fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
                this.$tabs.each(function(i, a) {
                        var href = $(a).attr('href');
-                       
+
                        // For dynamically created HTML that contains a hash as href IE expands
                        // such href to the full page url with hash and then misinterprets tab as ajax...
                        if (href.split('#')[0] == location.toString().split('#')[0]) href = a.hash;
@@ -183,10 +193,10 @@ $.widget("ui.tabs", {
                else {
                        o.selected = this.$lis.index(this.$lis.filter('.ui-tabs-selected'));
                }
-               
+
                // update collapsible
                this.element[o.collapsible ? 'addClass' : 'removeClass']('ui-tabs-collapsible');
-               
+
                // set or update cookie after init and add/remove respectively
                if (o.cookie) this._cookie(o.selected, o.cookie);
 
@@ -199,7 +209,7 @@ $.widget("ui.tabs", {
 
                // remove all handlers before, tabify may run on existing tabs after add or option change
                this.$lis.add(this.$tabs).unbind('.tabs');
-               
+
                if (o.event != 'mouseover') {
                        var handleState = function(state, el) {
                                if (el.is(':not(.ui-state-disabled)')) el.toggleClass('ui-state-' + state);
@@ -211,7 +221,7 @@ $.widget("ui.tabs", {
                                handleState('focus', $(this).closest('li'));
                        });
                }
-               
+
                // set up animations
                var hideFx, showFx;
                if (o.fx) {
@@ -276,7 +286,7 @@ $.widget("ui.tabs", {
                        // for a disabled or loading tab!
                        if (($li.hasClass('ui-tabs-selected') && !o.collapsible)
                                || $li.hasClass('ui-state-disabled')
-                               || $(this).hasClass('ui-tabs-loading')
+                               || $li.hasClass('ui-state-processing')
                                || self._trigger('select', null, self._ui(this, $show[0])) === false
                                ) {
                                this.blur();
@@ -285,6 +295,8 @@ $.widget("ui.tabs", {
 
                        o.selected = self.$tabs.index(this);
 
+                       self.abort();
+
                        // if tab may be closed TODO avoid redundant code in this block
                        if (o.collapsible) {
                                if ($li.hasClass('ui-tabs-selected')) {
@@ -292,13 +304,11 @@ $.widget("ui.tabs", {
                                        if (o.cookie) self._cookie(o.selected, o.cookie);
                                        $li.removeClass('ui-tabs-selected ui-state-active')
                                                .addClass('ui-state-default');
-                                       self.$panels.stop();
                                        hideTab(this, $hide);
                                        this.blur();
                                        return false;
                                } else if (!$hide.length) {
                                        if (o.cookie) self._cookie(o.selected, o.cookie);
-                                       self.$panels.stop();
                                        var a = this;
                                        self.load(self.$tabs.index(this), function() {
                                                $li.addClass('ui-tabs-selected ui-state-active')
@@ -312,9 +322,6 @@ $.widget("ui.tabs", {
 
                        if (o.cookie) self._cookie(o.selected, o.cookie);
 
-                       // stop possibly running animations
-                       self.$panels.stop(false, true);
-
                        // show new tab
                        if ($show.length) {
                                var a = this;
@@ -327,8 +334,10 @@ $.widget("ui.tabs", {
                                                showTab(a, $show);
                                        }
                                );
-                       } else
+                       }
+                       else {
                                throw 'jQuery UI Tabs: Mismatching fragment identifier.';
+                       }
 
                        // Prevent IE from keeping other link focussed when using the back button
                        // and remove dotted border from clicked link. This is controlled via CSS
@@ -474,21 +483,23 @@ $.widget("ui.tabs", {
        select: function(index) {
                if (typeof index == 'string')
                        index = this.$tabs.index(this.$tabs.filter('[href$=' + index + ']'));
-                       
+
                else if (index === null)
                        index = -1;
 
                if (index == -1 && this.options.collapsible)
                        index = this.options.selected;
-                       
+
                this.$tabs.eq(index).trigger(this.options.event + '.tabs');
        },
 
        load: function(index, callback) { // callback is for internal usage only
                callback = callback || function() {};
-               
-               var self = this, o = this.options, $a = this.$tabs.eq(index), a = $a[0],
-                               bypassCache = callback == undefined, url = $a.data('load.tabs');
+
+               var self = this, o = this.options, a = this.$tabs.eq(index)[0],
+                               bypassCache = callback == undefined, url = $.data(a, 'load.tabs');
+
+               this.abort();
 
                // not remote or from cache - just finish with callback
                if (!url || !bypassCache && $.data(a, 'cache.tabs')) {
@@ -497,55 +508,53 @@ $.widget("ui.tabs", {
                }
 
                // load remote from here on
-
-               var inner = function(parent) {
-                       var $parent = $(parent), $inner = $parent.find('*:last');
-                       return $inner.length && $inner.is(':not(img)') && $inner || $parent;
-               };
-               var cleanup = function() {
-                       self.$tabs.filter('.ui-tabs-loading').removeClass('ui-tabs-loading')
-                                       .each(function() {
-                                               if (o.spinner)
-                                                       inner(this).parent().html(inner(this).data('label.tabs'));
-                                       });
-                       self.xhr = null;
-               };
+               this.$lis.eq(index).addClass('ui-state-processing');
 
                if (o.spinner) {
-                       var label = inner(a).html();
-                       inner(a).wrapInner('<em></em>')
-                               .find('em').data('label.tabs', label).html(o.spinner);
+                       var span = $('span', a);
+                       span.data('label.tabs', span.html()).html(o.spinner);
                }
 
-               var ajaxOptions = $.extend({}, o.ajaxOptions, {
+               this.xhr = $.ajax($.extend({}, o.ajaxOptions, {
                        url: url,
                        success: function(r, s) {
                                $(self._sanitizeSelector(a.hash)).html(r);
-                               cleanup();
 
-                               if (o.cache)
+                               // take care of tab labels
+                               self._cleanup();
+
+                               if (o.cache) {
                                        $.data(a, 'cache.tabs', true); // if loaded once do not load them again
+                               }
 
                                // callbacks
                                self._trigger('load', null, self._ui(self.$tabs[index], self.$panels[index]));
                                try {
                                        o.ajaxOptions.success(r, s);
                                }
-                               catch (er) {}
+                               catch (e) {}
 
                                // This callback is required because the switch has to take
                                // place after loading has completed. Call last in order to
                                // fire load before show callback...
                                callback();
                        }
-               });
+               }));
+       },
+
+       abort: function() {
+               // stop possibly running animations
+               this.$panels.stop(false, true);
+
+               // terminate pending requests from other tabs
                if (this.xhr) {
-                       // terminate pending requests from other tabs and restore tab label
                        this.xhr.abort();
-                       cleanup();
+                       delete this.xhr;
                }
-               $a.addClass('ui-tabs-loading');
-               self.xhr = $.ajax(ajaxOptions);
+
+               // take care of tab labels
+               this._cleanup();
+
        },
 
        url: function(index, url) {
@@ -571,7 +580,7 @@ $.extend($.ui.tabs, {
                fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
                idPrefix: 'ui-tabs-',
                panelTemplate: '<div></div>',
-               spinner: 'Loading&#8230;',
+               spinner: '<em>Loading&#8230;</em>',
                tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>'
        }
 });