Opened 14 years ago

Closed 13 years ago

#4451 closed bug (fixed)

AJAX tabs stop functioning properly after AJAX error callback is executed

Reported by: JBeckton Owned by: Jörn Zaefferer
Priority: critical Milestone: 1.8
Component: ui.tabs Version: 1.7.1
Keywords: Cc:
Blocked by: Blocking:

Description (last modified by Jörn Zaefferer)

I have some UI Tabs set up using AJAX calls to populate the container, set it up as suggested on the jQuery UI site.

In my AJAX options I have a handler for error event. I purposely broke the remote page to test the error handling. When I click the tab that calls the remote page my error callback runs as expected but now when I try to select the other tabs they freak out! I either have to click on them twice or they may load each others content inside them at the same time. Very strange!

My application handles the error and returns the http status 500 so the AJAX will know it took a crap.

Here is my code. HTML:

<div class="AJAXErrorContainer" style="display:none"></div>
<div id="caseManagerWorkbench" class="ui-tabs ui-widget ui-widget-
content ui-corner-all">
        <ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-
header ui-corner-all">
                <li class="ui-state-default ui-corner-top ui-tabs-selected ui-state-
active"><a href="index.cfm?fuseaction=casemanager.exhibits"
        <li class="ui-state-default ui-corner-top"><a href="index.cfm?
fuseaction=casemanager.checkwriter" title="Check Writer">Check Writer</
                <li class="ui-state-default ui-corner-top"><a href="index.cfm?
fuseaction=casemanager.comments" title="Comments">Comments</a></li>
        <li class="spinnerContainer"></li>
    <div id="Exhibits"></div>
    <div id="Check_Writer"></div>
    <div id="Comments"></div>


$(function() {

        //builds the tab interface for viewing the submittal data
        $("#caseManagerWorkbench").tabs({ ajaxOptions: {
                                                                                                        async: false,
                                                                                                        cache: false,
                                                                                                        success: function() {
                                                                                                        error: function() {
                                                                                                                                                $(".AJAXErrorContainer").html("An error has occured
during the remote request, Please try again.");
                                                                                spinner: null,
                                                                                select: function() {$(".spinnerContainer").html("<span
style='color:white;'><img src='images/ajax-loader-blue.gif' hspace='5'
vspace='4' align='absmiddle'> Loading...</span>");},
                                                                                load: function() {$(".spinnerContainer").html("");}

Attachments (2)

ui.tabs.js-4451.patch (640 bytes) - added by Jörn Zaefferer 14 years ago.
jquery.ui.tabs.js-4451.patch (1007 bytes) - added by andrew.sharpe.7.9 13 years ago.

Download all attachments as: .zip

Change History (12)

comment:1 Changed 14 years ago by Jörn Zaefferer

Description: modified (diff)
Milestone: TBD1.7.2

comment:2 Changed 14 years ago by Jörn Zaefferer


Changed 14 years ago by Jörn Zaefferer

Attachment: ui.tabs.js-4451.patch added

comment:3 Changed 14 years ago by Jörn Zaefferer

Attached a patch to handle ajax errors. Currently the error message is hard coded.

comment:4 Changed 14 years ago by itfische

Similarly, if the ajax request takes a long time, the user may click on a different tab. This causes the same behavior described for the error case -- the slow-loading tab becomes selected when the user clicks the next tab, the content is not loaded (so you end up with a blank panel), and the tab clicks become off-by-one in the stack of clicks.

To illustrate, consider the case of three tabs. Tab 1 is the currently selected. Tab 2 is a slow-loading tab. Tab 3 loads in a reasonable time.

The user starts on Tab 1 with the content loaded. He then clicks on Tab 2, but Tab 1 is still indicated as selected, since Tab 2 hasn't loaded yet. He quickly gets tired of waiting, so he clicks on Tab 3 before Tab 2 has loaded. At this point, Tab 2 becomes the selected tab, but there is no content in it. If he then clicks on Tab 3 again to try to get it to load, it does, but it has either the content for Tab 1 at the top and the content for Tab 3 at the bottom, or it has the blank div for Tab 1's panel at the top and the content for Tab 3 at the bottom (this is easiest to see if there is a minimum height set on the panels).

If instead of clicking Tab 3 a second time he clicks on Tab 1, he gets the off-by-one error behavior. Tab 3 will become selected when he clicks on Tab 1 with the double-content problem described above. If he then clicks on Tab 1 again, he will have the content from both Tab 1 and Tab 3 visible.

Obviously there is a more fundamental bug in the tabs than what this ticket initially suggests. However, I think the core if the issue would probably be corrected if selecting a tab always immediately updated the UI and displayed a spinner in the newly-displayed tab panel.

Getting this behavior may be as simple as moving


outside of the ajax callbacks and calling a new displayPanelSpinner function (as well as adding a new option for a panelSpinner). However, I haven't tried that fix yet.

This error is easily replicated by setting up the the three tabs as described above with normal ajax tab settings and setting a two second sleep on the server side for one of the tabs' target urls. As mentioned above, it is important to set the panels to have a minimum height in the css to be able to see the panels loading improperly.

comment:5 Changed 14 years ago by itfische

I have verified that moving the self.element.dequeue("tabs"); line out of the success callback does fix the slow tab/fast user errors. Presumably the same would work well with the patch attached to this ticket for the ajax error callbacks.

The end of my load function now looks like:

		this.xhr = $.ajax($.extend({}, o.ajaxOptions, {
			url: url,
			success: function(r, s) {

				// take care of tab labels

				if (o.cache) {
					$.data(a, 'cache.tabs', true); // if loaded once do not load them again

				// callbacks
				self._trigger('load', null, self._ui(self.anchors[index], self.panels[index]));
				try {
					o.ajaxOptions.success(r, s);
				catch (e) {}

		// last, so that load event is fired before show...
		return this;

Changed 13 years ago by andrew.sharpe.7.9

comment:6 Changed 13 years ago by andrew.sharpe.7.9

Added patch against [source:/trunk/ui/[email protected] r3488] which merges joerns patch with the following changes

  • don't display an error message in the tab panel
  • pass extra information to the error handler
    • the index of the broken tab
    • the anchor that initiated the request

comment:7 in reply to:  6 Changed 13 years ago by andrew.sharpe.7.9

Replying to andrew.sharpe.7.9:

And also moves


out of the success callback as suggested by itfische.

comment:9 Changed 13 years ago by Jörn Zaefferer

Owner: set to joern.zaefferer
Status: newaccepted

comment:10 Changed 13 years ago by Jörn Zaefferer

Resolution: fixed
Status: acceptedclosed

Fixed in r3846. I removed the e-argument and changed it to call options.ajaxOptions.error to be consistent with options.ajaxOptions.success. Also extended the ajax demo to demo slow-loading and broken tabs.

Note: See TracTickets for help on using tickets.