Функция
applay_tree имитирует работу парсера по созданию иерархического списка, отражающего структуру документа.
Функция
attr_transform скрывает значения аттрибутов и "стилизует" сам список. Предполагается, что из-под пасера список выходит "голым".
<!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">
/*свойства списка*/
li.taglist{
list-style: none;
}
/*свойства блоков*/
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>'
var s = ' ' + i + '="' + tree[i] + '"'
// имя="значение", причём значение - в отдельном блоке
li.innerHTML += s // добавляем в элемент
}
}
li.appendChild(ul) // здесь в объект-элемент вставляется кенгурятник со всем содержимым (если оно есть)
return li // возврат элемента позволит вставить его в "более высокоуровневые кенгурятники"
}
function attr_transform(node){ // собственно, преобразование списка
node.parentNode.removeChild(node) // убираем кнопку за ненадобностью
var cont = document.getElementById('textcont') // находим рамочный блок
// следующие 2 строчки - скрываем значения аттрибутов и убираем символы списков
cont.innerHTML = cont.innerHTML.replace(/(\w*=")([^"]*)"/gi,'<div class="named_attr">$1<div class="hidden">$2</div>"</div>')
cont.innerHTML = cont.innerHTML.replace(/<li\s*>/gi, '<li class="taglist">')
}
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><!--рамочка в документе-->
<input type="button" onclick="attr_transform(this)" value="свернуть аттрибуты"/>
</body>
</html>