jQuery UI non ajax tab loading whole website into itself?
Asked Answered
A

7

22

Having a large problem with jQuery Tabs.

Im trying to load the tabs on my sites product page... When the page loads i see that tabs content for a second (standard html tabs not ajax) then suddenly my whole website loads inside the tab.

i am using the standard code from the jquery ui tabs demo page.

<div id="productTabs">
    <ul>
        <li><a href="#tabDescription">Description</a></li>
        <li><a href="#tabSpecs">Specifications</a></li>
        <li><a href="#tabReviews">Reviews</a></li>
        <li><a href="#tabDownloads">Downloads</a></li>
    </ul>
    <div id="tabDescription">test</div>
    <div id="tabSpecs">test</div>
    <div id="tabReviews">test</div>
    <div id="tabDownloads">Sorry, no downloads available for this product.</div>
</div>
<script type="text/javascript">jQuery(document).ready(function(){jQuery("#productTabs").tabs();});</script>

But, i have a lot of other javascript around the site, just wondering if anyone has seen this before.

Many thanks

Anytime answered 12/12, 2012 at 10:6 Comment(4)
your code seems perfect... are u making some other ajax call to this page??Cancan
Show other javascript around!Villareal
i have just finished an extensive test and it was the meta base tag that is causing this issue! i am using tabs on my homepage and they load fine... hoping someone can shed some light, thanks.Anytime
I had the same problem that wasn't related to the base tag. On my site the .htcaccess or perhaps caching tool had a rewrite that was rewriting the tabs like #tabSpecs as full urls - example/page/#tabSpecs. The solution was to use jQuery to remove the full url before calling .tabs() to initialize the tabs.Ahearn
T
30

You are right, it's the BASE meta tag. This is a problem you'll face with the latest version of jQuery UI (1.9), it worked with 1.8. There were lot of changes to the Tabs API, but nothing seemed to cause this problem until you check the jQuery source code.

  1. The BASE meta tag instructs the browser to transform the href attribute in the tabs (that you use as reference for the tabs content) from hash+id to a full URL (using your BASE tag value). That's the expected behavior.
  2. Previous versions of the Tabs UI would try hard to guess if the href was really remote or not, spliting the href tab value, then comparing it to the current URL AND to the BASE tag, then deciding if it was actually local.
  3. Latest version of jQuery doesn't check the BASE tag value.
  4. So, the latest version, when used with BASE meta tag, will try to load the tab content using Ajax, reloading themselves (or whatever is in the BASE URL).

This is what jQuery UI Tabs used in version 1.8.24:

    this.anchors.each(function( i, a ) {
      var href = $( a ).attr( "href" );
      // For dynamically created HTML that contains a hash as href IE < 8 expands
      // such href to the full page url with hash and then misinterprets tab as ajax.
      // Same consideration applies for an added tab with a fragment identifier
      // since a[href=#fragment-identifier] does unexpectedly not match.
      // Thus normalize href attribute...
      var hrefBase = href.split( "#" )[ 0 ],
        baseEl;
      if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
          ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
        href = a.hash;
        a.href = href;
      }

This is what jQuery UI Tabs uses in version 1.9.2:

    function isLocal( anchor ) {
      return anchor.hash.length > 1 &&
        anchor.href.replace( rhash, "" ) ===
          location.href.replace( rhash, "" )
            // support: Safari 5.1
            // Safari 5.1 doesn't encode spaces in window.location
            // but it does encode spaces from anchors (#8777)
            .replace( /\s/g, "%20" );
     }

The code is organized differently because of the extensive rewriting of the Tabs code, but you can get the idea (The $( "base" )[ 0 ] is the BASE meta tag value).

So far I haven't found any way to tell the tabs "this is local, don't use Ajax" using the normal tabs API. What I can offer you is what I did to quick fix it in the mean time (while I ask, recheck and maybe fill a bug report): a hack.

    function isLocal( anchor ) {
      return anchor.hash.length > 1 &&
        ( (anchor.href.replace( rhash, "" ) === location.href.replace( rhash, "" ).replace( /\s/g, "%20" )) ||
          (anchor.href.replace( rhash, "" ) === $( "base" )[ 0 ].href));
    }

This is the newer version plus the check done in the previous version.

In a non-minified copy of the latest jQuery UI, replace the isLocal function with that. Then minify the file. Replace the original version. Test.

It worked for me in Firefox (17.0.1) and Chromium (18.0.1025.168).

The disadvantage is that you cannot use a third-party copy (from a CDN). For me that is not a problem as most of my applications are used in intranets.

If anybody finds a better solution or is aware of how to do it without hacking the jQuery UI code, please let us know.

UPDATE: I found this bug report (with several duplicates): http://bugs.jqueryui.com/ticket/7822 I was tempted to add my own comment but it seems the jQuery developers won't "fix" this as they consider the problem is elsewhere. Quote from the bugtracker:

I don't see how this is non-trivial to fix...

Here's the trivial, dynamic PHP implementation: 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . '#foo'.

It's also fairly trivial to fix this in JavaScript, but I won't provide sample code because that is the wrong place to be fixing this and should be highly discouraged. The behavior of links are clearly defined and consistent across all browsers. There is absolutely no reason people should be using incorrect URLs and then hacking around them in JavaScript.

Finally, it's important to note that "fixing" this would mean breaking the correct behavior for everyone who uses properly. Keep in mind that this was fixed because people with proper URLs were running into the real bug that existed in the old code.

Textualist answered 31/12, 2012 at 15:51 Comment(2)
Thank you so much for the very clear explanation and work-around!Anytime
2015 and still not fixed??? people with proper URLs were running into the real bug that existed in the old code. I'm interested in knowing what the real bug was and how it affected people with proper URLs?Peltry
C
20

This is a simple workaround that works inside your .js, so you can use a third-party copy for jquery.ui.
Tested with Jquery UI 1.10.2.
Resolve base meta tag problem and also the problem with the optional trailing slash n url.

$("#mytabs UL LI A").each(function() {
    $(this).attr("href", location.href.toString()+$(this).attr("href"));
});
$("#mytabs").tabs();
Catenate answered 19/4, 2013 at 17:25 Comment(3)
@Ortix92 I believe Angelica Rosa is simply saying grab your tab links in your tab container and change their href attribute to match base href attribute. I like this approach better, clear and elegant.David
Ditto that this is a better approach - at some point I expect the jQuery guys will fix this bug and in the meantime I'd prefer to NOT mess with the core code.Heber
THAT has fixed it! THANK YOU so much!Gerstein
P
7

As @MV mentioned, the problem is that jquery is confusing the base tag on top of my webpage. So instead of editing the jQuery ui file witch is not in my options, I simply removed the base tag using jQuery like that

<script>
    jQuery(function() {
        jQuery('base').remove();
        jQuery( "#tabs" ).tabs();                   
    });
</script>

This seems to work for me since I don't mind removing the base tag temporary for the sake of tabs control on that specific page. But I was also thinking a solution in case one needs those definitions, like collecting those base tags into an array, removing them and then after executing the tabs() method, add them again which looks a bit st..id but should work if tabs() is not implementing any listener pattern. I haven't tried it and I wont yet. Anyway It looks like jQuery ui has a bug there indeed!

Planish answered 29/6, 2013 at 21:34 Comment(3)
if base tag exists due to good reason, this will break whole links, if exists relative links, with urls with several levels (/any/any, /any/, /any/any/any/, whole links will be relatives to url and not to base tag.Luckey
yes that would be a problem. I use this only when I don't need the base tags.Planish
/any/any/any/, whole links will be relatives to url that's not correct. /any/any will be relative to domain, any/any (notice the missing / in start) will be relative to current URL.Peltry
A
2

Angelica had the answer that worked for me. I used this in a requirejs file for any page with the class 'tabs' as the selector for the tabs.

jQuery(".tabs ul li a").each(function() {
    jQuery(this).attr("href", location.href.toString()+jQuery(this).attr("href"));
});
jQuery(".tabs").tabs();
Ashbey answered 16/2, 2015 at 23:55 Comment(0)
T
1

My Conclusion

var base=$('base').clone(true);

$("#selector").dialog({
    open: function( event, ui ) {
        $('base').remove(); //Delete the Basepath to solve the Problem by loading Content
        $('#tabs').tabs();//Create the Tabs   
    }
    close: function( event, ui ) {base.insertAfter("head");
});

Maybe look at this it can be very helpfull to remove the basepath, than create your tabs(), and when your works with tabs are finished you have to append back to head

Tinytinya answered 7/2, 2014 at 8:18 Comment(0)
H
1

Messing with base attribute just to make tabs working. It's too much

Another hacky workaround:

element.tabs({
  create: function(event, ui){
    var tabsData = $(event.target).data('ui-tabs');
    tabsData.anchors.each(function(idx, anchor){
      var contentId = $(anchor).attr('href');
      var $panel = $(tabsData.panels[idx]);
      $panel.html($(contentId).remove().html());
    });
  },
  beforeLoad: function(event, ui){
    event.preventDefault();
  }
});

tested with jQuery UI - v1.11.1

Hurty answered 14/10, 2014 at 11:18 Comment(0)
C
0

I am in no way JS programmer, more C++/C# on Windows, reached this post while helping a relative with his web site on Joomla, where he had a similar problem, but thanks to MVlink to bug item the solution is simple. Bottom line - you can't use "local" href= , so .. don't use them , for example for page mypage.html on server http://www.example.com the code instead of original:

<div id="productTabs">
    <ul>
        <li><a href="#tabDescription">Description</a></li>
        <li><a href="#tabSpecs">Specifications</a></li>
        <li><a href="#tabReviews">Reviews</a></li>
        <li><a href="#tabDownloads">Downloads</a></li>
    </ul>
    <div id="tabDescription">test</div>
    <div id="tabSpecs">test</div>
    <div id="tabReviews">test</div>
    <div id="tabDownloads">Sorry, no downloads available for this product.</div>
</div>

You should use:

<div id="productTabs">
    <ul>
        <li><a href="http://www.example.com/mypage.html#tabDescription">Description</a></li>
        <li><a href="http://www.example.com/mypage.html#tabSpecs">Specifications</a></li>
        <li><a href="http://www.example.com/mypage.html#tabReviews">Reviews</a></li>
        <li><a href="http://www.example.com/mypage.html#tabDownloads">Downloads</a></li>
    </ul>
    <div id="tabDescription">test</div>
    <div id="tabSpecs">test</div>
    <div id="tabReviews">test</div>
    <div id="tabDownloads">Sorry, no downloads available for this product.</div>
</div>

And everything will work just fine. Of course if you use some code generation , like PHP in Joomla it becomes even easier to put for example() echo JUri::getInstance() . '#tab<Name>' in code generation

Caducity answered 16/3, 2019 at 19:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.