Page 1 of 1

Dynamic Tree View

Posted: Thu Jun 29, 2006 7:56 am
by vivekjain
Hi,
I want some help with developing a dynamic tree view menu. It would have unlimited levels of nodes. Can anyone help me with this?

Thanks

Re: Dynamic Tree View

Posted: Thu Jun 29, 2006 8:03 am
by aerodromoi
vivekjain wrote:Hi,
I want some help with developing a dynamic tree view menu. It would have unlimited levels of nodes. Can anyone help me with this?

Thanks
viewtopic.php?t=47288 ?

Posted: Mon Jul 03, 2006 8:08 am
by CoderGoblin
Overkill for what you probably need but personally I tend to use CSS and <ul>/<li> html tags. I can then have the CSS controlling the look and feel of the tree (OK doesn't print out correctly but I use this for debugging a $_SESSION array. I have also used this methodoly with AJAX etc to get browsable trees without running out of Javascript memory for large treelists.

Code: Select all

....
$out.='<ul class="treelist"><li class="root">_SESSION<ul class="sitemap">';
                if (!empty($_SESSION)) $out.=cssTreeList($_SESSION,1);
                $out.='</ul></li></ul>';
...

function cssTreeList($data,$first=0)
{
        static $level=0;
        static $node_no=1;
        $node_no++;
        $out='';
        if (!$first) $out.='<ul style="display:none;" id="subnode'.($node_no-1).'">';
        ksort($data);
        foreach ($data as $key=>$value) {
            if (is_array($value)) {
                if (count($value)) {
                    $out.='<li class="closed" id="node'.$node_no.'"><a href="javascript:traceToggle('.$node_no.');" class="tclosed" id="link'.($node_no).'">'.$key.'</a>';
                } else {
                    $out.='<li class="closed" id="node'.$node_no.'"><a href="javascript:traceToggle('.$node_no.');" class="tgclosed" id="link'.($node_no).'">'.$key.'</a>';
                }
                $out.=$this->cssTreeList($value);
                $out.='</li>';
            } else {
                $out.='<li class="opened"><span class="tpage">'.$key.' = ['.$value.']</span></li>';
            }
        }
        if (!$first) $out.='</ul>';
        return $out;                
}
With this javascript:

Code: Select all

function traceToggle(node)
{
  var cname='';
  var element=document.getElementById('node'+node);
  if (element) {
    switch (element.className) {
      case 'opened':
        element.className='closed';
        break;
      case 'closed':
        element.className='opened';
        break;
    }
    cname=element.className;
  }
  element=document.getElementById('link'+node);
  if (element) {
    switch (element.className) {
      case 'topened':
        element.className='tclosed';
        break;
      case 'tclosed':
        element.className='topened';
        break;
      case 'tgopened':
        element.className='tgclosed';
        break;
      case 'tgclosed':
        element.className='tgopened';
        break;
    }
    element.href='javascript:traceToggle('+node+');';
  }
  element=document.getElementById('subnode'+node);
  if (element) {
    switch (cname) {
      case 'opened':
        element.style.display='block';
        break;
      case 'closed':
        element.style.display='none';
        break;
    }
  }
  
}
and finally this css (minus the images of course (16x16),

Code: Select all

ul.treelist
{
  font-family: Arial, Helvetica, sans-serif;
  font-size: 12px;
  color: #000;
  white-space: nowrap;
  list-style-type:none;
  padding:0;
  margin:0;
}

ul.treelist li.root:before
{
  content:url(../img/base.gif);
}

ul.sitemap
{
list-style-type: none;
padding: 0;
margin: 0;
vertical-align:middle;
}

ul.sitemap ul {
 list-style-type:none;
 padding:0;
 margin:0;
 vertical-align:middle; 
}

ul.sitemap li a {
	text-decoration: none
}

ul.sitemap li 
{
  padding:0 0 0 15px;
  background: url(../img/line.gif) repeat-y 0 0;
}

ul.sitemap li:last-child {
  background-repeat: no-repeat;
}


ul.sitemap li.closed a.tclosed
{
  margin:-15px;
  padding: 0 0 0 0px;
  background:url(../img/nolines_plus.gif) no-repeat 0 -0.15em;
}

ul.sitemap li.closed a.tgclosed
{
  margin:-15px;
  padding: 0 0 0 0;
  background:url(../img/nolines_plus.gif) no-repeat 0 -0.15em;
  
}

ul.sitemap li.opened a.topened
{
  margin:-15px;
  padding: 0 0 0 0px;
  background:url(../img/nolines_minus.gif) no-repeat 0 -0.15em;
}

ul.sitemap li.opened a.tgopened
{
  margin:-15px;
  padding: 0 0 0 0;
  background:url(../img/nolines_minus.gif) no-repeat 0 -0.15em;
  
}

ul.sitemap li.locked span.tclosed {
  margin:-15px;
  padding: 0 0 0 0;
  background:url(../img/padlock.png) no-repeat 0 -0.15em;
}

li span.tclosed:before {
  vertical-align:middle;
  content: url(../img/join.gif) url(../img/gfolder.gif);
}

li a.tclosed:before {
  vertical-align:middle;
  content: url(../img/join.gif) url(../img/folder.gif);
}

li a.topened:before {
  vertical-align:middle;
  content: url(../img/join.gif) url(../img/folder_open.gif);
}

li a.tgclosed:before {
  vertical-align:middle;
  content: url(../img/join.gif) url(../img/gfolder.gif);
}

li a.tgopened:before {
  vertical-align:middle;
  content: url(../img/join.gif) url(../img/gfolder_open.gif);
}

ul.sitemap li.opened span.tpage {
  margin:-15px;
  padding: 0 0 0 0;
  background:url(../img/join.png) no-repeat 0 -0.15em;
}

li span.tpage:before {
  vertical-align:middle;
  content: url(../img/join.gif) url(../img/page.gif);
}
(gfolder is a grey folder used to indicate nothing in it).