Skip to main content

Search and Top Navigation

#8851 closed bug (duplicate)

Opened November 24, 2012 01:01PM UTC

Closed November 26, 2012 02:22AM UTC

Last modified March 31, 2015 08:51PM UTC

Tabs widget fails on inline tabs if invoking URL contains a query string

Reported by: savvyaviator Owned by: savvyaviator
Priority: minor Milestone: 1.10.0
Component: ui.tabs Version: 1.9.2
Keywords: Cc:
Blocked by: Blocking:
Description

Serious bug introduced starting in jQuery UI 1.9.0 that causes the tabs widget to fail on inline tabs if the invoking URL contains a query string ("?xxx"). This is a crippling problem for content management systems like Joomla! where many URLs contain query strings. The problem did not exist with jQuery UI 1.8.

The problem is the function isLocal( anchor ) which attempts to test whether the anchor is local (inline tab) or non-local (remote ajax tab). If the invoking URL (window.location) contains a query string, isLocal always returns false even if the tested anchor is actually local (e.g., "#panel-1").

The buggy code is:

var rhash = /#.*$/;
function isLocal( anchor ) {
	return anchor.hash.length > 1 &&
	anchor.href.replace( rhash, "" ) === location.href.replace( rhash, "" );
}

One way to fix it might be:

var rhash = /#.*$/;
var rquery = /\\?[^#]*/;
function isLocal( anchor ) {
	return anchor.hash.length > 1 &&
	anchor.href.replace( rhash, "" ) === 
		location.href.replace( rquery, "" ).replace( rhash, "" );
}

Another possibility (that I think is more elegant) is:

function isLocal( anchor ) {
	return anchor.hash.length > 1 &&
	anchor.host === location.host &&
	anchor.pathname === location.pathname;
}
Attachments (0)
Change History (11)

Changed November 24, 2012 11:11PM UTC by tj.vantoll comment:1

owner: → savvyaviator
status: newpending

@savvyaviator Thanks for taking the time to contribute to the jQuery UI project! There have been changes to that function since 1.9 originally came out, specifically - https://github.com/jquery/jquery-ui/commit/c6b52db892703ba14153800dbf620db509acb9e6#ui/jquery.ui.tabs.js.

Can you check whether this is still an issue with jQuery in master? You can use http://code.jquery.com/ui/jquery-ui-git.css and http://code.jquery.com/ui/jquery-ui-git.js to test with.

Thanks.

Changed November 25, 2012 12:42AM UTC by scottgonzalez comment:2

This is working correctly. If you have two URLs with the same path, but different query strings, then they point to two different resources. Can you please provide an example of what you think is behaving incorrectly?

Changed November 25, 2012 05:39PM UTC by savvyaviator comment:3

status: pendingnew

Replying to [comment:2 scott.gonzalez]:

This is working correctly. If you have two URLs with the same path, but different query strings, then they point to two different resources. Can you please provide an example of what you think is behaving incorrectly?

It is NOT working correctly in the latest distribution release 1.9.2.

If the URL that invokes the page containing the tabs widget has ANY query string (even a zero-length one, just a terminating "?") and the tabs are inline (i.e., <li><a href="#xxxx">Tab Label</a></li>), then the isLocal(anchor) function returns false instead of true and the tabs widget tries to treat the anchor as a non-local pane and performs an ajax load.

I have verified this failure with both Chrome and Firefox using jQuery UI 1.9.0, 1.9.1 and 1.9.2. I have also verified that both of the code revisions to the isLocal() function that I outlined above resolve it.

I have not yet tried the version from github, but will do so and report back.

The problem is apparently caused by the fact that when the browser tries to absolutize a relative URL like "#xxxx" it prepends the invoking host and path but NOT any invoking query string. In other words, if the invoking URL is:

https://www.foo.com/yabba/dabba/doo?alpha=bravo

then the relative URL "#xxxx" is resolved to

https://www.foo.com/yabba/dabba/doo#xxxx

and the current isLocal() code (which trims the #xxxx but not the ?alpha=bravo) gets an unequal compare and concludes incorrectly that #xxxx is non-local.

--Mike Busch

Changed November 25, 2012 06:36PM UTC by scottgonzalez comment:4

status: newpending

I'm not seeing this behavior. For example, if I go to http://view.jqueryui.com/master/demos/tabs/default.html?query=test the tabs work properly. I need to see a reduced page that shows the problem.

Changed November 25, 2012 07:00PM UTC by savvyaviator comment:5

status: pendingnew

Replying to [comment:4 scott.gonzalez]:

I'm not seeing this behavior. For example, if I go to http://view.jqueryui.com/master/demos/tabs/default.html?query=test the tabs work properly. I need to see a reduced page that shows the problem.

I'm getting the same result as you are on that page, so I will need to investigate further and report back.

The problems I am seeing occur on a Joomla!-based website. I will try to generate a non-Joomla!-based test case that illustrates the problem if I can.

Changed November 26, 2012 01:46AM UTC by savvyaviator comment:6

_comment0: Replying to [comment:4 scott.gonzalez]: \ > I'm not seeing this behavior. For example, if I go to http://view.jqueryui.com/master/demos/tabs/default.html?query=test the tabs work properly. I need to see a reduced page that shows the problem. \ \ '''Okay, Scott, I have it isolated now into three minimal test cases that clearly demonstrate the issue.''' \ \ [https://www.savvyanalysis.com/test/test1.html?query=test] works fine. This is identical to the tabs widget demo you cited, except that I moved it to my server and linked to jQuery 1.8.3 and jQueryUI 1.9.1 from the Google CDN. \ \ [https://www.savvyanalysis.com/test/test2.html?query=test] demonstrates the failure. It is identical to the first case with one exception: the head section of the HTML page contains one additional HTML element: \ \ {{{ \ <base href="https://www.savvyanalysis.com/test/test2.html"> \ }}} \ \ You'll notice that this page works fine so long as you leave off the query string in the invoking URL, but it fails if you include the query string. \ \ '''Please note that Joomla! (the world's most widely used content management system on the web) generates this <BASE...> element on every page, and its href attribute properly includes the host and path of the invoking URL, but EXCLUDES any ?querystring or #fragmentid that may be included in the invoking URL.''' That's why this bug is urgent in my opinion. I do not know whether other popular CMS such as Drupal or Wordpress generate such <BASE...> elements on their pages, but that's certainly possible. \ \ [https://www.savvyanalysis.com/test/test3.html?query=test] shows a work-around that I have come up with until this bug in the jQueryUI tabs widget is fixed. It is identical to the second case, but with a Javascript hack included prior to invoking the $('#tabs').tabs() statement that looks for a <BASE> element in the DOM and (if there is one) resets its href to agree with the invoking URL (including any ?querystring or #fragmentid). The workaround reads as follows: \ \ {{{ \ <head> \ ... \ <script> \ $(function() { \ baseElements = document.getElementsByTagName("base"); \ if( baseElements.length>0 ) { \ baseElements[0].href = document.location.href; \ } \ $( "#tabs" ).tabs(); \ }); \ </script> \ </head> \ }}} \ \ Yuck! \ \ '''In my opinion, this really needs to be fixed in jQueryUI 1.9.x.''' It was not a problem in jQueryUI 1.8.24 and earlier. I will temporarily incorporate the ugly workaround hack in my Joomla!-generated web pages to circumvent the issue until it is (hopefully) corrected in the jQueryUI library. \ \ Thanks in advance. --Mike1353894796546027

Replying to [comment:4 scott.gonzalez]:

I'm not seeing this behavior. For example, if I go to http://view.jqueryui.com/master/demos/tabs/default.html?query=test the tabs work properly. I need to see a reduced page that shows the problem.

Okay, Scott, I have it isolated now into three minimal test cases that clearly demonstrate the issue.

https://www.savvyanalysis.com/test/test1.html?query=test works fine. This is identical to the tabs widget demo you cited, except that I moved it to my server and linked to jQuery 1.8.3 and jQueryUI 1.9.1 from the Google CDN.

https://www.savvyanalysis.com/test/test2.html?query=test demonstrates the failure. It is identical to the first case with one exception: the head section of the HTML page contains one additional HTML element:

<base href="https://www.savvyanalysis.com/test/test2.html">

You'll notice that this page works fine so long as you leave off the query string in the invoking URL, but it fails if you include the query string.

'''Please note that Joomla! (the world's most widely used content management system on the web) generates this <BASE...> element on every page, and its href attribute properly includes the host and path of the invoking URL, but EXCLUDES any ?querystring or #fragmentid that may be included in the invoking URL.''' That's why this bug is urgent in my opinion. I do not know whether other popular CMS such as Drupal or Wordpress generate such <BASE...> elements on their pages, but that's certainly possible.

https://www.savvyanalysis.com/test/test3.html?query=test shows a work-around that I have come up with until this bug in the jQueryUI tabs widget is fixed. It is identical to the second case, but with a Javascript hack included prior to invoking the $('#tabs').tabs() statement that looks for a <BASE> element in the DOM and (if there is one) resets its href to agree with the invoking URL (including any ?querystring or #fragmentid). The workaround reads as follows:

<head>
...
<script>
$(function() {
    var baseElements = document.getElementsByTagName("base");
    if( baseElements.length>0 ) {
        baseElements[0].href = document.location.href;
    }
    $( "#tabs" ).tabs();
});
</script>
</head>

Yuck!

In my opinion, this really needs to be fixed in jQueryUI 1.9.x. It was not a problem in jQueryUI 1.8.24 and earlier. I will temporarily incorporate the ugly workaround hack in my Joomla!-generated web pages to circumvent the issue until it is (hopefully) corrected in the jQueryUI library.

Thanks in advance. --Mike

Changed November 26, 2012 02:22AM UTC by scottgonzalez comment:7

resolution: → duplicate
status: newclosed

Duplicate of #7822.Here we go again...

This is not a bug. This is correct behavior, because <base> is changing your #tabs-1 into https://www.savvyanalysis.com/test/test2.html#tabs-1 and not https://www.savvyanalysis.com/test/test2.html?query=test#tabs-1. Therefore, the link is no longer pointing to the same page.

Changed November 26, 2012 02:43AM UTC by mikesherov comment:8

I'm just going to leave this here: https://github.com/joomla/joomla-cms/pull/189

Changed January 25, 2013 04:01PM UTC by philw comment:9

My version... if we have a URL with a query parameter which has a space in it, then jQueryUi 1.9.2 returns false for isLocal() for IE(6,7,8,9, and 10). For Chrome or Firefox it returns the correct value, which is true. If I change all the URL spaces for something else, jQueryUI gets it right for all browsers.

The work around for those of us with no "remote" tabs is to replace the isLocal function with something which simply returns true.

It may not be a defect to you, but it was to me, so I posted this here as it may help others when they have this problem.

Changed January 25, 2013 06:41PM UTC by scottgonzalez comment:10

@philw The space has nothing to do with this ticket. See #8896.

Changed March 31, 2015 08:51PM UTC by ricardovigatti comment:11

<script> $(function() { var baseElements = document.getElementsByTagName("base"); if( baseElements.length>0 ) { baseElements[0].href = document.location.href; } $( "#tabs" ).tabs(); }); </script>

This fix worked very well for me. Thank U. Also, I do not think this is a jQuery UI bug, but a bug in Joomla!