Twitter Bootstrap - Tab - URL không thay đổi


109

Tôi đang sử dụng Twitter Bootstrap và các "tab" của nó.

Tôi có mã sau:

<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>

Các tab hoạt động bình thường, nhưng trong URL không được thêm #add, #edit, #delete.

Khi tôi xóa data-toggleURL thay đổi, nhưng các tab không hoạt động.

Bất kỳ giải pháp cho điều này?


1
Plugin rằng các bản sửa lỗi này: github.com/timabell/jquery.stickytabs
Tim Abell

Đây là một câu hỏi tương tự như stackoverflow.com/q/18999501/873282
koppor

Câu trả lời:


269

Hãy thử mã này. Nó thêm tab href vào url + tab mở dựa trên băm khi tải trang:

$(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
Nó hoạt động rất tốt. +1. Nhưng lý do "băm && $ .." từ bộ chọn là tab hiển thị, nhưng "băm &&" có nghĩa là gì. Thank
richardhell

4
&&có nghĩa là ANDnhư vậy nếu bên trái của điều đó tương đương với true ( hashkhông phải là 0, rỗng hoặc trống) và bên phải tương đương với true thì hãy làm điều gì đó, tuy nhiên dòng kết thúc bằng a ;nên không có gì phải làm trước đó ;và nó không quan trọng nếu a tab có hiển thị hay không và không quan trọng kết .tab('show')quả trả về, nó vẫn sẽ thử. Khi đánh giá logic theo cách này, nếu phần đầu tiên của phương trình (trước đó &&) là sai, không cần tiếp tục đánh giá, vì vậy tab sẽ không được hiển thị. Bạn có thể đạt được hiệu ứng tương tự như thế này:if(hash){ $('ul.nav a[href="' + hash + '"]').tab('show'); }
vahanpwns

1
TL; DR: a && b;có nghĩa là thử avà sau đó chỉ khi nó đúng, hãy thử b. Các chuỗi là true nếu chúng không rỗng.
vahanpwns

8
Tôi sẽ làm như thế nào để nó chỉ tải lại trang ở trên cùng khi tôi sử dụng url "#"? Ngay bây giờ, nó sẽ cuộn xuống nơi các tab bắt đầu. Tôi chỉ muốn cuộn đầu trang đến trang thực tế
kibaekr

1
hoạt động tốt nhưng phải thay thế "$ ('. nav-tabs a'). click (" bằng "$ ('# navtabs a'). on ('show.bs.tabs," trên Bootstrap 3
Zzirconium

49

Có ba thành phần cần thiết cho một giải pháp hoàn chỉnh:

  1. Hiển thị đúng tab khi trang được tải nếu có hàm băm trong URL.
  2. Thay đổi hàm băm trong URL khi thay đổi tab.
  3. Thay đổi tab khi hàm băm thay đổi trong URL (nút quay lại / chuyển tiếp) và đảm bảo rằng tab đầu tiên được xoay vòng một cách chính xác.

Tôi không nghĩ rằng bất kỳ nhận xét nào ở đây, cũng như câu trả lời được chấp nhận, sẽ xử lý tất cả các tình huống này.

Vì có khá nhiều liên quan, tôi nghĩ nó gọn gàng nhất là một plugin jQuery nhỏ: https://github.com/aidanlister/jquery-stickytabs

Bạn có thể gọi plugin như vậy:

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

Tôi đã tạo một bài đăng trên blog cho điều này, http://aidanlister.com/2014/03/persisting-the-tab-state-in-bootstrap/


Tôi đã cung cấp cho nó repo git của riêng nó: github.com/timabell/jquery.stickytabs - cảm ơn rất nhiều vì plugin này rất hiệu quả.
Tim Abell

+1 cho giải pháp này vì nó cũng hoạt động khi duyệt lại / tiếp theo mà giải pháp @tomaszback 'không làm được. Cảm ơn!
bitfidget

Điều này thật tuyệt và hoạt động tốt, nhưng không phải khi tôi tải trang có hàm băm trong URL. Sẽ tiếp tục đào xung quanh để đảm bảo rằng đó là điều tôi đã làm sai (rất có thể). Tuy nhiên, tôi sẽ cho nó +1
MattBoothDev

27

Việc sử dụng data-toggle="tab" yêu cầu plugin xử lý các tab, trong khi thực hiện nó sẽ gọi preventDefaultsự kiện ( mã trên github ).

Bạn có thể sử dụng kích hoạt tab của riêng mình và để sự kiện diễn ra:

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

Và bạn phải xóa thuộc tính data-toggle="tab"

Kiểm tra tài liệu nếu bạn có nghi ngờ.


11

Vì các phần tử neo của bạn đã thay đổi băm url, nên lắng nghe sự kiện onhashchange là một lựa chọn tốt khác. Như @flori đã đề cập, phương pháp này hoạt động tốt với nút quay lại của trình duyệt.

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");

Cuối cùng, việc kích hoạt sự kiện ngay sau khi bạn xác định trình lắng nghe cũng sẽ giúp hiển thị đúng tab khi tải trang.


3

Giải pháp của tôi cho vấn đề của bạn:

Đầu tiên hãy thêm data-valuethuộc tính mới vào từng aliên kết, như sau:

<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>

Thứ hai, thay đổi id của các tab, ví dụ từ từ addsang tab-add, cũng cập nhật hrefs để bao gồm tab-tiền tố:

<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>

Và cuối cùng là mã 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>

Đây là jsFiddle - nhưng nó không hoạt động do iframe được jsFiddle sử dụng, nhưng bạn có thể đọc nguồn giải pháp của tôi.


3

Vấn đề tương tự với CakePHP với Bootstrap 3 Tabs, cộng với khi tôi gửi bằng URL bên ngoài và liên kết, nó sẽ chuyển đến phần làm mất menu của tôi, sau khi xem xét nhiều giải pháp đã thực hiện điều này ...

cảm ơn: 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

Ngoài ra còn có một cách đơn giản để phản ứng khi thay đổi hàm băm (ví dụ: nút quay lại). Chỉ cần thêm trình xử lý sự kiện hashchange vào giải pháp 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

Tôi đang sử dụng Bootstrap 3.3. * Và không giải pháp nào ở trên giúp được tôi, thậm chí còn được đánh dấu là câu trả lời. Tôi chỉ cần thêm kịch bản bên dưới và làm việc.

$(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'));
    });
});

Hy vọng điều này sẽ giúp bạn.


0

Đơn giản nhất, giả sử bạn đang sử dụng data-toggle="tab"cú pháp được mô tả ở đây :

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

Điều này thay đổi URL nhưng không thể chuyển đến đó khi nhấp vào liên kết để mở một tab cụ thể
Khrys

0

Đối với những người sử dụng Ruby on Rails hoặc bất kỳ tập lệnh phía máy chủ nào khác, bạn sẽ muốn sử dụng anchortùy chọn trên các đường dẫn. Điều này là do khi trang tải, nó không có sẵn băm URL. Bạn sẽ muốn cung cấp đúng tab thông qua liên kết hoặc gửi biểu mẫu.

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

Nếu bạn đang sử dụng một tiền tố để ngăn cửa sổ chuyển sang id:

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

Sau đó, bạn 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

Hoặc 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);
});

Điều này sẽ hoạt động trong Bootstrap 3.


0

Cảm ơn @tomaszbak vì giải pháp ban đầu, tuy nhiên vì các chỉnh sửa của tôi bị từ chối và tôi không thể nhận xét về bài đăng của anh ấy nên tôi sẽ để phiên bản cải tiến hơn một chút và dễ đọc hơn ở đây.

Về cơ bản, nó hoạt động tương tự nhưng nếu khắc phục được vấn đề tương thích giữa các trình duyệt mà tôi gặp phải với của anh ấy.

$(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
   });
});

Rejected không hoạt động đối với tôi (có thể đó chỉ là phiên bản Firefox). Dù sao, tôi đã thay đổi thành var scrollmem = $ ('body'). ScrollTop () || $ ('html'). scrollTop (); Cảm ơn!
tomaszbak

1
Đúng. Hãy kể cho tôi nghe về điều đó ngay khi bạn nói rằng tôi nhận ra đó là một thứ trình duyệt nhanh chóng được đưa vào chrome để đảm bảo. Tôi chắc chắn muốn có một cách để bình luận về các bài đánh giá chỉnh sửa.
Fuxy

0

Đây là một tùy chọn sử dụng history.pushStateđể bạn có thể sử dụng lịch sử trình duyệt của mình để quay lại tab trước đó

  $(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

Không có cách nào ở trên phù hợp với tôi, vì vậy đây là cách tôi bắt đầu làm việc:

  1. Thêm class="tab-link"vào tất cả các liên kết cần chức năng này
  2. Thêm mã sau vào javascript của bạn:
    window.addEventListener
    (
        'popstate',
        hàm (sự kiện)
        {
            tab_change ();
        }
    );

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

        $ ('.tab-link') .click
        (
            hàm (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

Tôi hiểu rằng OP đã nói bằng cách sử dụng JQuery nhưng bạn có thể chỉ cần sử dụng vanilla JS để làm điều đó:

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

-2

Điều này cũng khắc phục một tab cực kỳ khó hiểu a href không kích hoạt khi sử dụng jquery và bootstrap

<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 Tôi không thấy làm thế nào câu trả lời này thêm bất kỳ giá trị nào cho các câu trả lời trước đó đã được đưa ra 3 tháng trước với cùng một mã trong câu trả lời. Do đó không phải là một câu trả lời hữu ích theo ý kiến ​​khiêm tốn của tôi.
Không
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.