Открыть меню    

Вкладки на jQuery

Вы когда-нибудь сталкивались с отрывистым представлением контента по нажатию на вкладку? Такому поведению может быть масса причин: каждой вкладке соответствует свой контент, высота которого различна; или проблема в самом процессе переключения между вкладками (нижний контент прыгает вверх и вниз в тот момент между переключением, когда текущая колонка уже исчезла, а новая еще не показалась). За неимением лучшего термина, те вкладки (tabs), которые ведут себя более «плавно», я называю органичными.

плавные вкладки на jquery

План

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

Использовать будем плагин jQuery, так как вполне возможно, что на одной странице может находиться несколько областей с вкладками.

HTML

Сперва нам понадобиться элемент-обертка, который вместит в себя все вкладки с контентом. Этот элемент и будет передаваться плагину. Внутри этого элемента под вкладки создадим неупорядоченный список. Каждая вкладка имеет атрибут href, значение которого соответствует id неупорядоченного списка (контент вкладки), этим мы связываем вкладку с контентом. Контент вкладок находится в блоке с классом list-wrap. Сам контент вкладок - это простой неупорядоченный список. Ключевым элементом является блок с классом list-wrap, так как в зависимости от его высоты и будет происходить анимация между вкладками.

HTML

<div id="example-one">

 <ul class="nav">
   <li class="nav-one"><a href="#featured" class="current">Featured</a></li>
   <li class="nav-two"><a href="#core">Core</a></li>
   <li class="nav-three"><a href="#jquerytuts">jQuery</a></li>
   <li class="nav-four last"><a href="#classics">Classics</a></li>
 </ul>

    <div class="list-wrap">

		<ul id="featured">
			<li>Stuff in here!</li>
		</ul>

		 <ul id="core" class="hide">
			<li>Stuff in here!</li>
		 </ul>

		 <ul id="jquerytuts" class="hide">
			<li>Stuff in here!</li>
		 </ul>

		 <ul id="classics" class="hide">
			<li>Stuff in here!</li>
		 </ul>

    </div> <!-- END List Wrap -->

 </div> <!-- END Organic Tabs (Example One) -->

CSS

Ничего необычного делать не будем, просто постараемся, чтобы все выглядело так, как положено. Не стесняйтесь работать со своим дизайном, так как он почти не накладывает никаких ограничений на работу плагина. В демо вы увидите горизонтальный ряд вкладок. Текущая (выбранная) вкладка имеет свой цвет.

CSS

/* Specific to example one */

#example-one 
    { background: #eee; padding: 10px; margin: 0 0 15px 0;
 -moz-box-shadow: 0 0 5px #666; -webkit-box-shadow: 0 0 5px #666; }

#example-one .nav 
    { overflow: hidden; margin: 0 0 10px 0; }
#example-one .nav li 
    { width: 97px; float: left; margin: 0 10px 0 0; }
#example-one .nav li.last 
    { margin-right: 0; }
#example-one .nav li a 
    { display: block; padding: 5px; background: #959290; 
color: white; font-size: 10px; text-align: center; border: 0; }
#example-one .nav li a:hover 
    { background-color: #111; }

#example-one ul 
    { list-style: none; }
#example-one ul li a 
    { display: block; border-bottom: 1px solid #666; padding: 4px; color: #666; }
#example-one ul li a:hover, #example-one ul li a:focus 
    { background: #fe4902; color: white; }
#example-one ul li:last-child a 
    { border: none; }

#example-one li.nav-one a.current, ul.featured li a:hover 
    { background-color: #0575f4; color: white; }
#example-one li.nav-two a.current, ul.core li a:hover 
    { background-color: #d30000; color: white; }
#example-one li.nav-three a.current, ul.jquerytuts li a:hover
     { background-color: #8d01b0; color: white; }
#example-one li.nav-four a.current, ul.classics li a:hover 
    { background-color: #FE4902; color: white; }

Перед нами есть задача: спрятать все блоки с контентом за исключением того, который стоит по умолчанию. Существует несколько способов решения: можно воспользоваться объявлением display: none (CSS), можно воспользоваться функцией .hide() (javascript). Оба эти способа имеют при этом свои недостатки. Для CSS это проблема с доступностью, у javascript вероятна ситуация, когда при первоначальной загрузке скрытые блоки на миг показываются, а затем коряво исчезают. Поэтому будем использовать следующую комбинацию:

CSS

/* Generic Utility */
.hide { position: absolute; top: -9999px; left: -9999px; }

Далее поработаем над плагином. Сбросим значения и спрячем блоки hide при помощи javaScript. Таким образом, эти блоки будут готовы к показу в случае необходимости (а не вышвырнуты за страницу).

jQuery

Вот план нашего плагина.

1. Когда объявили элемент.

2. Скрываем блоки с классом hide

3. По клику на вкладке...

4. Если это не текущая вкладка...

5. ... и ничего не анимируется в данный момент

6. Установите высоту текущего блока по заданной высоте текущего контента

7. Установите подсветку от текущей вкладки к правильной вкладке

8. Текущий контент исчезает

9. Новый контент появляется

10. Производим анимацию высоты внешнего блока по высоте нового контента

JQuery

(function($) {
    // плагин
    $.organicTabs = function(el, options) {
        // для javascript
        var base = this;
        // использем в  jQuery
        base.$el = $(el);
        // навигация у переданного в плагин селектора		
        base.$nav = base.$el.find(".nav");
        // выполняется при вызове плагина
        base.init = function() {
            // Замещаем  опции, если есть		
            base.options = $.extend({},$.organicTabs.defaultOptions, options);

            // Скрываем блоки с классом .hide
            $(".hide").css({
                "position": "relative",
                "top": 0,
                "left": 0,
                "display": "none"
            }); 
            // установим обработчик события click,
// всем  дочерним ссылкам элемента li (ВКЛАДКАМ)
            base.$nav.delegate("li > a", "click", function() {

                // Вычисляем href  текущего списка  по классу CSS (функция substring 
// начнет отсчет с 1-й буквы, то есть отбросит # у  атрибута href)
                var curList = base.$el.find("a.current").attr("href").substring(1),

                // Нажатая вкладка, сюда переместится список
                    $newList = $(this),

                // ID нового списка
                    listID = $newList.attr("href").substring(1),

                // Вычисляем  высоту внешнего контейнера (.list-wrap) 
// для текущего внутреннего списка
                    $allListWrap = base.$el.find(".list-wrap"),
                    curListHeight = $allListWrap.height();
                $allListWrap.height(curListHeight);
                // если ID вкладки, по которой кликнули не равен href 
// текущего списка и  кол-во элементов, кот. учавствуют в анимации равно 0 
                if ((listID != curList) && ( base.$el.find(":animated").length == 0)) {

                    // Прячем текущий список
                    base.$el.find("#"+curList).fadeOut(base.options.speed, function() {

                        // Выводим новый список в callback-функции
                        base.$el.find("#"+listID).fadeIn(base.options.speed);

 // выравниваем внешний контейнер так, чтобы он прижимался к новому списку
                        var newHeight = base.$el.find("#"+listID).height();
                        $allListWrap.animate({
                            height: newHeight
                        });

                        // Удаляем подсветку у текущей вкладки 0 добавляем новой
                        base.$el.find(".nav li a").removeClass("current");
                        $newList.addClass("current");

                    });

                }   

                // Не будет работать как обычная ссылка.
                // Останавливаем дальнейшую обработку
                return false;
            });

        };
        base.init();
    };

    $.organicTabs.defaultOptions = {
        "speed": 300
    };

    $.fn.organicTabs = function(options) {
        return this.each(function() {
            (new $.organicTabs(this, options));
        });
    };

})(jQuery);

Используя plugin

Подобно остальным модулям, сперва вам понадобиться загрузить библиотеку jQuery, затем файл, в котором лежит плагин, ну и наконец, вызываем сам плагин.

<script type='text/javascript' 
src='http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js'></script>
<script type="text/javascript" src="js/organictabs.jquery.js"></script>
<script type='text/javascript'>
    $(function() {

        $("#example-one").organicTabs();

        $("#example-two").organicTabs({
            "speed": 200
        });

    });
</script>   

Источник

Комментарии к статье