Страницы

Поиск по вопросам

среда, 18 декабря 2019 г.

Алгоритм работы интересного меню

#javascript #jquery


Всем привет!
Подскажите, как можно реализовать такое меню (на jQuery):

Схематично нарисовано:



Суть работы:

При уменьшении размера экрана (.on('resize') или при маленьком экране, пункты меню
которые не помещаются $(document).width(), перемещаются из главного ul списка в второстепенный,
как показано на картинке.
При обратном действии (т.е при увеличении размера экрана), пункты меню которые уже
можно отобразить - отображать.
Ширина li - автоматическая, в зависимости от содержимого.

Мое решение:

В массив занес все значения ширины каждого отдельного элемента li.
После загрузки страницы и изменения размера экрана, выполнял функцию, которая:
Проверяла ширину всего меню и ширину всего документа.
ЕСЛИ ширина документа меньше ширины меню:

меню.children('li').slice(последний-элемент).prependTo(второстепенное-меню);


В рекурсии прогонял, пока, не подтверждалась, ЧТО ширина документа больше ширины
меню, тогда, пытался вставить первый пункт второстепенного меню в конец и проверить
еще раз ширину меню и ширину экрана(окна). 
Если, при этом, ширина меню меньше ширины экрана, то добавлял элемент в главное меню:

второстепенное-меню.children('li').slice(0, 1).appendTo(меню);


Все работало, НО работало очень плохо - постоянно мигало, иногда вставляло элемент,
когда он не подходил по ширине. Вот такая вот "печальбеда" 

Интересно, как бы вы решили такую задачу (алгоритм - что проверять? от чего отталкиваться)?
Возможно, есть уже готовое решение моей проблемы? Может есть какая-то библиотека jQuery?

Только учусь...
    


Ответы

Ответ 1



попробуйте так $().ready(function() { //we reconstruct menu on window.resize $(window).on("resize", function(e) { var parentWidth = $("#nav-bar-filter").parent().width() - 40; var ulWidth = $("#more-nav").outerWidth(); var menuLi = $("#nav-bar-filter > li"); var liForMoving = new Array(); //take all elements that can't fit parent width to array menuLi.each(function() { ulWidth += $(this).outerWidth(); if (ulWidth > parentWidth) { console.log(ulWidth); liForMoving.push($(this)); } }); if (liForMoving.length > 0) { //if have any in array -> move em to "more" ul e.preventDefault(); liForMoving.forEach(function(item) { item.clone().appendTo(".subfilter"); item.remove(); }); } else if (ulWidth < parentWidth) { //check if we can put some 'li' back to menu liForMoving = new Array(); var moved = $(".subfilter > li"); for (var i = moved.length - 1; i >= 0; i--) { //reverse order var tmpLi = $(moved[i]).clone(); tmpLi.appendTo($("#nav-bar-filter")); ulWidth += $(moved[i]).outerWidth(); if (ulWidth < parentWidth) { $(moved[i]).remove(); } else { ulWidth -= $(moved[i]).outerWidth(); tmpLi.remove(); } } } if ($(".subfilter > li").length > 0) { //if we have elements in extended menu - show it $("#more-nav").show(); } else { $("#more-nav").hide(); } }); $(window).trigger("resize"); //call resize handler to build menu right }); body { font-family: verdana; color: #999999; font-size: 12px; font-weight: bold; text-transform: uppercase; } .row { width: 1020px; } #more-nav { display: none; vertical-align: top; padding-left: 0; width: 150px; } .subfilter { padding-left: 0; } .subfilter>li { padding: 0 8px; list-style-type: none; } .subfilter>li>a { display: block; padding: 4px 8px; } #nav-bar-filter>li { display: inline-block; } #nav-bar-filter { padding-left: 0; } a { text-decoration: none; color: inherit; } li { list-style-type: none; padding: 0 8px; } #nav-bar-filter, #more-nav { display: inline-block; } .subfilter { display: block; }

Комментариев нет:

Отправить комментарий