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-toggleзміни URL-адреси, але вкладки не працюють.

Будь-які рішення для цього?


1
Плагін, що виправляє це: github.com/timabell/jquery.stickytabs
Tim Abell

Це таке ж питання , як stackoverflow.com/q/18999501/873282
koppor

Відповіді:


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. Але в чому причина "хеш і & $ .." від селектора - це вкладка show, але що означає "хеш &&". Дякую
richardhell

4
&&це означає, що ANDякщо ліворуч прирівнюється до істинного ( hashне 0, нульового чи порожнього), а право прирівнюється до істинного, тоді роби щось, однак рядок закінчується ;так, що раніше нічого робити, ;і не має значення, якщо відображається вкладка чи ні, і не має значення, що .tab('show')повертається, вона все одно буде намагатися. Оцінюючи логіку таким чином, якщо перша частина рівняння (раніше &&) помилкова, не потрібно продовжувати оцінювання, тому вкладка не відображатиметься. Ви могли б досягти такого ж ефекту, як і цей:if(hash){ $('ul.nav a[href="' + hash + '"]').tab('show'); }
vahanpwns

1
TL; DR: a && b;означає спробувати, aі тільки тоді, якщо це правда, спробуйте b. Рядки справжні, якщо вони не порожні.
vahanpwns

8
Як зробити це так, щоб воно просто перезавантажувало сторінку вгорі, коли я використовую URL-адресу "#"? Зараз він прокручується вниз, де починаються вкладки. Я просто хотів би прокрутити верхню сторінку до фактичної сторінки
kibaekr

1
працює нормально, але довелося замінити "$ ('. nav-tabs a'). click (" by "$ ('# navtabs a'). on ('показано.bs.tabs," на 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>

По-друге, змініть ідентифікатори вкладок, наприклад, з addна tab-add, також оновіть hrefs, щоб включити 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 - але це не працює через iframe, який використовує jsFiddle, але ви можете прочитати джерело мого рішення.


3

Та ж проблема з CakePHP з Bootstrap 3 Tabs, плюс коли я надсилаю із зовнішньою 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

Існує також простий спосіб реагувати на зміни хешу (наприклад, кнопка "назад"). Просто додайте слухача подій хеш-змін до рішення 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-адреси, але не може перейти туди, натиснувши посилання, щоб відкрити певну вкладку
Хрис

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
Так. Скажіть мені про це, як тільки ви сказали, що я зрозумів, що це браузер, що швидко перейшов у хром, щоб переконатися. Я впевнений, що хотів, щоб був спосіб коментувати редагування відгуків.
Фуксі

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;
        хеш && $ ('ul.nav a [href = "' + хеш + '"]') .tab ('показати');

        $ ('.tab-link') .click
        (
            функція (е)
            {
                $ (this) .tab ('показ');

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

                $ ('ul.nav-tabs a [href = "' + window.location.hash + '"]') .tab ('показати');
            }
        );
    }


0

Я зрозумів, що ОП сказав, використовуючи JQuery, але ви можете просто використовувати JS ванілі для цього:

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

-2

Це також виправляє надзвичайно незрозумілу вкладку, коли href не спрацьовує при використанні jquery та 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 Я не бачу, як ця відповідь додає будь-якого значення вже попереднім відповідям, даним 3 місяця тому з точно таким же кодом у відповіді. Тому не корисна відповідь на мою скромну думку.
Nope
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.