2

My idea is simple: if child->indent, if parent->make bold.

Lets say p0 is the parent of p1 and p2, p3 and p4 are the childs of p1. p5 is the independent page like p0. So what i wanna get is

p0 (bold font)
[3px]p1(bold font)
[  6px  ]p3
[  6px  ]p4
[3px]p2
p5 (bold font)

The problem is, I can't figure out. how to realize my idea. Tried given functions. No success. It works but indents only first level childs. My recursive php function looks like that

function generateOptions($parent, $level, $padding, $db)
{
    $result=$db->query("SELECT id, name FROM menu WHERE parent='$parent' AND showinmenu!='0'");
    if($level == 0) {$padding=''; $optstyle='bold';}
    else {$optstyle='std'; $padding=' ';}
    while($data=$result->fetch_row()){
        echo generateOption($optstyle.'option', $data, $padding);
        generateOptions($data[0], $level++, $padding, $db);
    }
}

function generateOption($type,$data, $padding){
    switch($type){
    case 'boldoption': return '<option class="bold"  value="'.$data[0].'">'.$padding.$data[1]."</option>\n"; break;
    case 'stdoption': return '<option class="std"  value="'.$data[0].'">'.$padding.$data[1]."</option>\n"; break;
    }
}

And here is the screenshot of my db table. http://prntscr.com/39461

The final working result

function generateOptions($parent, $level, $padding, $db)
{
    $result=$db->query("SELECT id, name FROM menu WHERE parent='$parent' AND showinmenu!='0'");
    $spacer = '&nbsp;&nbsp;'; 
    $padding = str_repeat($spacer, $level);
    while($data=$result->fetch_row()){      
        $children_html = generateOptions($data[0], $level+1, $padding, $db);
        $optstyle = empty($children_html) ? 'std' : 'bold';
        $html .= generateOption($optstyle.'option', $level, $data, $padding); 
        $html .= $children_html;
    }
    return $html;
}

function generateOption($type, $level, $data, $padding){
    $bgcolor=array('0'=>'#f66e02','1'=>'#FF9C4D', '2'=>'#FF9C4D');
    $fontcolor=array('0'=>'#fff','1'=>'#000', '2'=>'#000');
    switch($type){
    case 'boldoption': return '<option class="bold" style="background-color:'.$bgcolor[$level].'; color:'.$fontcolor[$level].'" value="'.$data[0].'">'.$padding.$data[1]."</option>\n"; break;
    case 'stdoption': return '<option class="std"  value="'.$data[0].'">'.$padding.$data[1]."</option>\n"; break;
    }
}
hakre
  • 193,403
  • 52
  • 435
  • 836
demonoid
  • 318
  • 3
  • 13
  • 40

3 Answers3

2

Your indentation problem you can easily solve by multiplying the $level by the number of pixels for a simple indent (3px in your case).

For the bold problem you need a different approach as in your current code, you don't know if the item has any children. The solution to that would be to first get the children in a variable, then add the bold style if any exist, echo the item and only then process the children.

Personally I would first get all data from the database in one pass, then build the hierarchical structure and then use a different function to generate the html. See for example this question for more details.

Edit: Based on your updated question; you can easily optimize it and get rid of the query in the while loop (I'd still go for the option in the previous paragraph by the way...):

  • Don't echo anything, just return a string from your function
  • Get rid of the query in the while function
  • Swap the echo and the function call lines

The result in your function would be something like:

....
$html = '';
while (...)
{
    $children_html = generateOptions($data[0], $level+1, $padding, $db);
    $optstyle = empty($children_html) ? 'std' : 'bold';
    $html .= generateOption($optstyle.'option', $data, $padding); 
    $html .= $children_html;
}
return $html;

and just do a echo generateOptions(...) where you called the function before.

Community
  • 1
  • 1
jeroen
  • 91,079
  • 21
  • 114
  • 132
  • i can't figure out how to implement the link that you've sent to my code – demonoid Sep 29 '11 at 17:22
  • There are 3 steps: First you get your database information in a flat array, then you transform that flat array in a multi-dimensional array (using a variation of that recursive function) and then you can write different (recursive...) functions to generate the html output you want (or just one for the `options` in your case). – jeroen Sep 29 '11 at 17:48
  • @user971388 Ouch! That's a lot of db queries, especially considering it's a recursive function! – jeroen Sep 29 '11 at 18:47
1

It looks like you might need to be adding more &nbps;'s to your padding where you're just assigning it to one space.

else {$optstyle='std'; $padding='&nbsp;';}

to

else {$optstyle='std'; $padding .='&nbsp;';}
jprofitt
  • 10,874
  • 4
  • 36
  • 46
0

You are trying to map a flat data structure (list) into a tree visually.

Before you can do this in a simple manner, you need to gather the date that is influencing the display to the list.

E.g. you could add a level per entry (1, 2 or 3), which looks like that being your recursive structure already!

Then you pass the modified list to the display routine, that only needs to decide based on the level how to display the entry, for each level:

  1. font-weight: bold;
  2. padding-left: 3px; font-weight: bold;
  3. padding-left: 6px;

The easiest thing to achieve that is to assing a class attribute to the elements parent HTML tag like level-1, level-2 etc..

You already have a $level variable, but I see an error, you increment it all the time, but you only need to pass the value:

generateOptions($data[0], $level+1, $padding, $db);

It might be that this already solves your issue.

hakre
  • 193,403
  • 52
  • 435
  • 836
  • it's not clear for me. can we continue discussion on skype or any other im? – demonoid Sep 29 '11 at 15:59
  • Can you provide your tables data in form of an array in your question as well? If you do so, I should be able to write something up so you can better see what I mean, – hakre Sep 29 '11 at 17:51