jQuery для начинающих. Часть 2. JavaScript Меню.

Categories: JavaScript

В первой части были рассмотрены базовые принципы работы селекторов и приведены несколько примеров, в данной статье я постараюсь акцентировать внимание на реализации JavaScript меню для Вашего сайта.

Если Вам готовый код наглядней документации, то переходим от слов к делу, т.е. на страницу с примерами.

Slide меню

Два slide-меню на странице: вверху и внизу.

Кликаем по ссылке с классом “btn-slide”, выезжает панель с меню.

Частично данный пример присутствует в первой части, так что особо углубляться в реализацию не буду, приведу лишь JavaScript код с пояснениями:

<script type="text/javascript">
// когда страница загрузится
$(document).ready(function(){
	// вешаем обработчик на ссылку с классом "btn-slide" (верхнее меню)
	$(".btn-slide").click(function(){
		// выдвигаем/прячем панель с id = panel1
		$("#panel1").slideToggle("slow");
		// изменяем класс самой ссылки
		$(this).toggleClass("active");
		// и ничего не делаем дальше (дабы не было перехода по ссылки)
		return false;
	});

	// вешаем обработчик на ссылку с классом "btn-slide2" (нижнее меню)
	$(".btn-slide2").click(function(){
		// выдвигаем/прячем панель с id = panel2
		$("#panel2").slideToggle("slow");
		// изменяем класс самой ссылки
		$(this).toggleClass("active2");
		// и ничего не делаем дальше (дабы не было перехода по ссылки)
		return false;
	});
});
</script>

Slide меню 2

Slide-меню слева и справа страницы. Для начала приготовим HTML :

<div class="left">
    <!-- Непосредственно содержание меню, мы его прячем -->
    <div class="panel">
    	<ul>
    	   <li><a href="#" title="Элемент 1">Элемент 1</a></li>
    	   <li><a href="#" title="Элемент 2">Элемент 2</a></li>
    	   <li><a href="#" title="Элемент 3">Элемент 3</a></li>
    	</ul>
    	<ul>
    	   <li><a href="#" title="Элемент 1">Элемент 1</a></li>
    	   <li><a href="#" title="Элемент 2">Элемент 2</a></li>
    	   <li><a href="#" title="Элемент 3">Элемент 3</a></li>
    	</ul>
    	<ul>
    	   <li><a href="#" title="Элемент 1">Элемент 1</a></li>
    	   <li><a href="#" title="Элемент 2">Элемент 2</a></li>
    	   <li><a href="#" title="Элемент 3">Элемент 3</a></li>
    	</ul>
    </div>
    <!-- Панелька с кнопкой -->
    <p class="slide"><a href="#" class="btn-slide">Меню</a></p>
</div>

У нас должно получиться что-то наподобие следующего:

Теперь создадим обработчик событий для ссылок с классом “btn-slide”:

	// создаем обработчик событий для ссылок с классом "btn-slide"
	$(".btn-slide").toggle(function(){
		// ... 1-ый клик по ссылке
		// возвращаем false
		return false;
	},function(){
		// ... 2-ой клик по ссылке
		// возвращаем false
		return false;
	});

Затем нам необходимо найти элемент с классом “panel” и выдвинуть его на 120 пикселей:

// идем по DOM'у на 2-а уровня вверх, внутри элемента (это div c классом left/right) находим нужный нам элемент и приращиваем ему 120 пикселей в ширину
$(this).parent().parent().find(".panel").animate({"width": "+=120px"}, "slow");
// заменяем класс кнопки (для изменение стрелочки)
$(this).toggleClass("active");

Соединяем это вместе:

$(document).ready(function(){
	$(".btn-slide").toggle(function(){
		$(this).parent().parent().find(".panel").animate({"width": "+=120px"}, "slow");
		$(this).toggleClass("active"); return false;
	},function(){
		$(this).parent().parent().find(".panel").animate({"width": "-=120px",opacity: "hide"}, "slow");
		$(this).toggleClass("active"); return false;
	});
});

Drop-down меню

Одна из самых распространенных реализаций меню для сайта это горизонтальное выпадающее меню, его конечно можно реализовать при помощи CSS, но статья у нас о jQuery, так что будем орудовать оным. Начнем с HTML’a (замечу, что для всех остальных примеров код практически не отличается):

Ну и собственно сам HTML:

    <div class="topmenu">
        <ul>
            <li><a href="#" title="Меню 1">Меню 1</a>
                <ul>
            	   <li><a href="#" title="Элемент 1.1">Элемент 1.1</a></li>
            	   <li><a href="#" title="Элемент 1.2">Элемент 1.2</a></li>
            	   <li><a href="#" title="Элемент 1.3">Элемент 1.3</a></li>
                </ul>
            </li>
            <li><a href="#" title="Меню 2">Меню 2</a>
                <ul>
            	   <li><a href="#" title="Элемент 2.1">Элемент 2.1</a></li>
            	   <li><a href="#" title="Элемент 2.2">Элемент 2.2</a></li>
            	   <li><a href="#" title="Элемент 2.3">Элемент 2.3</a></li>
                </ul>
            </li>
            <li><a href="#" title="Меню 3">Меню 3</a>
                <ul>
            	   <li><a href="#" title="Элемент 3.1">Элемент 3.1</a></li>
            	   <li><a href="#" title="Элемент 3.2">Элемент 3.2</a></li>
            	   <li><a href="#" title="Элемент 3.3">Элемент 3.3</a></li>
                </ul>
            </li>
        </ul>
    </div>

Далее нам необходимо добавить обработчик для события hover для элементов li:

    $('.topmenu ul li').hover(
        function() {
            // ...
        },
        function() {
            // ...
        }
    );

И отображаем под-меню:

// находим элемент ul и вызываем анимацию slideDown
$(this).find('ul').slideDown();
// изменяем фон выбранного элемента путем добавления класса active
$(this).addClass("active");

А теперь всё вместе:

$(document).ready(function(){
    $('.topmenu ul li').hover(
        function() {
            $(this).addClass("active");
            $(this).find('ul').stop(true, true); // останавливаем всю текущую анимацию
            $(this).find('ul').slideDown();
        },
        function() {
            $(this).removeClass("active");
            $(this).find('ul').slideUp('fast');
        }
    );
});

Drop-down AJAX меню

Горизонтальное выпадающее меню с подгрузкой элементов AJAX’ом.
Для начала нам понадобится само меню:

    <div class="topmenu">
        <ul>
            <li id="menu1"><a href="#" title="Меню 1">Меню 1</a></li>
            <li id="menu2"><a href="#" title="Меню 2">Меню 2</a></li>
            <li id="menu3"><a href="#" title="Меню 3">Меню 3</a></li>
        </ul>
    </div>

И заготовки для подменю, назовем их menu1.html, menu2.html и menu3.html – по id соответствующих элементов меню (скорей всего данные элементы будут генерироваться динамически, но для упрощения примера используем статические странички):

Пример menu1.html:

<ul>
    <li><a href="#" title="Элемент 1">Элемент 1</a></li>
    <li><a href="#" title="Элемент 2">Элемент 2</a></li>
    <li><a href="#" title="Элемент 3">Элемент 3</a></li>
</ul>

Теперь, как и в предыдущем примере, нам необходим обработчик события hover:

$(document).ready(function(){
    $('.topmenu ul li').hover(
        function() {
            // ... тут необходимо внести изменения в код
            $(this).addClass("active");
        },
        function() {
            // тут оставляем так как есть
            $(this).removeClass("active");
            $(this).find('ul').slideUp('fast');
        }
    );
});

Теперь необходимо загрузить недостающие элементы меню посредством AJAX’a:

// получаем id активного элемента меню
var id = $(this).attr('id');
// запихиваем активный элемент в локальную переменную
var li = $(this);
$.ajax({
     // формируем имя запрашиваемой посредством AJAX страницы
     url: 'ajax/'+id+'.html',
     beforeSend: function(){
          // перед тем как "спросить" изменяем класс элемента - отображаем loading картинку
          li.addClass('loading');
     },
     success: function(data){
          // наполняем подменю
          li.append(data);
          // показываем что получилось
          li.find('ul').slideDown();
          // убираем loading картинку
          li.removeClass('loading');
     }
});

Собираем:

$(document).ready(function(){
    $('.topmenu ul li').hover(
        function() {
            // добавляем проверочку - не загружали ли до этого элементы
            if ($(this).find('ul').length == 0) {
                var id = $(this).attr('id');
                var li = $(this);
                $.ajax({
                    url: 'ajax/'+id+'.html',
                    beforeSend: function(){
                         li.addClass('loading');
                    },
                    success: function(data){
                         li.append(data);
                         li.find('ul').stop(true, true); // останавливаем всю текущую анимацию
                         li.find('ul').slideDown();
                         li.removeClass('loading');
                    }
                });
            } else {
                $(this).find('ul').stop(true, true); // останавливаем всю текущую анимацию
                $(this).find('ul').slideDown();
            }
            $(this).addClass("active");
        },
        function() {
            $(this).find('ul').slideUp('fast');
            $(this).removeClass("active");
        }
    );
});

Drop-down меню

Вертикальное выпадающее меню. Достаточно простенький примерчик:

$(document).ready(function(){
    // добавить обработчик события hover
    $('.topmenu ul li').hover(
        function() {
            $(this).find('ul:first').stop(true, true);
            $(this).find('ul:first').slideDown();
        },
        function() {
            $(this).find('ul:first').slideUp('fast');
        }
    );
    // всем элементам меню с вложенностью добавить символ &raquo;
    $('.topmenu li:has(ul)').find('a:first').append('&raquo;');
});

Float меню

Плавающее меню. Нам понадобится плагин Dimensions (дабы работали методы height() и width()) – для jQuery 1.3.x данный плагин уже не нужен. Ну с HTML я думаю, Вы разберетесь:

Теперь по порядку – начнем с получение информации о текущем расположении “плавающих” меню:

// получаем информацию из css о расположении верхнего меню
menu1 = parseInt($(".right").css("top").substring(0,$(".right").css("top").indexOf("px")));
// расположении нижнего меню вычисляем отталкиваясь от размеров окна (96 взято на глаз)
menu2 = $(window).height() - 96;

Далее, нам необходимо “повесить” свою функцию для события scroll:

$(window).scroll(function () {
// тут будем перетаскивать наши меню
});

Ну и собственно наполнение:

$(window).scroll(function () {
	// определяем новое положение для наших меню
	offset1 = menu1 + $(document).scrollTop() + "px";
	offset2 = menu2 - $('.left .panel').height() + $(document).scrollTop() + "px";

	// перетаскиваем элементы на новое место
	$('.right').animate({top:offset1},{duration:500,queue:false});
	$('.left').animate({top:offset2},{duration:1000,queue:false});
});

Так же добавим отображение/скрытие элементов подменю:

    // для всех элементов "a" которые находятся в "li" со вложенными списками "ul"
    $('.panel ul li:has(ul) a').click(function() {
        // идем к паренту, находим "ul" и прячем/скрываем его
        $(this).parent().find('ul').slideToggle();
        return false;
    });
    // кнопка "+" - скрываем все "ul" вложенные в "li"
    $('a.plus').click(function(){
       // идем к паренту, находим следующий элемент в доме, ищем в нем "ul li ul", выполняем "slideUp"
       $(this).parent().next().find('ul li ul').slideUp('fast');
       return false;
    });
    // кнопка "-" - отображаем все "ul" вложенные в "li"
    $('a.minus').click(function(){
       // идем к паренту, находим следующий элемент в доме, ищем в нем "ul li ul", выполняем "slideDown"
       $(this).parent().next().find('ul li ul').slideDown('slow');
       return false;
    });

Так же Вы можете скачать все примеры в одном архиве.

Цикл статей

  1. jQuery для начинающих
  2. jQuery для начинающих. Часть 2. JavaScript Меню
  3. jQuery для начинающих. Часть 3. AJAX
  4. jQuery для начинающих. Часть 4. Селекторы

This entry was posted on Wednesday, August 6th, 2008 at 07:59 and is filed under JavaScript.
You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Другие посты на эту тему

44 Responses to “jQuery для начинающих. Часть 2. JavaScript Меню.”

  1. Andrey

    ЗДОРОВО! Спасибо за статью и примеры!

  2. Init0

    Огромное спасибо, на примерах изучать намного проще.

  3. Dmitry

    Здорово. Самое главное что все просто и гениально.
    Есть только один вопрос:
    Когда элементов подменю становится слишком много (больше 3 или 4) появляется необходимость применить settimeout на onmouseout, что бы при случайном соскальзывании с маршрута меню не исчезало.
    Как это реализовать?

  4. Antonhb

    Спасибо за статью) Вот только одна проблема. В сафари 3.1 пример Slide меню 2 немного криво работает.. Там картинка сползает под меню с элементами =\

  5. [...] jQuery для начинающих. Часть 2. JavaScript Меню. [...]

  6. anonymous

    float menu fail

  7. @anonymous:
    хотел было спросить в каком браузере – да сам увидал, что в Опере…

  8. anonymous

    при 120% размере шрифта в винде дивы стандартно так не помещаются в некотрых меню)

  9. Владимир

    спасибо, Антон, статья просто отличная!)

  10. [...] Антон Шевчук, ведущий блога для web-разработчиков, опубликовал 2ю часть статьи из серии “jQuery для начинающих”, в которой рассказывает о том как сделать JavaScript меню. [...]

  11. Bagira

    Можно ли реализовать меню, подобное drop-down, если его структура содержится в таблице, а не в списке? Как в таком случае получить доступ к пунктам меню.

  12. Bagira

    Есть такая структура. Необходимо написать меню на js, с использованием jquery: каждому пункту горизонтального меню первого уровня соответствует выпадающее горизонтальное меню, а каждому пункту горизонтального меню(второй уровень вложенности) соответствует выпадающее вертикальное меню(3- ий уровень). Я никогда не писала на js, сделать надо быстро.

    <!-- MENU -->
    <div id="menu-container ">
    <table id="dark">
    <tr>
    <td class="left">
    <img src="img/x.gif" hspace="0" vspace="0">
    </td>
    <td class="container">
    <table class="menu">
    <tr>
    <td class="left"></td>
    <td class="items">
    <a class="item" href="">Пункт меню 1</a> //первый уровень , горизонтальное меню
    <img src="img/x.gif">
    <a class="item" href="">Пункт меню 2</a>
    <img src="img/x.gif">
    <a class="item" href="" id="selected">Пункт меню 3 </a>
    <img src="img/x.gif">
    <a class="item" href="">Пункт меню 4</a>
    </td>
    <td class="right"></td>
    </tr>
    </table>
    </td>
    <td class="right">
    <img src="img/x.gif" hspace="0" vspace="0">
    </td>
    </tr>
    </table>
    <table id="light"> // горизонтальное меню второго уровня
    <tr>
    <td class="left">
    <img src="img/x.gif" hspace="0" vspace="0">
    </td>
    <td class="container">
    <table class="menu">
    <tr>
    <td class="left"></td>
    <td class="items">
    <a class="item" href="">Пункт меню</a>
    <img src="img/x.gif">
    <a class="item" href="">Пункт меню в две строкивфаыва</a>
    <img src="img/x.gif">
    <a class="item" href="" id="selected">Пункт меню в две строки fdsgsdfgs sdfg sdf g</a>
    <img src="img/x.gif">
    <a class="item" href="">Пункт меню в две строки</a>
    </td>
    <td class="right"></td>
    </tr>
    </table>
    </td>
    <td class="right">
    <img src="img/x.gif" hspace="0" vspace="0">
    </td>
    </tr>
    </table>
    </div>
    
    <!-- CONTENT -->
    
    <div id="contenter">
    
    <!-- dropdown menu - меню третьего уровня -->
    <div id="sub-menu">
    <a href="">Пункт менюхи1</a>
    <div><img src="img/x.gif" hspace="0" vspace="0"></div>
    <a href="">Пункт менюхи2 sdf sdf sdf sdf sdf sdf sdf sdf sdf </a>
    <div><img src="img/x.gif" hspace="0" vspace="0"></div>
    <a href="">Пункт менюхи3</a>
    </div>
    <!-- end of dropdown menu -->

    Можно ли использовать что-то такого типа, как для вашего dropdown меню:

    <script type="text/javascript" src="jss/jquery-1.2.6.min.js"></script>
    
    	<script language="JavaScript" type="text/javascript">
        	    $(document).ready(function(){
                $("div#menu-container table#dark td.container table.menu td.items a.item").hover(
                    function() {
                        <!--$(this).addClass("active");-->
                        $(this).find("div#menu-container table#light td.container table.menu td.items a.item").slideDown();
                    },
                    function() {
                        <!--$(this).removeClass("active");-->
                        $(this).find('td.items').slideUp('fast');
                    }
                );
            });
    
    	</script>
    
  13. AppaL

    красиво, сделал! Благодарю!!!

  14. [...] jQuery для начинающих. Часть 2. JavaScript Меню [...]

  15. [...] jQuery для начинающих. Часть 2. JavaScript Меню [...]

  16. Vlad

    спасибо за статью, в пример Slide меню в iE 7 разъезжается раметка

  17. Gleb

    Да интересно только во float(попробуйте в ссылке заместо # поставить хотя бы index.html) меню не работают ссылки…
    и что же это может быть?

  18. [...] jQuery для начинающих. Часть 2. JavaScript Меню [...]

  19. num

    спасибо за статью! =)

  20. [...] статей “jQuery для начинающих”, в четырех частях (1,2,3 и [...]

  21. Вот такой вот у меня прикол:
    Делаю полностью по инструкции, всё работает, но первоначальное состояние меню – раскрытое, а по идее должно быть спрятано, и в предыдущей статье в примерах тоже самое.

  22. рабоаит)))

  23. Безнадега какае-то! Не могу сделать так, что бы выплывающее меню при первом открытии страницы НЕ появлялось.
    Вот что у меня:

    $(document).ready(function(){
        $('.topmenu').hover(
            function() {
                $(this).addClass("active");
                $(this).find('ul').slideDown();
            },
            function() {
                $(this).removeClass("active");
                $(this).find('ul').slideUp('fast');
            }
        );
    });
    

    Вот CSS для меню:

    a:focus {
    	outline: none;
    }
    .topmenu {
        float:right;
    }
    .topmenu ul, .topmenu ul li{
        list-style:none;
        margin: 0;
        padding: 0;
    }
    .topmenu ul li {
    	position:relative;
    	width:140px;
    }
    .topmenu ul li a{
    	display:block;
    	padding:2px 2px 2px 2px;
    	color:#FFFFFF;
    	text-decoration: none;
    	border:1px dotted #999;
    	margin:1px;
    }
    .topmenu ul li a:HOVER{
        color:#000000;
        background-color:#FFFFFF;
    }
    

    И вот часть html где меню:

    ...
    <table width="100%" border="0" cellpadding="0" cellspacing="0">
                  <tr>
                    <td class="fon_menu1"><div class="topmenu"><a href="info.html" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('ИНФОРМАЦИЯ','','images/AG2_5.jpg',1)"><img src="images/AG_5.jpg" alt="ИНФОРМАЦИЯ" name="ИНФОРМАЦИЯ" width="234" height="38" border="0"></a>
                    <div align="center">
                       <ul>
                           <li><a href="about_stone.html">О КАМНЕ</a></li>
                           <li><a href="about.html">О СЕБЕ</a></li>
                           <li><a href="lern.html">К СВЕДЕНИЮ</a></li>
                       </ul></div>
                       </div>
                    </td>
                  </tr>
                  <tr>
                    <td class="fon_menu2"><div class="topmenu"><a href="img.html" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('ГАЛЕРЕЯ','','images/AG2_6.jpg',1)"><img src="images/AG_6.jpg" alt="ГАЛЕРЕЯ" name="ГАЛЕРЕЯ" width="234" height="34" border="0"></a>
                    <div align="center"><ul>
                           <li><a href="#">КАРТИНЫ</a></li>
                           <li><a href="#">АБСТРАКЦИИ</a></li>
                           <li><a href="#">ШКАТУЛКИ</a></li>
                           <li><a href="#">СТОЛЕШНИЦЫ</a></li>
                           <li><a href="#">ПРОЧЕЕ</a></li>
                           <li><a href="#">В ПРОЦЕССЕ</a></li>
                    </ul></div>
                    </div>
                    </td>
                  </tr>
    ...
    

    Что надо поменять, что бы выплывающее меню было не сразу и потом пропадало только как мышку наведешь и убирешь, а сразу его не было.
    Вот сам сайт полностью:
    http://www.holdfast.ru/ag/img.html

  24. Rider

    Заметил глюк в примере “Drop-down меню” наблюдается в FireFox 3.0.10 : при наведении на пункт родительского меню выпадает дочернее, затем если курсор увести в сторону, а потом навести его на пункт дочернего меню, пока оно не успело свернуться меню начинает закрываться и открываться бесконечно.
    А вообще классная статья.

  25. На мой первый вопрос такой быстрый ответ был. А на главный жду ответа уже который день. Сам пробую переделат, но ни как… Уже по разному изменял, нужна квалифицированная помошь! Мой вопрос выше, через одного. Почему сразу идет показ тех меню, которые должны всплывать при навелении? Мне кажется нужно дописать, а не исправлять. Помогите, пожалуйста!

    • CSS:

      .topmenu ul{
          display: none;
      }
      
      • Вот спасибо! А я пробовал так делать раньше, но не туда поставил display:none. Сейчас тоже поставил в одно место не работало вообще, а потом в другое и все ок. Спасибо!

  26. [...] jQuery для начинающих. Часть 2. JavaScript Меню – 10 873 [...]

  27. Max

    А как избавиться от касяка с “Drop-down меню”, который заметил Rider?

  28. статья зачетна!

  29. Sagor

    Добрый день.
    А проблема с “Drop-down меню” так и не решена?

  30. Sania

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

    $(document).ready(function(){
        $('.topmenu ul li').click(
            function() {
               $(this).find('ul').slideDown();
            }
    	);
    });
  31. slava

    Добрый день!
    Подскажите, пожалуйста, как сделать ссылки в Float-меню кликабельными.
    Там проблема (проверил во всех браузера): ссылки “Элемент 1″..”Элемент 3″ не срабатывают на клик (срабатывают только при использовании контекстного меню или средней кнопой миши).
    ЗЫ: отступы между пунктами в IE6 значительно больше.

    • Пример исправил

      P.S. IE6 считаю умершим…

      • nikki

        примеры не работающие, особенно dd3
        по поводу ie6. хм. зря батенка, его еще долго терпеть придется (

        зы. Hmmm, your comment seems a bit spammy. We’re not real big on spam around here.
        Please go back and try again.

        ну очень сильно напрягает

      • Ваш комментарий действительно похож на спам, нет информации для понимания в чем именно проблема.
        И да – IE6 умер, для некрофилов – отдельные расценки…

  32. Andrey24may

    Подскажите, пожалуйста, а как сделать, что текст снизу меня не сдвигался, а накрывался этой панелью (Slide)

  33. Артур

    Спасбиа за публикации ваших статей о jQuery очень полезно …особенно в такое время ….и если можно то пожалуста опубликуйте парочку статей про Cappucino

  34. kod

    Интересная особенность (но наверное она наследуется от библиотеки).
    В противоположных меню (верх/низ и лево/право) различно реализована анимация.
    Т.е. в одном случае сам “блок с элементами” остается неподвижным и скрытие/открытие происходит над ним, а в другом случае “блок с элементами” двигается сам, как-бы выезжая из-за края экрана.

    Можно ли этим манипулировать, или остается принять как данность?

  35. shkon

    Добрый день. Ребята подскажите как сделать вот такое меню.
    http://www.client-server.ru/index3.jpg
    Чтобы было горизонтальное и раздвигалось вправо при наведении на блок. Уже неделю парюсь не получается(((

Leave a Reply

Copyright © 2007-2010, Anton Shevchuk. Powered by WordPress

MAXCACHE: 0.29MB/0.00043 sec