Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   рекурсивный обход меню (https://javascript.ru/forum/events/17134-rekursivnyjj-obkhod-menyu.html)

evgh 07.05.2011 10:15

рекурсивный обход меню
 
Доброго времени суток.
Требуется обойти древовидное меню, подскажите как исправить, а то в ступор зашёл.
Функция доходит до самых младших потомков (узлов), обрабатывает их, некоторых почему-то дважды, и помирает.
Как исправить не знаю :cray:

<div id="first">
<ul id="editor">
<li>1
    <ul>
        <li>11</li>
        <li>12</li>
        <li>13
            <ul>
                <li>131</li>
                <li>132</li>
                <li>133</li>
            </ul>
        </li>
        <li>14</li>
    </ul>
</li>
<li>2
    <ul>
        <li>21</li>
        <li>22</li>
        <li>23</li>
    </ul>
</li>
<li>3</li>
<li>4</li>
</ul>
</div>

function Next(n) {
    if(n.getElementsByTagName('li').length > 0) return n;
}
function rec(ul)
{
    if(ul.getElementsByTagName('ul').length > 0)
    {
        el=ul.getElementsByTagName('ul')[0].childNodes;
        if( el.length > 0 )
        {
            for(var i=0; i < el.length; i++)
            {
                if(el[i].nodeType != 3)
                {
                    alert( el[i].innerHTML );
                    if(Next(el[i])) rec( el[i] );
                }
            }
        }
    }
}
rec(document.getElementById('first'));


P.S. желательно без библиотек

poorking 07.05.2011 10:50

Могу предложить такой вариант
<script type = "text/javascript">
window.onload = function(){		
		
function hasSubs(li){
	var subs = [];
	for(var i = 0, il = li.childNodes.length; i < il; i ++){
		if(li.childNodes[i].nodeName == "UL"){
			subs[subs.length] = li.childNodes[i];
		}
	}
	return subs;
}
		
function isLI(node){
	return node.nodeName == "LI";
}
		
function count(ul){
	var childs = ul.childNodes;
	for(var i = 0, il = childs.length; i < il; i ++){
		if(isLI(childs[i])){
			var subs = hasSubs(childs[i]);
			if(subs.length){
				for(var j = 0, jl = subs.length; j < jl; j ++){
					count(subs[j]);
				}
			}else{
				alert("item" + childs[i].innerHTML);
			}		
		}
	}			
}

var outer = document.getElementById("menu");	
count(outer);
}
</script>

<ul id = "menu">
	<li>1</li>
	<li>2</li>
	<li>3</li>
	<li>
		<ul>
			<li>4.1</li>
			<li>4.2</li>
			<li>4.3</li>
			<li>
				<ul>
					<li>4.4.1</li>
					<li>4.4.2</li>
					<li>4.4.3</li>
					<li>4.4.4</li>
				</ul>
			
			</li>
		</ul>
	</li>
	<li>5</li>
</ul>

evgh 07.05.2011 11:05

на первый взгляд работает, но пункты "4" и "4.4" (которые ты специально не вписал :p ) не обрабатывает))

кое что интересное подчеркнул для себя

poorking 07.05.2011 11:20

Все работает ровно так как я хотел) совокупность вложенныx 4.x пунктов и образуют пункт 4, мoй вариант обрабоатывет li без дочерних ul, если нужно отображать таки корневой пункт 4, то я бы перед списком ul с дочерними меню вставил div скажем
Цитата:

Сообщение от evgh
<li>1
    <ul>
        <li>11</li>
        <li>12</li>
        <li>13

Потому что я перемещаюсь по узлам элементов, а у вас например, первой строке приведенной мной цитаты пункт 1 это просто textNode, то есть он не выделен.. даже не знаю как сказать, если нужны корневые элементы, то я б лучше вот так сделал
<ul id = "menu">
	<li>1</li>
	<li>2</li>
	<li>3</li>
	<li>4</li>
	<li>
		<ul>
			<li>4.1</li>
			<li>4.2</li>
			<li>4.3</li>
			<li>4.4</li>
			<li>
				<ul>
					<li>4.4.1</li>
					<li>4.4.2</li>
					<li>4.4.3</li>
					<li>4.4.4</li>
				</ul>
			
			</li>
		</ul>
	</li>
	<li>5</li>
</ul>

И тогда все будет работать ок

evgh 07.05.2011 11:25

poorking,
спасибо что отозвались, вопрос решён, указали на мою ошибку.
http://forum.vingrad.ru/forum/topic-...2342178/0.html

evgh 07.05.2011 11:27

Цитата:

Сообщение от poorking (Сообщение 103700)
...то я бы перед списком ul с дочерними меню вставил div ...

не валидно получится

poorking 07.05.2011 11:30

Цитата:

Сообщение от evgh
не валидно получится

Почему не валидно? все элементы блочные.
<li>
  <div>пункт 4</div>
  <ul>
     <li>Пункт 4.1</li>
     <li>Пункт 4.2</li>
     <li>Пункт 4.3</li>
  </ul>
</li>


Или что, валидатор разрешает в li только ul из блочных помещать?

evgh 07.05.2011 11:42

точно. вы правы. глупость сказал


Часовой пояс GMT +3, время: 23:44.