Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Сканирование вложенных списков (https://javascript.ru/forum/dom-window/5141-skanirovanie-vlozhennykh-spiskov.html)

Paguo-86PK 19.09.2009 07:28

Сканирование вложенных списков
 
Необходимо просканировать следующее меню:
<menu mode="hor" value="Main">
 <menu class=0 mode="ver" title="Файл" value="File">
  <li mode="button" action="window.status='New'" title="Новый" value="New"/>
  <li mode="button" action="window.status='Open'" title="Открыть" value="Open"/>
  <li mode="button" action="window.status='Save'" title="Сохранить" value="Save"/>
  <li mode="button" action="window.status='Close'" title="Закрыть" value="Open"/>
  <li mode="separator"/>
  <li mode="button" action="window.status='Exit'" title="Выйти" value="Exit"/>
 </menu>
 <menu class=0 mode="ver" title="Правка" value="Edit">
  <li mode="button" action="window.status='Cut'" title="Вырезать" image="cut.gif" value="Cut"/>
  <li mode="button" action="window.status='Copy'" title="Копировать" image="copy.gif" value="Copy"/>
  <li mode="button" action="window.status='Paste'" title="Вставить" image="paste.gif" value="Paste"/>
 </menu>
 <menu class=0 mode="ver" title="Вид" value="View">
  <menu class=0 mode="hor" value="Syntax" title="Синтаксис">
   <li mode="button" action="window.status='Asm'" title="Ассемблер" value="Assembler"/>
   <li mode="button" action="window.status='Basic'" title="Бейсик" value="Basic"/>
   <li mode="button" action="window.status='Cpp'" title="Си" value="C++"/>
  </menu>
  <menu class=0 mode="hor" title="Переключатели" value="Triggers">
   <li mode="radio" action="window.status='Radio 1'" title="Опция #1" value="Radio 1"/>
   <li mode="radio" action="window.status='Radio 2'" title="Опция #2" value="Radio 2"/>
   <li mode="radio" action="window.status='Radio 3'" title="Опция #3" value="Radio 3"/>
   <li mode="separator"/>
   <li mode="check" action="window.status='Check 1'" title="Флажок #1" value="Check 1"/>
   <li mode="check" action="window.status='Check 2'" title="Флажок #2" value="Check 2"/>
   <li mode="check" action="window.status='Check 3'" title="Флажок #3" value="Check 3"/>
  </menu>
 </menu>
 <li mode="button" value="Help" action="window.status='Help'" title="Справка"/>
</menu>
Написал рекурсивную функцию, которая должна пробегать по всем элементам с произвольной вложенностью. Однако, спотыкаюсь на одном месте:
Почему-то в рекурсии функция не обрабатывает дочерные ноды, а сканирует с начала.

Вот примерный алгоритм:
var ii=0; // Отладочный счётчик глубины рекурсии
function CreateMenu(items) {
 var i, s;
 var mnu = new Array(); // Копим элементы меню здесь
 ++ii;
 for(i = 0; i < items.length; ++ i) {
  itm = items[i];
  document.getElementById("pres").innerHTML += ii + ' type=' + itm.mode + ' value=' + itm.value + ', ' + itm.tagName + '<br/>'; // pres - <pre id='pres'>Debug log</pre>
  switch(itm.mode) {
  case "hor":
  document.getElementById("pres").innerHTML += 'hor<br>';
   mnu[mnu.length] = itm.value + " " + itm.title + " >";
   mnu[mnu.length] = CreateMenu(items.getChildElements()); // Тут и ошибка! Нужно из <menu> извлечь вложенные пункты меню <li> или подменю <menu>...
   break;
  case "ver":
  document.getElementById("pres").innerHTML += 'ver<br>';
   mnu[mnu.length] = itm.value + " " + itm.title + " v";
   mnu[mnu.length] = CreateMenu(itm.getElementsByTagName("LI"));
   break;
  case "button":
  document.getElementById("pres").innerHTML += 'button<br>';
   mnu[mnu.length] = itm.value + " " + itm.title + " " + itm.action + "" + "";
   break;
  case "radio":
   mnu[mnu.length] = itm.value + " " + itm.title + " " + itm.action + "" + ";";
   break;
  case "separator":
   mnu[mnu.length] = "";
   break;
  }
 }
 mnu[mnu.length] = ".";
 --ii;
 return mnu;
}
function CreateMnu(items) {
 return CreateMenu(items[0].getElementsByTagName("MENU"));
}
window.onload = function() {
mnu = document.getElementsByTagName("MENU");
 mnus = CreateMnu(mnu);
 document.body.removeChild(mnu[0]);
...
Функция визуализации меню имеется собственной давней разработки. Работает отлично, но формирует меню из Array. Проблема лишь в том, что не могу верно обработать <menu>, которое, затем просто удаляется со страницы как пережиток прошлого... Оно лишь нужно, чтобы сгенерировать Array... Так-как JS генерации меню работает в фоне без лишних вызовов...

Спасибо!

x-yuri 19.09.2009 18:43

а сразу этот Array использовать нельзя? Что такое getChildElements? Ошибки в консоли какие-то появляются?

Paguo-86PK 20.09.2009 00:20

Разобрался за несколько часов. Я забыл, что вместо getChildElements существует all[]...:D
В общем, 15 минут назад лишь добился генерации меню работающего.
Однако, смущает следующее:
function CreateMenu(items) {
 var i, s;
 var mnu = new Array();
 for(i = 0; i < items.length; ++ i) {
  itm = items[i];
  switch(itm.mode) {
  case "menu":
   mnu[mnu.length] = itm.caption;
   i += (mnus = CreateMenu(itm.all)).length - 1; // <-- Вот тут указатель i обязательно нужно сместить, чтобы снова не читать те же элементы
   for(j in mnus)                                // <-- А здесь необходимо искусственно сделать concat
    mnu[mnu.length] = mnus[j];
   break;
  case "button":
   mnu[mnu.length] = itm.caption + " " + itm.title + " " + itm.action + " " + " " + (itm.image ? itm.image : "");
   break;
...
  case "separator":
   mnu[mnu.length] = "";
   break;
  }
 }
 mnu[mnu.length] = ".";
 return mnu;
}
т.е. необходимо смещать указатель так, чтобы обойти дочерние элементы дочерного элемента. Как это обойти? Удалать дочерний элемент на лету вместе с его содержимым? Кривовато и не красиво:stop:

Riim 20.09.2009 16:53

all[] работает только в IE и Opera.

B~Vladi 21.09.2009 10:38

Цитата:

Сообщение от Paguo-86PK
вместо getChildElements существует all[]

вместо getChildElements существует childNodes.

Paguo-86PK 24.09.2009 03:48

childNodes? Странно, но заменив все, вернее всего два, all на childNodes, у меня меню испортилось: Многие пункты повылазали из подменю в основное...

Octane 24.09.2009 04:14

Потомучто childNodes не аналочино all работает, в возвращаемую коллекцию попадают все узлы, в том числе и текстовые, нужно дополнительно проверять nodeType == 1.

Paguo-86PK 24.09.2009 04:41

:dance: Всё сломалось и не лечится...
Завтра буду ковыряться:write:

B~Vladi 24.09.2009 10:37

Цитата:

Сообщение от Paguo-86PK
Всё сломалось и не лечится...

Чего радуешься:)


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