Тема: Show/hide content
Показать сообщение отдельно
  #8 (permalink)  
Старый 09.10.2010, 15:11
Аспирант
Отправить личное сообщение для MikhailGirshberg Посмотреть профиль Найти все сообщения от MikhailGirshberg
 
Регистрация: 27.07.2010
Сообщений: 72

ну вот, не прошло и суток...
... как я снова здесь.

Пример строит дерево (предположительно, иллюстрирующее структуру XML-документа) в виде вложенных списков как элементов DOM. Для каждого элемента показывается имя, вложенные поддеревья элементов и группы пара="значение" для остальных аттрибутов. По умолчанию, значения аттрибутов скрыты. Кликнув по имени, их можно раскрыть. Повторно кликнув - скрыть снова.

В примере я выпустил момент создания объекта (json), описывающего дерево XML. Полагаю, не Javascript-овое это дело, на серверной стороне гораздо удобнее парсить XML. В принципе, не вопрос всё преобразование спихнуть на серверную сторону.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>XML nodetree representation</title>
    <style type="text/css">
      /*свойства блоков*/
      div.named_attr{border: 1px dotted silver;cursor:default;}/*бордюр и курсор - для красоты*/
      div.named_attr,div.named_attr div{display: inline}/*оставим блоки в строке*/
      div.named_attr div.hidden{display: none}/*скрыть "скрытое"*/
    </style>
    <script type="text/javascript">
      //  Здесь я задаю структуру и наполнение дерева объектом
      // В реальной жизни что-то вроде этого выполнит парсер XML на серверной стороне
      var tags_tree = {"name":"root", "theme":"a1", "subj":"b1", "category":"c1", "children":[
          {"name":"child1", "class":"c1", "children":[
              {"name":"grandchild1", "class":"c2", "children":[]}
            ]},
          {"name":"child2", "class":"c1", "children":[
              {"name":"grandchild2", "class":"c2", "children":[]},
              {"name":"grandchild3", "class":"c2", "children":[]} // у всех объектов одинаковая структура
              // name - имя объекта, children - массив объектов-детей, остальные поля - пары 'имя:значение'
            ]},
          {"name":"child3", "class":"c1", "children":[]}
        ]}

      function apply_tree(tree){  //  отображаем дерево объектов(tree) в дерево элементов DOM
        var li = document.createElement('LI') //   элемент дерева станет элементом списка - так проще форматировать
        li.className = "nodedesk" //  у меня не используется. можно применять для изменения вида списка
        var ul = document.createElement('UL') //  "кенгурятник" для детей
        for(var i in tree){ // полями объекта являются имя, список детей (вложенных объектов) и свободные поля
          switch(i){
            case 'name':  //  имя объекта
              li.innerHTML += tree[i] //  без затей добавляется в элемент (ещё НЕ DOM - просто объект-элемент)
              break;
            case 'children':  // массив вложенных объектов (детей)
              var subtree = tree[i] // каждый вложенный объект разбирается как (под)дерево и добавляется в
              if(subtree.length > 0) for(var j in subtree)ul.appendChild(apply_tree(subtree[j]))// кенгурятник
              break;
            default:  //  прочие (свободные) поля
              var s = ' <div class="named_attr">' // превращаются в блоки
              s += i + '="' + '<div class="hidden">' + tree[i] + '</div>"</div>'
              // имя="значение", причём значение - в отдельном блоке
              li.innerHTML += s // добавляем в элемент
          }
        }
        li.appendChild(ul)  // здесь в объект-элемент вставляется кенгурятник со всем содержимым (если оно есть)
        return li // возврат элемента позволит вставить его в "более высокоуровневые кенгурятники"
      }
            
      onload = function(){  //  вызывается один раз - при загрузке документа
        var textcont = document.getElementById('textcont')  //  место в документе, где будем строить список
        var ul = document.createElement('UL') //  корневой "супер-кенгурятник"...
        ul.appendChild(apply_tree(tags_tree)) //  ... вмещает корневой элемент со всем содержимым
        textcont.appendChild(ul)  // вставляем кенгурятник в рамочку, которая уже висит в документе
        textcont.onclick = function(event){ // на ВСЮ рамочку вешаем обработчик события "клик мышкой"
          event = event || window.event //  несколько выморочным, но безотказно-кроссбраузерным способом...
          var elem = event.target || event.srcElement // ... определяем, где кликнули
          if(elem.className.search('named_attr')< 0) return // если не там - уходим
          elem = elem.getElementsByTagName('DIV')[0]  // в кликнутом элементе находим вложенный блок
          if(elem.className.search('hidden') < 0) elem.className += 'hidden'  //  если открыт - закроем
          else elem.className = elem.className.replace('hidden', "")  //  иначе - откроем
        }
      }
    </script>
  </head>
  <body>
    <div id="textcont"></div><!--рамочка в документе-->
  </body>
</html>


Прошу сообщить, если не читаются комментарии в HTML-коде, возможны проблемы с кодировками.

Да, и ещё. Обрабатывается клик только на имя "аттибута", но не на значение. Чтобы это исправить, надо переработать проверку (стр. 59), добавив аналогичную проверку для родительского элемента. В примере эта доппроверка исключена. Дабы не загромождать код.
Ответить с цитированием