Вкладки Twitter Bootstrap: перейти к конкретной вкладке на странице «Перезагрузка» или «Гиперссылка»

358

Я занимаюсь разработкой веб-страницы, на которой я использую Twitter Bootstrap Framework и их вкладки Bootstrap JS . Он отлично работает, за исключением нескольких мелких проблем, одна из которых заключается в том, что я не знаю, как перейти непосредственно к конкретной вкладке из внешней ссылки. Например:

<a href="facility.php#home">Home</a>
<a href="facility.php#notes">Notes</a>

должны перейти на вкладку «Главная» и «Примечания» соответственно при нажатии на ссылки с внешней страницы

mraliks
источник
49
Жаль, что это было встроено!
Деймон
5
Этот вопрос также был поднят здесь: github.com/twitter/bootstrap/issues/2415 (и там есть несколько решений).
Ztyx
это помогло мне -> stackoverflow.com/questions/12131273/…
JGilmartin
1
Обновленная ссылка на проблему начальной загрузки: github.com/twbs/bootstrap/issues/2415
bmihelac
3
Плагин, который исправляет это: github.com/timabell/jquery.stickytabs
Тим Абелл

Ответы:

603

Вот мое решение проблемы, возможно, немного поздно. Но это может помочь другим:

// Javascript to enable link to tab
var url = document.location.toString();
if (url.match('#')) {
    $('.nav-tabs a[href="#' + url.split('#')[1] + '"]').tab('show');
} 

// Change hash for page-reload
$('.nav-tabs a').on('shown.bs.tab', function (e) {
    window.location.hash = e.target.hash;
})
dubbe
источник
83
Я бы добавил еще 1 дополнительную строку, window.scrollTo(0, 0);чтобы окно всегда прокручивалось вверх
Trung Lê
1
$ ('. nav-tabs a [href * = #' + url.split ('#') [1] + ']'). tab ('show'); // с * безопаснее, так как в противном случае он соответствует только первому # ...
mattangriffel
1
Онлайн, который работал для меня: window.location.hash && $ ('li a [href = "' + window.location.hash + '"]'). Tab ('show'). Trigger ("click");
Дин Михан,
10
Вот демоверсия для Bootstrap 3: bootply.com/render/VQqzOawoYc#tab2 и исходный код
Zim
2
После обновления JQuery до 1,11 с 1,09 я получаю эту ошибку: Syntax error, unrecognized expression: .nav-tabs a[href=#tab-2]. Решено с помощью stackoverflow.com/questions/12131273/…
Пьетро З.
213

ОБНОВИТЬ

Для Bootstrap 3 измените .on('shown', ...)на.on('shown.bs.tab', ....)


Это основано на ответе @dubbe и принятом ТАКом ответе . Это решает проблему с window.scrollTo(0,0)не работает правильно. Проблема в том, что когда вы заменяете хеш URL на показанной вкладке, браузер прокручивает этот хеш, так как это элемент на странице. Чтобы обойти это, добавьте префикс, чтобы хеш не ссылался на фактический элемент страницы

// Javascript to enable link to tab
var hash = document.location.hash;
var prefix = "tab_";
if (hash) {
    $('.nav-tabs a[href="'+hash.replace(prefix,"")+'"]').tab('show');
} 

// Change hash for page-reload
$('.nav-tabs a').on('shown', function (e) {
    window.location.hash = e.target.hash.replace("#", "#" + prefix);
});

Пример использования

Если у вас есть панель вкладок с id = "mytab", вам нужно разместить ссылку так:

<a href="yoursite.com/#tab_mytab">Go to Specific Tab </a>
flynfish
источник
1
Будет ли простой способ ссылки на закладки, расположенные под определенной вкладкой? У меня есть пять вкладок на моей странице, и под ними у меня есть несколько закладок. То, что я хотел бы, чтобы сделать эти закладки связываемыми снаружи вкладки.
nize
@nize, если вы создадите jsfiddle с тем, что вы пытаетесь сделать, я постараюсь взглянуть.
рыба-мух
1
Вот демоверсия Bootlpy для Bootstrap 3: bootply.com/render/VQqzOawoYc#tab2 и исходный код
Zim
В приведенном выше примере отсутствуют двойные кавычки на href. строка 5 должна быть:$('.nav-tabs a[href="'+hash.replace(prefix,"")+'"]').tab('show');
Ponyboy
Работает для меня, за исключением того, что мне пришлось удалить последнюю косую черту (перед #) в 'yoursite.com/anotherpage/#tab_mytab', в противном случае это привело к хаосу при загрузке страницы.
Александр
52

Вы можете вызвать clickсобытие на соответствующей ссылке вкладки:

$(document).ready(function(){

  if(window.location.hash != "") {
      $('a[href="' + window.location.hash + '"]').click()
  }

});
Мариан Тайсен
источник
Спасибо за совет! Это прекрасно работало с одной маленькой проблемой. Обновление страницы не приведет к ее правильной вкладке. Нажав Ctrl + F5 будет. Я изменил код следующим образом: `$ (document) .ready (function () {function getUrlVars () {var vars = {}; var parts = window.location.href.replace (/ [? &] + ([ ^ = &] +) = ([^ &] *) / gi, функция (m, ключ, значение) {vars [ключ] = значение;}); возврат vars;} var action = getUrlVars () ["action" ]; if (action! = "") {$ ('a [href = "#' + action + '"]'). click ()};}); `
Мраликс
44

Это улучшенная реализация решения dubbe, которое предотвращает прокрутку.

// Javascript to enable link to tab
var url = document.location.toString();
if (url.match('#')) {
    $('.nav-tabs a[href="#'+url.split('#')[1]+'"]').tab('show') ;
} 

// With HTML5 history API, we can easily prevent scrolling!
$('.nav-tabs a').on('shown.bs.tab', function (e) {
    if(history.pushState) {
        history.pushState(null, null, e.target.hash); 
    } else {
        window.location.hash = e.target.hash; //Polyfill for old browsers
    }
})
Демиркан Челеби
источник
21

Хотя предоставленное решение JavaScript может работать, я пошел несколько другим путем, который не требует дополнительного JavaScript, но требует логики в вашем представлении. Вы создаете ссылку со стандартным параметром URL, например:

<a href = "http://link.to.yourpage?activeTab=home">My Link</a>

Затем вы просто определяете значение activeTab для записи 'class = "active"' в соответствующий <li>

Псевдокод (реализуйте соответственно на вашем языке). Примечание. Я установил вкладку «Домой» в качестве активной по умолчанию, если в этом примере параметры не указаны.

$activetabhome = (params.activeTab is null or params.activeTab == 'home') ? 'class="active"' : '';
$activetabprofile = (params.activeTab == 'profile') ? 'class="active"' : '';

<li $activetabhome><a href="#home">Home</a></li>
<li $activetabprofile><a href="#profile">Profile</a></li>
Питер
источник
Я предпочитаю ваше решение решению JS по одной простой причине: JS location.hash будет переходить к идентификатору, в результате чего позиция курсора будет подниматься и опускаться.
Трунг Ле
Я предпочитаю это решение. Фактически, я создал новые маршруты для вкладок и заново сгенерировал представление, установив соответствующий класс соответствующим образом. Это позволяет избежать головной боли при изменении размера страницы, URL-хэша и прокрутки страницы.
Виджей Мина
10

Я не большой поклонник если ... еще; поэтому я выбрал более простой подход.

$(document).ready(function(event) {
    $('ul.nav.nav-tabs a:first').tab('show'); // Select first tab
    $('ul.nav.nav-tabs a[href="'+ window.location.hash+ '"]').tab('show'); // Select tab by name if provided in location hash
    $('ul.nav.nav-tabs a[data-toggle="tab"]').on('shown', function (event) {    // Update the location hash to current tab
        window.location.hash= event.target.hash;
    })
});
  1. Выберите вкладку по умолчанию (обычно первая)
  2. Переключиться на вкладку (если такой элемент действительно присутствует; пусть jQuery его обрабатывает); Ничего не происходит, если указан неправильный хеш
  3. [Необязательно] Обновите хэш, если вручную выбрана другая вкладка

Не обращается к прокрутке до запрошенного хэша; но должно ли это?

visitsb
источник
8

Это работает в Bootstrap 3 и улучшает 2 лучших ответа dubbe и flynfish, интегрируя также ответ GarciaWebDev (который учитывает параметры URL после хеша и является прямым от авторов Bootstrap на трекере проблем github):

// Javascript to enable link to tab
var hash = document.location.hash;
var prefix = "tab_";

if (hash) {
    hash = hash.replace(prefix,'');
    var hashPieces = hash.split('?');
    activeTab = $('.nav-tabs a[href=' + hashPieces[0] + ']');
    activeTab && activeTab.tab('show');
} 

// Change hash for page-reload
$('.nav-tabs a').on('shown', function (e) {
    window.location.hash = e.target.hash.replace("#", "#" + prefix);
});
greggdavis
источник
1
это не работает в Bootstrap 3, 'shown'должно быть в 'shown.bs.tab'соответствии с документацией: getbootstrap.com/javascript/#tabs-events . Я озадачен тем, почему, но когда я попытался отредактировать ваше сообщение, оно было отклонено ...
YPCrumble
6

Этот код выбирает правую вкладку в зависимости от #hash и добавляет правильный #hash при нажатии на вкладку. (это использует jquery)

В Coffeescript:

$(document).ready ->
    if location.hash != ''
        $('a[href="'+location.hash+'"]').tab('show')

    $('a[data-toggle="tab"]').on 'shown', (e) ->
        location.hash = $(e.target).attr('href').substr(1)

или в JS:

$(document).ready(function() {
    if (location.hash !== '') $('a[href="' + location.hash + '"]').tab('show');
    return $('a[data-toggle="tab"]').on('shown', function(e) {
      return location.hash = $(e.target).attr('href').substr(1);
    });
});
Sucrenoir
источник
убедитесь, что поставили это после загрузки jquery. Я помещал это в середину страницы (это было легкое место, чтобы вставить это для тестирования), и это не работало. Положить его после загрузки JQuery прекрасно работает.
Рон
6

Опираясь на решение Демиркана Челеби; Я хотел, чтобы вкладка открывалась при изменении URL-адреса и открывала вкладку без перезагрузки страницы с сервера.

<script type="text/javascript">
    $(function() {
        openTabHash(); // for the initial page load
        window.addEventListener("hashchange", openTabHash, false); // for later changes to url
    });


    function openTabHash()
    {
        console.log('openTabHash');
        // Javascript to enable link to tab
        var url = document.location.toString();
        if (url.match('#')) {
            $('.nav-tabs a[href="#'+url.split('#')[1]+'"]').tab('show') ;
        } 

        // With HTML5 history API, we can easily prevent scrolling!
        $('.nav-tabs a').on('shown.bs.tab', function (e) {
            if(history.pushState) {
                history.pushState(null, null, e.target.hash); 
            } else {
                window.location.hash = e.target.hash; //Polyfill for old browsers
            }
        })
    }
</script>
Gavin
источник
5

Решение @flynfish + @Ztyx, которое я использую для вложенных вкладок:

    handleTabLinks();

    function handleTabLinks() {
        if(window.location.hash == '') {
            window.location.hash = window.location.hash + '#_';
        }
        var hash = window.location.hash.split('#')[1];
        var prefix = '_';
        var hpieces = hash.split('/');
        for (var i=0;i<hpieces.length;i++) {
            var domelid = hpieces[i].replace(prefix,'');
            var domitem = $('a[href=#' + domelid + '][data-toggle=tab]');
            if (domitem.length > 0) {
                domitem.tab('show');
            }
        }
        $('a[data-toggle=tab]').on('shown', function (e) {
            if ($(this).hasClass('nested')) {
                var nested = window.location.hash.split('/');
                window.location.hash = nested[0] + '/' + e.target.hash.split('#')[1];
            } else {
                window.location.hash = e.target.hash.replace('#', '#' + prefix);
            }
        });
    }

у детей должен быть класс = "вложенный"

Артем Кашин
источник
5

Я придумал решение, которое использует хэш url или localStorage, в зависимости от доступности последнего, с кодом ниже:

$(function(){
    $(document).on('shown.bs.tab', 'a[data-toggle="tab"]', function (e) {
        localStorage.setItem('activeTab', $(e.target).attr('href'));
    })

    var hash = window.location.hash;
    var activeTab = localStorage.getItem('activeTab');

    if(hash){
          $('#project-tabs  a[href="' + hash + '"]').tab('show');   
    }else if (activeTab){
        $('#project-tabs a[href="' + activeTab + '"]').tab('show');
    }
});
Vaibhav
источник
4

Я бы посоветовал вам использовать код, предоставленный авторами Bootstrap для отслеживания их проблем на GitHub :

var hash = location.hash
  , hashPieces = hash.split('?')
  , activeTab = $('[href=' + hashPieces[0] + ']');
activeTab && activeTab.tab('show');

Вы можете найти в ссылке на проблему больше информации о том, почему они не решили поддержать это.

Алехандро Гарсия Иглесиас
источник
4

Попробовал несколько способов, описанных выше, и в итоге получил следующее рабочее решение, просто попробуйте скопировать и вставить в ваш редактор. Для проверки просто измените хэш на входящие, исходящие, составьте в URL и нажмите клавишу ввода.

<html>
    <head>
        <link type='text/css' rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css' />
        <script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
    </head>
    <body>
        <div class="container body-content">
            <ul class="nav nav-tabs">
                <li class="active"><a data-toggle="tab" href="#inbox">Inbox</a></li>
                <li><a data-toggle="tab" href="#outbox">Outbox</a></li>
                <li><a data-toggle="tab" href="#compose">Compose</a></li>
            </ul>
            <div class="tab-content">
                <div id="inbox" class="tab-pane fade in active">
                    Inbox Content
                </div>
                <div id="outbox" class="tab-pane fade">
                    Outbox Content
                </div>
                <div id="compose" class="tab-pane fade">
                    Compose Content
                </div>
            </div>
        </div>
        <script>
            $(function () {
                var hash = window.location.hash;
                hash && $('ul.nav a[href="' + hash + '"]').tab('show');
            });
        </script>
    </body>
</html>

Надеюсь, это сэкономит ваше время.

Abhimanyu
источник
3

Вот что я сделал, очень просто, и, если у ваших ссылок на вкладках есть ID, связанный с ними, вы можете получить атрибут href и передать его функции, которая показывает содержимое вкладки:

<script type="text/javascript">
        jQuery(document).ready(function() {
            var hash = document.location.hash;
            var prefix = "tab_";
            if (hash) {
                var tab = jQuery(hash.replace(prefix,"")).attr('href');
                jQuery('.nav-tabs a[href='+tab+']').tab('show');
            }
        });
        </script>

Затем в вашем URL вы можете добавить хеш в виде чего-то вроде: # tab_tab1, часть 'tab_' удаляется из самого хэша, поэтому после этого помещается идентификатор фактической ссылки вкладки в навигационных вкладках (tabid1), поэтому URL будет выглядеть примерно так: www.mydomain.com/index.php#tab_tabid1.

Это прекрасно работает для меня и надеюсь, что это поможет кому-то еще :-)

Дерек Бантин
источник
2

Это мое решение для обработки вложенных вкладок. Я просто добавил функцию, чтобы проверить, есть ли на активной вкладке родительская вкладка для активации. Это функция:

function activateParentTab(tab) {
    $('.tab-pane').each(function() {
        var cur_tab = $(this);
        if ( $(this).find('#' + tab).length > 0 ) {
            $('.nav-tabs a[href=#'+ cur_tab.attr('id') +']').tab('show');
            return false;
        }
    });
}

И можно назвать так (на основе решения @ flynfish):

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

// Change hash for page-reload
$('.nav-tabs a').on('shown', function (e) {
    window.location.hash = e.target.hash.replace("#", "#" + prefix);
});

Это решение работает довольно хорошо для меня на данный момент. Надеюсь, что это может быть полезно для кого-то еще;)

Стефано Марра
источник
2

Мне пришлось изменить некоторые биты, чтобы это работало на меня. Я использую Bootstrap 3 и JQuery 2

// Javascript to enable link to tab
var hash = document.location.hash;
var prefix = "!";
if (hash) {
    hash = hash.replace(prefix,'');
    var hashPieces = hash.split('?');
    activeTab = $('[role="tablist"] a[href=' + hashPieces[0] + ']');
    activeTab && activeTab.tab('show');
}

// Change hash for page-reload
$('[role="tablist"] a').on('shown.bs.tab', function (e) {
    window.location.hash = e.target.hash.replace("#", "#" + prefix);
});
ruifn
источник
Отличный ответ, кроме меня пришлось заменить на "!" префикс с "tab_". В остальном работал отлично.
koziez
2

Просто вставьте этот код на свою страницу:

$(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();
    window.location.hash = this.hash;
    $('html,body').scrollTop(scrollmem);
  });
});

Амин Голибейгян
источник
1

У меня просто была эта проблема, но мне нужно было обрабатывать несколько уровней вкладок. Код довольно уродливый (см. Комментарии), но делает свою работу: https://gist.github.com/JensRantil/4721860 Надеюсь, кто-то найдет его полезным (и не стесняйтесь предлагать лучшие решения!).

Ztyx
источник
1

Комбинируя peices из других ответов, вот решение, которое может открыть много уровней вложенных вкладок:

// opens all tabs down to the specified tab
var hash = location.hash.split('?')[0];
if(hash) {
  var $link = $('[href=' + hash + ']');
  var parents = $link.parents('.tab-pane').get();
  $(parents.reverse()).each(function() {
    $('[href=#' + this.id + ']').tab('show') ;
  });
  $link.tab('show');
}
cweston
источник
работает только до 2 уровней вложенности, 3-й уровень вызывает проблемы.
Николас Гамильтон
Я только что проверил это на трех уровнях вкладок, и, похоже, это работает для меня. Вы уверены, что это не проблема с вашей реализацией? Какую «проблему» вы испытываете?
Cweston
Любая вкладка 1-го уровня и 2-го уровня работает нормально, однако, на 3-м уровне, при обновлении страницы (или отправке формы), когда страница открывается снова, она фокусируется на первой вкладке на 2-м уровне.
Николас Гамильтон
Так что все заработало нормально (в моем коде была небольшая опечатка), однако после исправления опечатки, только $('.nav-tabs li a').click( function(e) { history.pushState( null, null, $(this).attr('href') );});в javascript над вашим кодом.
Николас Гамильтон
1

Если это кому-нибудь важно, следующий код небольшой и работает безупречно, чтобы получить единственное значение хеша из URL и показать, что:

<script>
    window.onload = function () {
        let url = document.location.toString();
        let splitHash = url.split("#");
        document.getElementById(splitHash[1]).click();
    };
</script>

он извлекает идентификатор и запускает событие click. Просто.

Сэм
источник
0

Я делаю что-то вроде этого для ссылок с ajax #!#(например, / test.com #! # Test3), но вы можете изменить его так, как вам нравится.

$(document).ready(function() {

       let hash = document.location.hash;
       let prefix = "!#";

       //change hash url on page reload
       if (hash) {
         $('.nav-tabs a[href=\"'+hash.replace(prefix,"")+'\"]').tab('show');
       } 

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

Пример с простой страницей на Github здесь

эвдемония
источник
0

Я знаю, что этот поток очень старый, но я оставлю здесь свою собственную реализацию:

$(function () {
  // some initialization code

  addTabBehavior()
})

// Initialize events and change tab on first page load.
function addTabBehavior() {
  $('.nav-tabs a').on('show.bs.tab', e => {
    window.location.hash = e.target.hash.replace('nav-', '')
  })

  $(window).on('popstate', e => {
    changeTab()
  })

  changeTab()
}

// Change the current tab and URL hash; if don't have any hash
// in URL, so activate the first tab and update the URL hash.
function changeTab() {
  const hash = getUrlHash()

  if (hash) {
    $(`.nav-tabs a[href="#nav-${hash}"]`).tab('show')
  } else {
    $('.nav-tabs a').first().tab('show')
  }
}

// Get the hash from URL. Ex: www.example.com/#tab1
function getUrlHash() {
  return window.location.hash.slice(1)
}

Обратите внимание, что я использую nav-префикс класса для навигации по ссылкам.

Ренан Коэльо
источник