Twitter Bootstrap-选项卡-URL不变


109

我正在使用Twitter Bootstrap及其“选项卡”。

我有以下代码:

<ul class="nav nav-tabs">
    <li class="active"><a data-toggle="tab" href="#add">add</a></li>
    <li><a data-toggle="tab" href="#edit" >edit</a></li>
    <li><a data-toggle="tab" href="#delete" >delete</a></li>
</ul>

这些标签正常工作,但未在URL中添加#add,#edit,#delete。

当我删除data-toggleURL更改时,这些选项卡不起作用。

有什么解决办法吗?


1
修复此问题的插件:github.com/timabell/jquery.stickytabs
Tim Abell

Answers:


269

试试这个代码。它将标签href添加到url,并根据页面加载时的哈希值打开标签:

$(function(){
  var hash = window.location.hash;
  hash && $('ul.nav a[href="' + hash + '"]').tab('show');

  $('.nav-tabs a').click(function (e) {
    $(this).tab('show');
    var scrollmem = $('body').scrollTop() || $('html').scrollTop();
    window.location.hash = this.hash;
    $('html,body').scrollTop(scrollmem);
  });
});

1
它的工作非常好。+1。但是,选择器中“ hash && $ ..”的原因是显示选项卡,但是什么意思是“ hash &&”。感谢
richardhell

4
&&意味着AND如果它的左边等于true(hash不为0,null或为空),而右边等于true,则执行某项操作,但是该行以a结尾,;因此之前;无需执行任何操作,并且如果a标签显示与否,无论.tab('show')返回什么都无关紧要,它仍然会尝试。以这种方式评估逻辑时,如果等式的第一部分(之前&&)为false,则无需继续评估,因此不会显示该选项卡。您可以达到以下相同的效果:if(hash){ $('ul.nav a[href="' + hash + '"]').tab('show'); }
vahanpwns 2014年

1
TL; DR:a && b;表示try a,然后仅当其为true时才尝试b。如果字符串不为空,则为true。
vahanpwns 2014年

8
我将如何使用它,以便在使用“#” URL时仅重新加载顶部的页面?现在,它向下滚动到选项卡的开始位置。我想滚动到实际页面顶部
kibaekr 2014年

1
工作正常,但必须在Bootstrap 3
Zzirconium

49

完整的解决方案需要三个组件:

  1. 如果URL中包含哈希,则在加载页面时显示正确的选项卡。
  2. 更改选项卡时,更改URL中的哈希。
  3. URL中的哈希值更改时,请更改标签(后退/前进按钮),并确保第一个标签正确循环。

我认为这里没有任何评论或公认的答案可以解决所有这些情况。

由于涉及到很多,我认为它是最小的jQuery插件:https : //github.com/aidanlister/jquery-stickytabs

您可以这样调用插件:

$('.nav-tabs').stickyTabs();

我为此写了一篇博文,http://aidanlister.com/2014/03/persisting-the-tab-state-in-bootstrap/


我给了它它自己的git repo:github.com/timabell/jquery.stickytabs-非常感谢您的插件,请多多关照
蒂姆·阿贝尔

此解决方案+1,因为它也适用于后退/后退浏览,@ tomaszback的解决方案则不行。谢谢!
bitfidget

这很棒,效果很好,但是当我在URL中加载带有哈希值的页面时,效果并不理想。会不断挖掘以确保这是我做错了的事情(很有可能)。但是,我要给它+1
MattBoothDev

27

使用data-toggle="tab" 询问插件来处理的标签,这在做的过程调用preventDefault的事件(在github代码)。

您可以使用自己的标签激活功能,并让事件通过:

$('.nav-tabs a').click(function (e) {
    // No e.preventDefault() here
    $(this).tab('show');
});

并且必须删除该属性 data-toggle="tab"

如有疑问,请检查文档


11

由于锚元素已经更改了URL哈希,因此监听onhashchange事件是另一个不错的选择。如@flori所述,此方法与浏览器的后退按钮配合使用效果很好。

var tabs$ = $(".nav-tabs a");

$( window ).on("hashchange", function() {
    var hash = window.location.hash, // get current hash
        menu_item$ = tabs$.filter('[href="' + hash + '"]'); // get the menu element

    menu_item$.tab("show"); // call bootstrap to show the tab
}).trigger("hashchange");

最后,在定义侦听器后立即触发事件也将有助于在页面加载时显示正确的选项卡。


3

我对您的问题的解决方案:

首先data-value向每个a链接添加新属性,如下所示:

<ul class="nav nav-tabs">
    <li class="active">
        <a data-toggle="tab" href="#tab-add" data-value="#add">add</a>
    </li>
    <li>
        <a data-toggle="tab" href="#tab-edit" data-value="#edit">edit</a>
    </li>
    <li>
        <a data-toggle="tab" href="#tab-delete" data-value="#delete">delete</a>
    </li>
</ul>

其次,更改标签的ID(例如从add到)tab-add,还会更新href以包含tab-前缀:

<div class="tab-content">
    <div class="tab-pane" id="tab-add">Add panel</div>
    <div class="tab-pane" id="tab-edit">Edit panel</div>
    <div class="tab-pane" id="tab-delete">Panel panel</div>
</div>

最后是js代码:

<script type="text/javascript">
    $(function () {
        var navTabs = $('.nav-tabs a');
        var hash = window.location.hash;
        hash && navTabs.filter('[data-value="' + hash + '"]').tab('show');

        navTabs.on('shown', function (e) {
            var newhash = $(e.target).attr('data-value');
            window.location.hash = newhash;
        });
    })
</script>

这是jsFiddle-但由于jsFiddle使用iframe而无法使用,但是您可以阅读我的解决方案的源代码。


3

带有Bootstrap 3选项卡的CakePHP的同样问题,加上当我使用外部URL和锚发送时,它跳到丢失了菜单的部分,在查看了许多解决方案后,此操作...

感谢:http : //ck.kennt-wayne.de/2012/dec/twitter-bootstrap-how-to-fix-tabs

$(document).ready(function()
 {  
//Redirecciona al tab, usando un prefijo al cargar por primera vez, al usar redirect en cake #_Pagos    
//Redirecciona al tab, usando #Pagos
/* Automagically jump on good tab based on anchor; for page reloads or links */
 if(location.hash) 
  {
     $('a[href=' + location.hash + ']').tab('show');         
  }


//Para evitar el bajar al nivel del tab, (al mostrarse el tab subimos)
$('a[data-toggle="tab"]').on('shown.bs.tab', function(e) 
{
    location.hash = $(e.target).attr('href').substr(1);
    scrollTo(0,0);      
});



//Actualiza el URL con el anchor o ancla del tab al darle clic
 /* Update hash based on tab, basically restores browser default behavior to
 fix bootstrap tabs */
$(document.body).on("click", "a[data-toggle]", function(event) 
  {
    location.hash = this.getAttribute("href");
  });


//Redirecciona al tab, al usar los botones de regresar y avanzar del navegador.
/* on history back activate the tab of the location hash if exists or the default tab if no hash exists */   
$(window).on('popstate', function() 
{
  //Si se accesa al menu, se regresa al tab del perfil (activo default), fixed conflict with menu
  //var anchor = location.hash || $("a[data-toggle=tab]").first().attr("href");
  var anchor = location.hash;
  $('a[href=' + anchor + ']').tab('show');

});   

});//Fin OnReady

2

还有一种简单的方法可以对哈希更改做出反应(例如,后退按钮)。只需将一个hashchange事件监听器添加到tomaszbak解决方案中:

$(function(){
  // Change tab on load
  var hash = window.location.hash;
  hash && $('ul.nav a[href="' + hash + '"]').tab('show');

  $('.nav-tabs a').click(function (e) {
    $(this).tab('show');
    var scrollmem = $('body').scrollTop();
    window.location.hash = this.hash;
    $('html,body').scrollTop(scrollmem);
  });

  // Change tab on hashchange
  window.addEventListener('hashchange', function() {
    var changedHash = window.location.hash;
    changedHash && $('ul.nav a[href="' + changedHash + '"]').tab('show');
  }, false);
});

1

我正在使用Bootstrap 3.3。*,以上解决方案都没有帮助我,甚至被标记为答案一。我只是添加了以下脚本并开始工作。

$(function(){
    var hash = document.location.hash;
    if (hash) {
       $('.navbar-nav a[href="' + hash + '"]').tab('show');
    }
    $('a[data-toggle="tab"]').on('click', function (e) {
       history.pushState(null, null, $(this).attr('href'));
    });
});

希望对您有帮助。


0

最简单,假设您正在使用此处data-toggle="tab"描述的文档化语法:

$(document).on('shown.bs.tab', function(event) {
  window.location.hash = $(event.target).attr('href');
});

这会更改URL,但单击链接打开特定选项卡时无法转到URL
Khrys 2014年

0

对于使用Ruby on Rails或任何其他服务器端脚本的用户,您将需要anchor在路径上使用该选项。这是因为页面一旦加载,便没有可用的URL哈希。您将要通过链接或表单提交提供正确的标签。

<%= form_for @foo, url: foo_path(@foo, anchor: dom_id(foo)) do |f| %>
# Or
<%= link_to 'Foo', foo_path(@foo, anchor: dom_id(foo)) %>

如果您使用前缀来防止窗口跳转到ID:

<%= form_for @foo, url: foo_path(@foo, anchor: "bar_#{dom_id(foo)}") do |f| %>

然后,您使用CoffeeScript:

  hash = document.location.hash
  prefix = 'bar_'
  $('.nav-tabs a[href=' + hash.replace(prefix, '') + ']').tab 'show' if hash
  $('.nav-tabs a').on 'shown.bs.tab', (e) ->
    window.location.hash = e.target.hash.replace '#', '#' + prefix

或JavaScript:

var hash, prefix;

hash = document.location.hash;
prefix = 'bar_';

if (hash) {
  $('.nav-tabs a[href=' + hash.replace(prefix, '') + ']').tab('show');
}

$('.nav-tabs a').on('shown.bs.tab', function(e) {
  window.location.hash = e.target.hash.replace('#', '#' + prefix);
});

这应该在Bootstrap 3中工作。


0

感谢@tomaszbak提出的原始解决方案,但是由于我的编辑被拒绝并且我无法对他的帖子发表评论,但我将在此处保留略有改进和可读性的版本。

它的作用基本相同,但是如果解决了我对他的跨浏览器兼容性问题。

$(document).ready(function(){
   // go to hash on window load
   var hash = window.location.hash;
   if (hash) {
       $('ul.nav a[href="' + hash + '"]').tab('show');
   }
   // change hash on click
   $('.nav-tabs a').click(function (e) {
       $(this).tab('show');
       if($('html').scrollTop()){
           var scrollmem = $('html').scrollTop(); // get scrollbar position (firefox)
       }else{
           var scrollmem = $('body').scrollTop(); // get scrollbar position (chrome)
       }
       window.location.hash = this.hash;
       $('html,body').scrollTop(scrollmem); // set scrollbar position
   });
});

被拒绝对我不起作用(也许只是Firefox版本)。无论如何,我对var scrollmem = $('body')。scrollTop()||进行了更改。$('html')。scrollTop(); 谢谢!
tomaszbak

1
是。告诉我有关它的信息,当您说我意识到这是浏览器的问题时,便迅速进入chrome进行确认。我确实希望有一种评论编辑评论的方法。
Fuxy

0

这是一个使用的选项,history.pushState以便您可以使用浏览器的历史记录返回上一个选项卡

  $(document).ready(function() {
  // add a hash to the URL when the user clicks on a tab
  $('a[data-toggle="tab"]').on('click', function(e) {
    history.pushState(null, null, $(this).attr('href'));
  });
  // navigate to a tab when the history changes
  window.addEventListener("popstate", function(e) {
    var activeTab = $('[href=' + location.hash + ']');
    if (activeTab.length) {
      activeTab.tab('show');
    } else {
      $('.nav-tabs a:first').tab('show');
    }
  });
});

0

以上都不对我有用,所以这是我的工作方式:

  1. 添加class="tab-link"到所有需要此功能的链接
  2. 将以下代码添加到您的javascript中:
    window.addEventListener
    (
        'popstate',
        函数(事件)
        {
            tab_change();
        }
    );

    函数tab_change()
    {
        var hash = window.location.hash;
        hash && $('ul.nav a [href =“'+ hash +'”]').tab('show');

        $('.tab-link').click
        (
            函数(e)
            {
                $(this).tab('show');

                var scrollmem = $('body').scrollTop()|| $('html').scrollTop();
                window.location.hash = this.hash;
                $('html,body').scrollTop(scrollmem);

                $('ul.nav-tabs a [href =“'+ window.location.hash +'”]').tab('show');
            }
        );
    }


0

我了解OP表示使用JQuery,但您可以简单地使用普通JS来做到这一点:

document.querySelectorAll('ul.nav a.nav-link').forEach(link => {
    link.onclick = () => window.history.pushState(null, null, link.attributes.href.value);
});

-2

这也修复了使用jquery和bootstrap时无法触发的href非常模糊的选项卡

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> 

<script type="text/javascript">
$('.nav-tabs a').click(function (e) {
    // No e.preventDefault() here.
    $(this).tab('show');
});
</script>

<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.2.1/js/bootstrap.min.js"></script>

5
-1我看不到此答案如何为3个月前给出的答案和之前答案完全相同的代码增加任何价值。因此,以我的拙见,这不是一个有用的答案。
Nope 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.