Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 03.04.2014, 02:00
Аспирант
Отправить личное сообщение для BelkinV Посмотреть профиль Найти все сообщения от BelkinV
 
Регистрация: 12.09.2012
Сообщений: 35

Проблема с рекурсией и циклом (можно ли упростить?)
Возникает переполнение стека из за рекурсии и цикла внутри.
Подскажите как можно по другому реализовать.

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

Сделал с использованием рекурсии и местами цикл.
В рекурсии делается проверка, всели пункты помещаются, если нет, то скрываем последний и проверяем снова, если скрывать не нужно, то проверяем поместится ли первый скрытый пункт, если да то показываем его и проверяем снова.
Цикл использовал для определения суммарной длинны всех видимых элементов (для сравнения в рекурсии)

Ниже привел код, из-за нескольких таких меню (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')
  }
Ответить с цитированием
  #2 (permalink)  
Старый 03.04.2014, 03:18
Профессор
Отправить личное сообщение для jsnb Посмотреть профиль Найти все сообщения от jsnb
 
Регистрация: 15.03.2014
Сообщений: 561

А нельзя просто циклом идти по элементам меню и считать общую ширину и как только она не будет влезать в контейнер, то оставшееся скрывать?
Ответить с цитированием
  #3 (permalink)  
Старый 03.04.2014, 08:47
Аспирант
Отправить личное сообщение для BelkinV Посмотреть профиль Найти все сообщения от BelkinV
 
Регистрация: 12.09.2012
Сообщений: 35

В первой проверке должно проверяться, всели элементы помещаются, а во второй, проверяется, уместится ли один скрытый элемент если его показать. Ну же как-то определить сколько элементов скрыть или показать.
Ответить с цитированием
  #4 (permalink)  
Старый 03.04.2014, 08:50
Аватар для danik.js
Профессор
Отправить личное сообщение для danik.js Посмотреть профиль Найти все сообщения от danik.js
 
Регистрация: 11.09.2010
Сообщений: 8,804

Сообщение от BelkinV
Если они не помещаются в контейнер, который во всю ширину выделенной ему области, то не поместившиеся пункты должны скрываться
А если задать контейнеру высоту, равную высоте элемента, а так же свойство overflow: hidden, а элементам выставить float:left?
Тогда непоместившиеся элементы будут падать вниз и скрываться из виду.

Хотя мне не очень нравится такая реализация, да и float: left не всегда подходит. Зато все просто как 2 x 2
__________________
В личку только с интересными предложениями
Ответить с цитированием
  #5 (permalink)  
Старый 03.04.2014, 09:26
Аспирант
Отправить личное сообщение для BelkinV Посмотреть профиль Найти все сообщения от BelkinV
 
Регистрация: 12.09.2012
Сообщений: 35

overflow: hidden не подходит, поскольку внутри элемента списка может быть выпадающее меню. плюс в списке могут быть элементы которые не должны скрываться или наоборот показываются когда какой-то элемент скрыт. (когда скрывается элемент, то в начале списка появляется пункт с выпадающем списком, в котором у нас скрытые пункты, решил не делать через append а просто продублировал список и делаю пункт видимым в зависимости скрыт ли данный пункт в общем меню)

Пример такого меню пока единственный пришёл в голову, в шапке в личном кабинете outlook, skydrive(onedrive) и прочих похожих сервисов microsoft. При выделение элемента там, появляются команды, которые так же скрываются в подсписок, если не умещаются. Только они там не прячутся, а удаляются и создаются. В исходном коде их скриптов разбираться бестолку, через компрессор пропущен (через декомпрессор картина все равно не меняется)

Последний раз редактировалось BelkinV, 03.04.2014 в 09:48.
Ответить с цитированием
  #6 (permalink)  
Старый 03.04.2014, 13:19
Профессор
Отправить личное сообщение для jsnb Посмотреть профиль Найти все сообщения от jsnb
 
Регистрация: 15.03.2014
Сообщений: 561

Сообщение от BelkinV Посмотреть сообщение
В первой проверке должно проверяться, всели элементы помещаются, а во второй, проверяется, уместится ли один скрытый элемент если его показать. Ну же как-то определить сколько элементов скрыть или показать.
Ну я имел ввиду что-то типо этого (только при ресайзе):
http://learn.javascript.ru/play/owycdc
Или я чего-то не понимаю?
Ответить с цитированием
  #7 (permalink)  
Старый 03.04.2014, 14:48
Аспирант
Отправить личное сообщение для BelkinV Посмотреть профиль Найти все сообщения от BelkinV
 
Регистрация: 12.09.2012
Сообщений: 35

Работает как надо) Спасибо! Теперь бы ещё с кодом разобраться, где что происходит)
Ответить с цитированием
  #8 (permalink)  
Старый 03.04.2014, 15:58
Профессор
Отправить личное сообщение для jsnb Посмотреть профиль Найти все сообщения от jsnb
 
Регистрация: 15.03.2014
Сообщений: 561

Сообщение от BelkinV Посмотреть сообщение
Теперь бы ещё с кодом разобраться, где что происходит)
Чего там разбираться то? Первый цикл идет до тех пор пока элементы влезают в контейнер. Соответственно всё что влезло показываем. Второй цикл уже идет для тех, кто не влезает, соответственно, их скрываем.
Ответить с цитированием
  #9 (permalink)  
Старый 03.04.2014, 16:29
Профессор
Отправить личное сообщение для kostyanet Посмотреть профиль Найти все сообщения от kostyanet
 
Регистрация: 23.10.2010
Сообщений: 2,718

Сообщение от BelkinV
Ну же как-то определить сколько элементов скрыть или показать.
Тут нет комбинаторики. По-моему все должно быть просто. Суть примерно такова:

// 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 назад, иначе так и выходит.

По этому счетчику все остальные пункты должны заехать в ту самую кнопку.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как можно упростить доступ к функциям внутри плагина Sanu0074 Events/DOM/Window 1 17.01.2014 13:56
проблема с циклом mAstAk4 Events/DOM/Window 3 06.12.2010 17:47
проблема с рекурсией astral_sight AJAX и COMET 4 22.10.2010 13:22
Подскажите плизз как можно упростить код frolvict Общие вопросы Javascript 19 08.04.2010 14:23
проблема с рекурсией, не могу понять почему скрипт не выходит из неё. Flirer Общие вопросы Javascript 5 24.12.2009 01:01