Search and Top Navigation
#4451 closed bug (fixed)
Opened April 09, 2009 11:37PM UTC
Closed February 24, 2010 06:44PM UTC
AJAX tabs stop functioning properly after AJAX error callback is executed
Reported by: | JBeckton | Owned by: | jzaefferer |
---|---|---|---|
Priority: | critical | Milestone: | 1.8 |
Component: | ui.tabs | Version: | 1.7.1 |
Keywords: | Cc: | ||
Blocked by: | Blocking: |
Description
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" title="Exhibits">Exhibits</a></li> <li class="ui-state-default ui-corner-top"><a href="index.cfm? fuseaction=casemanager.checkwriter" title="Check Writer">Check Writer</ a></li> <li class="ui-state-default ui-corner-top"><a href="index.cfm? fuseaction=casemanager.comments" title="Comments">Comments</a></li> <li class="spinnerContainer"></li> </ul> <div id="Exhibits"></div> <div id="Check_Writer"></div> <div id="Comments"></div> </div>
$(function() { //builds the tab interface for viewing the submittal data $("#caseManagerWorkbench").tabs({ ajaxOptions: { async: false, cache: false, success: function() { $(".AJAXErrorContainer").hide(); }, error: function() { $(".AJAXErrorContainer").html("An error has occured during the remote request, Please try again."); $(".AJAXErrorContainer").show(); } }, 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)
Change History (10)
Changed May 07, 2009 11:12AM UTC by comment:1
description: | 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" \ title="Exhibits">Exhibits</a></li> \ <li class="ui-state-default ui-corner-top"><a href="index.cfm? \ fuseaction=casemanager.checkwriter" title="Check Writer">Check Writer</ \ a></li> \ <li class="ui-state-default ui-corner-top"><a href="index.cfm? \ fuseaction=casemanager.comments" title="Comments">Comments</a></li> \ <li class="spinnerContainer"></li> \ </ul> \ <div id="Exhibits"></div> \ <div id="Check_Writer"></div> \ <div id="Comments"></div> \ </div> \ \ JavaScript: \ $(function() { \ \ //builds the tab interface for viewing the submittal data \ $("#caseManagerWorkbench").tabs({ ajaxOptions: { \ async: false, \ cache: false, \ success: function() { \ $(".AJAXErrorContainer").hide(); \ }, \ error: function() { \ $(".AJAXErrorContainer").html("An error has occured \ during the remote request, Please try again."); \ $(".AJAXErrorContainer").show(); \ } \ }, \ 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("");} \ }); → 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" \ title="Exhibits">Exhibits</a></li> \ <li class="ui-state-default ui-corner-top"><a href="index.cfm? \ fuseaction=casemanager.checkwriter" title="Check Writer">Check Writer</ \ a></li> \ <li class="ui-state-default ui-corner-top"><a href="index.cfm? \ fuseaction=casemanager.comments" title="Comments">Comments</a></li> \ <li class="spinnerContainer"></li> \ </ul> \ <div id="Exhibits"></div> \ <div id="Check_Writer"></div> \ <div id="Comments"></div> \ </div> \ }}} \ JavaScript: \ {{{ \ $(function() { \ \ //builds the tab interface for viewing the submittal data \ $("#caseManagerWorkbench").tabs({ ajaxOptions: { \ async: false, \ cache: false, \ success: function() { \ $(".AJAXErrorContainer").hide(); \ }, \ error: function() { \ $(".AJAXErrorContainer").html("An error has occured \ during the remote request, Please try again."); \ $(".AJAXErrorContainer").show(); \ } \ }, \ 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("");} \ }); \ }}} |
---|---|
milestone: | TBD → 1.7.2 |
Changed May 07, 2009 01:38PM UTC by comment:2
milestone: | 1.7.2 → 1.8 |
---|
Changed May 11, 2009 01:04PM UTC by comment:3
Attached a patch to handle ajax errors. Currently the error message is hard coded.
Changed May 13, 2009 08:19PM UTC by comment:4
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
self.element.dequeue("tabs");
outside of the ajax callbacks and calling a new
displayPanelSpinnerfunction (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.
Changed May 14, 2009 12:07AM UTC by comment:5
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
loadfunction now looks like:
this.xhr = $.ajax($.extend({}, o.ajaxOptions, { url: url, success: function(r, s) { $(self._sanitizeSelector(a.hash)).html(r); // 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.anchors[index], self.panels[index])); try { o.ajaxOptions.success(r, s); } catch (e) {} } })); // last, so that load event is fired before show... self.element.dequeue("tabs"); return this; },
Changed December 07, 2009 09:01AM UTC by comment:6
Added [attachment:ticket:4451:jquery.ui.tabs.js-4451.patch patch] against [source:/trunk/ui/jquery.ui.tabs.js@3488 r3488] which merges [attachment:ticket:4451:ui.tabs.js-4451.patch 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
Changed December 08, 2009 07:22AM UTC by comment:7
Replying to [comment:6 andrew.sharpe.7.9]:
And also moves
self.element.dequeue("tabs");
out of the success callback as suggested by itfische.
Changed February 03, 2010 08:54AM UTC by comment:8
Patch tested by ogdoad8 http://forum.jquery.com/topic/ajax-tabs-bug-4451-patch-is-good
Changed February 24, 2010 05:45PM UTC by comment:9
owner: | → joern.zaefferer |
---|---|
status: | new → accepted |
Changed February 24, 2010 06:44PM UTC by comment:10
resolution: | → fixed |
---|---|
status: | accepted → closed |
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.