Отрисовка DHTML-menu при Nested Sets модели данных(+)

Sherman

Mephi
Отрисовка DHTML-menu при Nested Sets модели данных(+)

Возможно здесь уже поднимался вопрос на данную тему, но я решения я не нашел.

Вводная. Есть реализованная структура данных nested sets(mysql/php). Реализация моя собственная, но очень похожа на то, что предлагали здесь: http://dev.e-taller.net/dbtree/


Нужно сделать из этих данных древовидное dhtml menu. Проблема в том, что все компоненты подобного рода используют связку id-parentid, так или иначе.

Вопрос: как выводить такое дерево.

Есть вариант решения. На лету переводим nested sets в Adjacency list и дальше уже строим дерево(т.е. создаем js/html).

о такой вариант очень накладен. Может кто уже сталкивался с подобной задачей и нашел решение?

p.s. я взял готовый компонент xtree:

http://webfx.eae.net/dhtml/xtree/

следующий код(js) иллюстрирует создание дерева:

Код:
                var tree = new WebFXTree('Root');
	var node1 = new WebFXTreeItem('node1');
	tree.add(node1);
	var node11 = new WebFXTreeItem('node1.1);
	node1.add(node11);
                ...
	document.write(tree);
 

kvf77

Red Devil
Вот, может не оптимально, но у меня работает. Эта функция генерит .js файлик для динамического меню JSCookMenu:

Используется стандартное дерево NestedSets + свои филды специфические - думаю от них ты и сам почистить сможешь код.
PHP:
<?

function MenuList() {
    if ('admin' == $admin) {
        $dbtree = new dbtree('modules', 'module', $this->adodb);
        $dbtree->Full(array('module_level', 'module_name', 'module_action', 'module_prefix', 'module_img'), array('and' => array('module_level > 0')));
        if (!empty($dbtree->ERRORS_MES)) {
            $this->ERRORS = $dbtree->ERRORS;
            $this->ERRORS_MES = $dbtree->ERRORS_MES;
            return FALSE;
        }
        $res = $dbtree->res;
        unset($dbtree);
    }
    if (0 == $res->RecordCount()) {
        $this->ERRORS_MES[] = _('no_modules');
        return FALSE;
    }
    $level_old = 1;
    $iteration = 0;
    $result = "<script language=\"JavaScript\">\n";
    $result .= "var myMenu =\n[\n";
    $prefix = array();
    while ($module = $res->FetchRow()) {
        if (!empty($module['module_action'])) {
            $module['module_action'] = explode('::', $module['module_action']);
            $module['module_action'] = '\'' . ADMIN_APP_URL . '/?lang=' . CURRENT_LANG . '&name=' . $module['module_action'][0] . '&action=' . $module['module_action'][1] . '\'';
        } else {
            $module['module_action'] = 'null';
        }
        if (!empty($module['module_img'])) {
            $module['module_img'] = '\'<img src="' . ADMIN_JS_WWW_PATH . '/menu/theme/icons/' . $module['module_img'] . '">\'';
        } else {
            $module['module_img'] = 'null';
        }
        if (!empty($module['module_prefix'])) {
            $prefix[] = $module['module_prefix'];
        }
        if ($module['module_level'] == $level_old) {
            if ($iteration <> 0) {
                $result .= "],\n";
            } else {
                $iteration++;
            }
            $result .= str_repeat(' ', 1 * $module['module_level']);
            $result .= "[" . $module['module_img'] . ", '" . _($module['module_name']) . "', " . $module['module_action'] . ", '_self', ''";
        }
        if ($module['module_level'] > $level_old) {
            $result .= ",\n";
            $result .= str_repeat(' ', 1 * $module['module_level']);
            $result .= "[" . $module['module_img'] . ", '" . _($module['module_name']) . "', " . $module['module_action'] . ", '_self', ''";
        }
        if ($module['module_level'] < $level_old) {
            if (1 == ($level_old - $module['module_level'])) {
                $result .= "]\n";
                $result .= str_repeat(' ', 1 * ($module['module_level']));
                $result .= "],\n";
            } else {
                $result .= "]\n";
                for ($i = 0;$i < $level_old - $module['module_level'];$i++) {
                    $result .= str_repeat(' ', 1 * ($module['module_level'] - $i + 1));
                    $result .= "],\n";
                }
            }
            $result .= str_repeat(' ', 1 * ($module['module_level']));
            $result .= "[" . $module['module_img'] . ", '" . _($module['module_name']) . "', " . $module['module_action'] . ", '_self', ''";
        }
        $level_old = $module['module_level'];
    }
    $result .= "]\n";
    for ($i = 0;$i < $level_old - 1;$i++) {
        $result .= str_repeat(' ', 1 * (1 - $i + 1));
        $result .= "],\n";
    }
    $result .= "];\n</script>\n";
    return array($result, $prefix);
}
?>
 

Sherman

Mephi
Мой вариант реализации(формат Tigra Tree Menu).

$catObj->nodeInfoCollection - данные, отсортированные по левому ключу(nested sets).

PHP:
$this->javaScriptCode = "var TREE_ITEMS = [";
$this->javaScriptCode .= "['Публикации', null,";

$numNodes = count($catObj->nodeInfoCollection);
for($i=0;$i<$numNodes;$i++)
{
	$prevlevel = $catObj->nodeInfoCollection[$i-1]["level"];
	$curLevel = $catObj->nodeInfoCollection[$i]["level"];
	$nextLevel = $catObj->nodeInfoCollection[$i+1]["level"];

	$this->javaScriptCode .= "[";
	$this->javaScriptCode .= "'" . $catObj->nodeInfoCollection[$i]["data"]["desc"] . "','" .
	"/modules/admin/test/?catid=" . $catObj->nodeInfoCollection[$i]["id"] . "'";

	if ($curLevel == $nextLevel)
	{
		$this->javaScriptCode .= "],";
	}

	if ($curLevel < $nextLevel)
	{
		$this->javaScriptCode .= ",";
	}

	if ($curLevel > $nextLevel)
	{
		$numItarations = $curLevel-$nextLevel+1;
		for($j=0;$j<$numItarations;$j++)
		{
			$this->javaScriptCode .= "]";			
		}

		if ($i != $counter-1)
		{
			$this->javaScriptCode .= ",";
		}
	}
	$this->javaScriptCode .= "\r\n";
}
$this->javaScriptCode .= "]];";
А вообще IE.WebControls намного лучше и удобнее, но как использовать их для php — загадка.
 

kvf77

Red Devil
Sherman

гм - че-то не уверен, что оно у тя правильно работает.
как быть, если твое дерево закончилось на узле с левелом 3?
не понял - помоему у тя это не учитывается.
 
Сверху