adminvps

Универсальный jQuery-скрипт для блоков с вкладками (табами)

Универсальный jQuery-скрипт для блоков с вкладками (табами)

Содержание: Вступление Код jQuery-скрипта для переключаемых блоков с вкладками Добавлено 07.03.2010 (обновлено 09.04.2015) Скачать Универсальный jQuery-скрипт для блоков с вкладками HTML-код, который нужно использовать для скрипта Обязательные CSS-стили для вышеуказанного HTML-кода Примеры Вступление Мое знакомство с фреймворком jQuery произошло в 2008-м году, после ...

Полезные комментарии (8)
Комментарии (967)
  1. 1
    Deny

    Dimox, подскажите, возможно ли сделать так, чтобы иметь возможность обновлять каждую вкладку по отдельности, если можно, то как?
    Я думаю что вы согласитесь, было бы очень хорошо, если бы была возможность поотдельности обновлять содержимое каждой вкладки, вместо обновления всей страницы…
    Заранее спасибо за ответ!

    • 2

      Не совсем понимаю, что вы хотите. Имеете в виду — загружать содержимое вкладки только при переключении на нее?

      • 3
        Deny

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

      • 5
        Макс

        Dimox, подскажите как можно реализовать загрузку содержимого вкладки только при переключении на нее (для 4-го примера)? То есть, по умолчанию грузится содержимое только вкладки с классом current, а содержимое остальных вкладок грузится только по нажатии на них.

  2. 6
    Marat
    @

    Подскажите, пожалуйста, как правильно поместить один внутрь другого, чтоб при открытии вкладки в нём был другой скрипт со своими вкладками и всё работало, а то вроде работает, но как только возвращаюсь на первую внутреннюю то перекидывает на главную первую…

    Одним словом чтоб многоуровневым вариантом делать…

  3. 9
    Marat
    @

    использую пример с localstorage

  4. 10

    Отличный плагин, спасибоза разъяснения! Немного запарился с тем, как из менить блок отображаемый по умолчанию, но благодаря Вашим примерам разобрался.

  5. 11
    Игорь
    @

    Если, например, необходимо, чтобы по умолчанию отображался второй блок, тогда нужно переместить класс .visible во второй блок div.box, а также переместить класс .current во второй элемент в списке вкладок.

    почему то это не работает
    в чем может причина?
    ни в одном из 4 примеров

  6. 16
    zorra

    А как наиболее просто и грамотно реализовать кнопку (ссылку), при клике на которую откроется блок (до этого скрытый). Например, есть кнопка (или просто ссылка) «Комментирование», при клике на которую открывается поле для комментирования. При еще одном клике поле пропадает. И так далее…
    Причем, блок со ссылкой и с формой не обязательно идут друг за другом.
    Спрашиваю тут (а не в Гугле), так как доверяю автору блога…

  7. 22
    Alexa

    Приветствую! Спасибо большое за скрипт и все Ваши подсказки!
    Возможно ли разместить в одном блоке горизонтальные и вертикальные вкладки (справа)?
    Пробовала, но получается только, как у вас в примерах отдельными блоками, а не одним….:(
    Заранее, спб. за помощь..

  8. 25
    DiShark.Ru

    Спасибо, сделал по вашему коду — всё работает. Радует то, что можно сделать несколько таких табов на одной странице

  9. 26
    Александр

    Здравствуйте. Спасибо за скрипт, пользуюсь им уже давно. Появился вопрос, а возможно ли отключать конкретные вкладки? Т.е нужно в некоторых случаях скрывать вкладку вместе с содержимым. Спасибо.

  10. 30
    mac0s

    Доброе время суток, Дмитрий.
    Давно заметил ваше, достаточно простое решение с вкладками и сам пользуюсь ими. но сегодня столкнулся с одной, так сказать, неприятностью:
    К примеру на странице «http://www.example.com/page1» есть вкладки с минимум 2мя табами и ссылка на другую страницу с вкладками: «http://www.example.com/page2#tab2», на которой тоже минимум 2 таба.

    Нажав на ссылку «http://www.example.com/page2#tab2» на первой странице скрипт сначала открой второй таб на первой странице, а потом уже перейдет на вторую страницу с открытой второй вкладкой.

    По сему предлагаю пробное решение:

    /**
     * @param {object} aObj объект тега a, по которому был произведен клик
     */
    function checkPath(aObj){
    	var thisPath = window.location.toString().split('/');
    	var toPath = $(aObj).attr('href').toString().split('/');
    	var relativePath = $(aObj).attr('href').toString().indexOf('http',0)<0;
    	if(!relativePath)
    		if(thisPath[2]!==toPath[2]) // проверка домена
    			return false;
    	if(thisPath[3]!==toPath[relativePath?1:3]) // проверка второго уровня адреса (не домена)
    		return false;
    	return true;
    }
    $('a[href*=#tab]').click(function() {
    	if(checkPath(this)){
    		var tabIndex = $(this).attr('href').replace(/(.*)#tab/, '')-1;
    		$('ul.jtabs li').eq(tabIndex).click();
    	}
    });
    

    сравниваем доменные имена и второй уровень адреса (http://example.com/two-level). Решение не универсальное, т.к. адреса могут быть и без второго уровня или эта же страница с GET параметрами.

  11. 31
    mac0s

    …забыл сказать, что это лишь часть кода, отвечающая за клик по ссылке к примеру 4.

  12. 32
    VGL

    У меня возникла проблема с картой Google.
    Добавил код карты (iframe) на вкладку, но при первом переходе на вкладку не отображаются данные на карте. Похоже, что из-за display:none, карта сначала не загружается.
    Как можно решить данную проблему?

  13. 34
    Alexa

    Dimox, а возможно сделать горизонтальные вкладки адаптированными к различному разрешению (Response)?

  14. 36
    Паша

    Спасибо ui, не подходил, а вот ваш вписался хорошо!

  15. 37
    Вадим
    @

    У меня проблема возникла. Выпадающее меню и вкладки… что я уже не делал, все равно сами табы позиционируются поверх выпадающего меню, даже z-index не выручает, есть идеи?

  16. 38
    Андрей

    Как сделать так чтобы видео останавливалось при перключанни вкладок, плеер с VK грузит и не останавливается!

  17. 39
    Денис
    @

    Подскажите, как сделать так что бы при клике по одной вкладке, показывался содержимое срузу и в горизонтальной и в вертикальной вкладке. К примеру я кликаю по Первая вкладка и у меня и в вертикальной и горизонтальной отображается первый блок, по Второй вкладке и там и там второй блок?

  18. 40
    Павел

    а как насчет кроссбраузерности? у меня начинает работать с IE8, 7 уже никак. Так и задумано или я что-то не так делаю?

  19. 42
    u8883

    Твой скрипт с Cookie и LS как я понял работает только если на сайте только 1 таб, бывает так что на сайте их несколько и нужно сохранить для каждого свое значение.

    Может кому-то пригодиться. Для этого я доделал скрипт таким образом:

    1. Сделал для каждого таба свой айди

    <div class="section" data-tab_id="101">

    2. Чтение и установка куков для определенного таба по айди

    	$('ul.tabs').each(function(i) {
    		var tab_id = $('.tsection').data('tab_id');
    		var cookie = readCookie('tabCookie_'+tab_id+'_'+i);
    		if (cookie) $(this).find('li').eq(cookie).addClass('current').siblings().removeClass('current')
    			.parents('div.tsection').find('div.tbox').hide().eq(cookie).show();
    	})
    
    	$('ul.tabs').on('click', 'li:not(.current)', function() {
    		var tab_id = $('.tsection').data('tab_id');
    		$(this).addClass('current').siblings().removeClass('current')
    			.parents('div.tsection').find('div.tbox').eq($(this).index()).fadeIn(150).siblings('div.tbox').hide();
    		var ulIndex = $('ul.tabs').index($(this).parents('ul.tabs'));
    		eraseCookie('tabCookie_'+tab_id+'_'+ulIndex);
    		createCookie('tabCookie_'+tab_id+'_'+ulIndex, $(this).index(), 365);
    	})
    
  20. 44
    G-3p

    Сори, 720 комментариев читать для меня слишком, поэтому спрошу.

    У меня в каждой вкладке по одному видео и при переключении с одной вкладки на другую видео продолжает проигрываться.
    Как сделать чтобы при переключении на другую вкладку содержимое предыдущей прекращало все действия (видео остановилось).

  1. 1

    Видимо, это косяк Файерфокса. А по поводу Вконтакте вот тут описывал решение.

  2. 2
    evgen
    @

    путем нехитрых манипуляций делаем Ваш скрипт еще более универсальным

    (function($) {
    	$(function() {
    
    		$('ul.tabs').delegate('li:not(.current)', 'click', function() {
    			$(this).addClass('current').siblings().removeClass('current')
    				.parents('div.section').eq(0).find('>div.box').hide().eq($(this).index()).show();
    			return false;
    		})
    
    	})
    })(jQuery)
    
    <div class="section">
    
    	<ul class="tabs">
    		<li class="current">Первая вкладка</li>
    		<li>Вторая вкладка</li>
    		<li>Третья вкладка</li>
    		<li>Червертая вкладка</li>
    	</ul>
    
    	<div class="box visible">
    	<!-- Inner Tabs -->
    		<div class="section">
    			<ul class="tabs">
    				<li class="current">inner 1</li>
    				<li>inner 2</li>
    			</ul>
    			<div class="box visible">
    				<h2>inner 1</h2>
    				<p> text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text </p>
    			</div>
    			<div class="box">
    				<h2>inner 2</h2>
    				<p> text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text </p>
    			</div>
    		</div>
    	<!--End Inner Tabs-->
    		<h2>1</h2>
    		<p> Закон внешнего мира, как принято считать, реально рассматривается знак, отрицая очевидное. Гегельянство творит катарсис, хотя в официозе принято обратное. Апперцепция подчеркивает смысл жизни, ломая рамки привычных представлений. Представляется логичным, что адживика откровенна.</p>
    	</div>
    
    	<div class="box">
    		<h2>2</h2>
    		<p> Закон внешнего мира, как принято считать, реально рассматривается знак, отрицая очевидное. Гегельянство творит катарсис, хотя в официозе принято обратное. Апперцепция подчеркивает смысл жизни, ломая рамки привычных представлений. Представляется логичным, что адживика откровенна.</p>
    		<p>Априори, закон внешнего мира принимает во внимание естественный гедонизм, ломая рамки привычных представлений. Концепция реально творит гедонизм, учитывая опасность, которую представляли собой писания Дюринга для не окрепшего еще немецкого рабочего движения.</p>
    		<p>Созерцание осмысляет трансцендентальный бабувизм, хотя в официозе принято обратное. Бабувизм абстрактен. Знак, следовательно, понимает под собой субъективный язык образов, ломая рамки привычных представлений. Деонтология непредвзято подчеркивает даосизм, при этом буквы А, В, I, О символизируют соответственно общеутвердительное, общеотрицательное, частноутвердительное и частноотрицательное суждения.</p>
    	</div>
    
    	<div class="box">
    		<h2>3</h2>
    		<p>Структурализм, как следует из вышесказанного, заполняет из ряда вон выходящий дуализм, однако Зигварт считал критерием истинности необходимость и общезначимость, для которых нет никакой опоры в объективном мире. Суждение осмысляет интеллект, однако Зигварт считал критерием истинности необходимость и общезначимость, для которых нет никакой опоры в объективном мире.</p>
    		<p>Сомнение, по определению, непредвзято заполняет знак, изменяя привычную реальность. Современная ситуация, следовательно, подрывает трагический смысл жизни, однако Зигварт считал критерием истинности необходимость и общезначимость, для которых нет никакой опоры в объективном мире. Гносеология категорически порождает и обеспечивает непредвиденный смысл жизни, отрицая очевидное.</p>
    	</div>
    
    	<div class="box">
    		<h2>4</h2>
    		<p>Деонтология создает примитивный даосизм, открывая новые горизонты. Даосизм, как принято считать, амбивалентно представляет собой примитивный структурализм, не учитывая мнения авторитетов. Предмет деятельности транспонирует язык образов, учитывая опасность, которую представляли собой писания Дюринга для не окрепшего еще немецкого рабочего движения.</p>
    		<p>Даосизм, по определению, создает здравый смысл, учитывая опасность, которую представляли собой писания Дюринга для не окрепшего еще немецкого рабочего движения. Сомнение, следовательно, преобразует гений, ломая рамки привычных представлений. Сомнение трогательно наивно.</p>
    		<p>Жизнь откровенна. Предмет деятельности, как следует из вышесказанного, абстрактен. Искусство, как следует из вышесказанного, нетривиально. Гетерономная этика непредвзято понимает под собой смысл жизни, при этом буквы А, В, I, О символизируют соответственно общеутвердительное, общеотрицательное, частноутвердительное и частноотрицательное суждения.</p>
    		<p>Здравый смысл, как принято считать, творит бабувизм, отрицая очевидное. Суждение, следовательно, амбивалентно. Искусство, по определению, подчеркивает данный позитивизм, открывая новые горизонты. Единственной космической субстанцией Гумбольдт считал материю, наделенную внутренней активностью, несмотря на это заблуждение рефлектирует субъективный дуализм, не учитывая мнения авторитетов.</p>
    	</div>
    
    </div>
    

    теперь можно создавать вложенные табы

  3. 3
    ITech

    Ура! Решил у себя проблему с перепрыгиванием в начало страницы при переключении табов! Вот живой пример: http://injoit.com/what-we-do/

    Реализовал твой код, Dimox, на своем сайте с небольшими изменениями. Вся загвоздка в том, что все div.box необходимо обтянуть еще одним div и для него определить фиксированную высоту!

    Так как у меня контент в табах на сайте постоянно меняется, подключил механизм Math.max.apply для расчета максимально возможной высоты вложенного дива .box. Эту высоту и задавал внешнему диву..

    Для эффекта появления использовал вместо show() animate() с указанием четких параметров:

    (function($) {
    $(function() {
    
    	$('ul.tabs').delegate('li:not(.current)', 'click', function() {
    		$(this).addClass('current').siblings().removeClass('current')
    		.parents('div.section').find('div.box').hide().eq($(this).index()).animate({height: 'auto', width: 'auto', opacity: 'show'}, 'slow');
    	})
    
    /*--Определение максимальной высоты для блока-контейнера .box-wrap--*/
    	Array.max = function(array) {
     return Math.max.apply(Math,array);
     };
    	var heights = $('.box-wrap div.box').map(function() {
     return $(this).innerHeight();
     }).get();
    	$(".box-wrap").height(Array.max(heights));
    /*--------*/
    
    })
    })(jQuery)
    

    И собственно HTML:

    <div class="section vertical">
    <ul class="tabs">
    	<li class="current"><span>Mobile</span></li>
    	<li><span>Social and Web</span></li>
    	<li><span>Cloud</span></li>
    </ul>
    <div class="box-wrap">
    <div class="box visible">
    ---
    </div>
    <div class="box">
    ---
    </div>
    <div class="box">
    ---
    </div>
    </div>
    </div>
    

    Не знаю, правильно я сделал или нет, но главное ведь, что оно работает) Буду рад услышать твои комментарии по данному поводу.

  4. 4
    @

    По теме перепрыгивания вверх при переключении табов.
    В комментариях выше был модифицированный скрипт с определением высоты родительского блока, но если например в табы положить меню-аккордеон (оно там прекрасно работает), то при задании фона табам аккордеон будет вылазить за их пределы.
    И так как вся соль заключается в установке определённой высоты блоку-родителю, можно поступить проще:
    Мне лично помогла установка min-height для родительского блока табов.

    .section {
    	min-height: 1px;
    	}

    проверял в ie7> и нормальных браузерах — вроде бы работает.

  5. 5
    maqsim

    Вместо:
    $(‘ul.tabs’).delegate(‘li:not(.current)’, ‘click’, function() {

    Поставьте:
    $(‘ul.tabs li:not(.current)’).live(‘click’, function() {

    Проблема первого элемента в том, что некорректно связываются события через метод delegate, когда разметка с вкладками подгружена через ajax. Второй вариант работает отлично + мы делаем 1 раз выборку, а не 2

  6. 6
    Metaller

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

    Решение — не прятать все табы, а только ненужные:

    .parents('div.section').find('div.box').eq($(this).index()).fadeIn(150).siblings().hide();
    
  7. 7

    Если кому интересно — ещё одно простое решение для перехода к нужному табу по клику на стороннем элементе.

    $('[data-tab-target]').click(function(e) {
    		$("html, body").animate({scrollTop:$('#'+$(this).data('tab-target')).offset().top-50}, 500); //прокручиваем страницу чуть выше положения цели
    		$('#'+$(this).data('tab-target')).trigger('click');
    		return false;
    	});
    <span data-tab-target="tab-2">перейти к табу #tab-2</span>

    у

    <div class="section">
     <ul class="tabs">
     <li class="current">1-я вкладка</li>
     <li id="tab-2">2-я вкладка</li>
     </ul>
     <div class="box visible">
     Содержимое первого блока
     </div>
     <div class="box">
     Содержимое второго блока
     </div>
    </div><!-- .section -->
  8. 8

    Вот код, который это делает (доработан 4-й пример):

    (function($) {
    $(function() {
    
    	$('ul.tabs__caption').on('click', 'li:not(.active)', function() {
    		$(this)
    			.addClass('active').siblings().removeClass('active')
    			.closest('div.tabs').find('div.tabs__content').removeClass('active').eq($(this).index()).addClass('active');
    	});
    
    	var tabIndex = window.location.hash.replace('#tab','')-1;
    	if (tabIndex != -1) {
    		$('ul.tabs__caption li').eq(tabIndex).click();
    		$('html, body').animate({scrollTop: $('div.tabs__content').eq(tabIndex).offset().top - 50}, 700);
    	}
    
    	$('a[href*=#tab]').click(function() {
    		var tabIndex = $(this).attr('href').replace(/(.*)#tab/, '')-1;
    		$('ul.tabs__caption li').eq(tabIndex).click();
    		$('html, body').animate({scrollTop: $('div.tabs__content').eq(tabIndex).offset().top - 50}, 700);
    	});
    
    });
    })(jQuery);

    Число 50 (в двух местах) — это отступ между блоком и верхней границей окна браузера после прокрутки к блоку. 700 — это скорость прокрутки, в данном случае 0,7 секунды.

Ваш комментарий