Xpoint
   [напомнить пароль]

построение раскрывающегося дерева

Метки: [без меток]
2005-07-07 13:40:02 [обр] tricord[досье]

Как сделать раскрывающееся меню(дерево),
есть таблица (id parent_id title)
parent_id=0 - корневые разделы (элементы)
сначало выводятся корневые разделы,
при нажатии на ссылку раздела(например c id=1 ), открываются только подразделы у которых parent_id=1 (например с id=11, 12 и 13), при нажатии на подраздел (с id=11) открываются только подподразделы с parent_id=11( например id=111, 112, 113)
1 этап:
раздел1(id=1)
раздел2(id=2)

2 этап(нажимаем на раздел1)
раздел1(id=1)
   раздел11(id=11)
   раздел12(id=12)
раздел2(id=2)

3 этап(нажимаем на раздел11)
раздел1(id=1)
   раздел11(id=11)
      раздел111(id=111)
      раздел112(id=112)
   раздел12(id=12)
раздел2(id=2)
и т.д.

Построить раскрытое дерево(когда все элеметы раскрыты) получилось, а тут затык.

спустя 18 минут [обр] Закиров Руслан(0/343)[досье]
хранить массив открытых точек дерева. Либо всех, либо только самые нижние уровни. Напечатали точку, далее проверили не собержит ли она точку(рекурсивно) из списка расскрытых, если содержит, то печатаем ее детей по той же схеме.
спустя 56 минут [обр] tricord[досье]
как я понял, должен сделать таблицу (хэш, массив) со всеми родителями раздела который хочу открыть?
спустя 49 минут [обр] Закиров Руслан(0/343)[досье]

Все зависит от возможностей и от задачи.
Вот у вас дерево:

1
1.1
1.1.1
1.1.1.1
1.1.2
1.2
2
2.1
2.2
  1. Вы хотите позволить пользователю расскрыть только один конечный пункт или несколько? То есть например у пользователя расскрыт пункт 1, и он видит:
1
1.1
1.2
2

Он нажимает на 2 и система схлопывает 1-ый пункт или система не схлопывает его, а показывает оба. В первом случае надо хранить одну конечную точку или одну цепочку, а во втором множество точек или цепочек.

  1. Какую информацию хранить? О конечных точках или цепочках? Конечные точки позволят сыкономить на памяти немного, например открыт пункт 1.1.1, но для того чтоб его показать нужно еще показать 1.1 и 1. Так вот вы можете заранее сохранить всю цепочку точек. Цепочки очень выгодны с точки зрения производительности при вашей структуре данных, потому что если вы дошли до пункта 1, то вам надо проверить есть ли он в списке и все, а если вам известна только конечная точка, то вам надо проверить содержит ли пункт 1 рекурсивно эту точку.

В случае веб-приложений(каталогизаторы типа яндекса и другие) очень часто останавливаются на предаче только конечной точки, затем получение пути от этой точки до корня.

Есть так же вариант когда информация о вложености элементов кешируется в БД в отдельной таблице, то есть можно одним запросом получить не только детей, но и всех потомков точки.

В Oracle и PostgreSQL(нужно патчить, обсуждение есть на xpoint) есть специальное расширение языка SQL для работы с подобной структурой таблиц.

спустя 30 минут [обр] tricord[досье]
  1. По первому пункту:
Вы хотите позволить пользователю расскрыть только один конечный пункт или несколько? То есть например у пользователя расскрыт пункт 1, и он видит:
1
1.1
1.2
2Он нажимает на 2 и система схлопывает 1-ый пункт или система не схлопывает его, а показывает оба. В первом случае надо хранить одну конечную точку или одну цепочку, а во втором множество точек или цепочек.

Система схлопывает 1-ый пункт.

  1. По второму пункту:

Использую Mysql.
Цепочка - это все родители (цепочка родителей) того раздела который я хочу открыть - правильно ли я понял?
Если да - то я этот массив получить могу, а вот дальше ... что то туго.

спустя 36 минут [обр] Закиров Руслан(0/343)[досье]

Правильно поняли.
Так что тугого? Или вы хотите в один запрос к БД все уложить? В один запрос не получится.
Получили цепочку всех родителей. Потом вызываем рекурсивную функцию печати:

sub print_node
{
  my $id = shift;
  my $level = shift || 0;
  my $node = load_node($id);
  print (' ' x $level) . $node->name;

  return unless $node->is_open; # поиск по массиву/хешу на наличие в списке расскрытых

  foreach my $kid( $node->kids ) {
    print_node( $kid, $level + 1);
  }
}

Где-то так.

спустя 14 минут [обр] tricord[досье]
Большое спасибо про развернутый ответ,
просто туплю при написании рекурсивной функции печати.
спустя 4 месяца 5 дней [обр] Libov[досье]

Если вам понравится раскрывающиеся дерево.
http://meduch.ec.ru/?com=cat/fav - то приведу скрипт на PHP.
Кратко: использую три класа ООП
class _btree() - выбирает из Мускула одним запросом в массив дерево и открытую ветвь
class m_tree extends _btree - оболочка для отображения выбраного массива. В основном состоит из скелетных вызовов
class x_tree extends m_tree - реализация . Введены функции редактирования, добавления и удаления. Прописывание дизайна.

Powered by POEM™ Engine Copyright © 2002-2005