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


358

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

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

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


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

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>

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. [Необязательно] Обновите хэш, если вручную выбрана другая вкладка

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



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

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

убедитесь, что поставили это после загрузки 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>


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

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>

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


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

Отличный ответ, кроме меня пришлось заменить на "!" префикс с "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 Надеюсь, кто-то найдет его полезным (и не стесняйтесь предлагать лучшие решения!).


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

работает только до 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-префикс класса для навигации по ссылкам.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.