Проблема с рекурсией и циклом (можно ли упростить?)
Возникает переполнение стека из за рекурсии и цикла внутри.
Подскажите как можно по другому реализовать. Вообщем задача была такая, есть горизонтальное меню с любым кол-вом элементов. Все пункты идут в одну линию. Если они не помещаются в контейнер, который во всю ширину выделенной ему области, то не поместившиеся пункты должны скрываться. Это всё должно происходить при загрузке страницы и при ресайзе окна браузера. Сделал с использованием рекурсии и местами цикл. В рекурсии делается проверка, всели пункты помещаются, если нет, то скрываем последний и проверяем снова, если скрывать не нужно, то проверяем поместится ли первый скрытый пункт, если да то показываем его и проверяем снова. Цикл использовал для определения суммарной длинны всех видимых элементов (для сравнения в рекурсии) Ниже привел код, из-за нескольких таких меню (4-6) на странице, при ресайзе виснет хром и ошибка о переполнение стека в консоли. Подскажите выход пожалуйста, что-то додуматься до другого варианта не смог function assayOne($this) { if(($this).width() < widthChildren($this)) { hideVisible($this) assayOne($this) } else assayTwo($this) } function assayTwo($this) { var widthChildren = widthChildren($this) var widthLastHidden = widthLastHidden($this) if($this.children('.hide').length && $this.width() >= widthChildren + widthLastHidden) { showHidden($this) assayTwo($this) } } function widthLastHidden($this) { var hidden = $this.children('.hide').last() var width = 0 hidden.removeClass('hide') width = hidden.outerWidth(true) hidden.addClass('hide') return width } function widthChildren($this) { var width = 0 var item = $this.children(':not(.hide)') item.each(function() { width = width + $(this).outerWidth(true) }) return width } function showHidden($this) { var hidden = $this.children(':not(.additional).hide').last() hidden.removeClass('hide') } function hideVisible($this) { var visible = $this.children(':not(.additional):not(.hide)').first() visible.addClass('hide') } |
А нельзя просто циклом идти по элементам меню и считать общую ширину и как только она не будет влезать в контейнер, то оставшееся скрывать?
|
В первой проверке должно проверяться, всели элементы помещаются, а во второй, проверяется, уместится ли один скрытый элемент если его показать. Ну же как-то определить сколько элементов скрыть или показать.
|
Цитата:
Тогда непоместившиеся элементы будут падать вниз и скрываться из виду. Хотя мне не очень нравится такая реализация, да и float: left не всегда подходит. Зато все просто как 2 x 2 |
overflow: hidden не подходит, поскольку внутри элемента списка может быть выпадающее меню. плюс в списке могут быть элементы которые не должны скрываться или наоборот показываются когда какой-то элемент скрыт. (когда скрывается элемент, то в начале списка появляется пункт с выпадающем списком, в котором у нас скрытые пункты, решил не делать через append а просто продублировал список и делаю пункт видимым в зависимости скрыт ли данный пункт в общем меню)
Пример такого меню пока единственный пришёл в голову, в шапке в личном кабинете outlook, skydrive(onedrive) и прочих похожих сервисов microsoft. При выделение элемента там, появляются команды, которые так же скрываются в подсписок, если не умещаются. Только они там не прячутся, а удаляются и создаются. В исходном коде их скриптов разбираться бестолку, через компрессор пропущен (через декомпрессор картина все равно не меняется) |
Цитата:
http://learn.javascript.ru/play/owycdc Или я чего-то не понимаю? |
Работает как надо) Спасибо! Теперь бы ещё с кодом разобраться, где что происходит)
|
Цитата:
|
Цитата:
// elems == элементы меню var width = container.offsetWidth; //ширина, тащемта for(var i=0; i<elems.length; i++) if(width-=elems[i].offsetWidth < 0) { if(elems[i].offsetWidth < menu_button_width) i--; break; } Ширина каждого элемента вычитается из ширины контейнера и как только не влезает скрипт выходит из цикла. При этом проверяется: если ширина не влезшего элемента меньше заранее известной ширины кнопки то счетчик откатывается на 1 назад, иначе так и выходит. По этому счетчику все остальные пункты должны заехать в ту самую кнопку. |
Часовой пояс GMT +3, время: 11:33. |