Reputation: 10168
I am working on a front-end web app where a nested unordered list would be used for the jQuery plugin mcdropdown.
Here is the data structure from PHP: a nested array of arrays :
Array
(
[0] => Array
(
[fullpath] => ../foil/alphanumeric/
[depth] => 0
)
[1] => Array
(
[fullpath] => ../foil/alphanumeric/letters/
[depth] => 1
)
[2] => Array
(
[fullpath] => ../foil/alphanumeric/numbers/
[depth] => 1
)
[3] => Array
(
[fullpath] => ../foil/alphanumeric/numbers/symbols/
[depth] => 2
)
)
Basically, I took the excellent answer from this question on SO, modified it a bit :
global $fullpaths; // $fullpaths contains the above data structure in print_r
$result = '';
$currentDepth = -1;
while(!empty($fullpaths))
{
$currentNode = array_shift($fullpaths);
if($currentNode['depth'] > $currentDepth)
{
$result .='<ul>';
}
if($currentNode['depth'] < $currentDepth)
{
$result .=str_repeat('</ul>', $currentDepth - $currentNode['depth']);
}
$result .= '<li>'. $currentNode['fullpath'] .'</li>';
$currentDepth = $currentNode['depth'];
if(empty($fullpaths))
{
$result .= str_repeat('</ul>', 1 + $currentDepth);
}
}
print $result;
and got the following output:
<ul>
<li>../foil/alphanumeric/</li>
<ul>
<li>../foil/alphanumeric/letters/</li>
<li>../foil/alphanumeric/numbers/</li>
<ul>
<li>../foil/alphanumeric/numbers/symbols/</li>
</ul>
</ul>
</ul>
Which cannot be accepted by the mcdropdown jQuery plugin, it expects something like this:
<li rel="1">
'Alphanumeric'
<ul>
<li rel="2">'Letters'</li>
<li rel="3">'Numbers'
<ul>
<li rel="4">'Symbols'</li>
</ul>
</li>
</ul>
</li>
To be frank, I don't quite understand how the answer from that question works, I have been trying to modify that solution to cope with my situation, but still failed.
Any help and suggestion is much appropriated in advance.
Upvotes: 3
Views: 586
Reputation: 9671
Does this code (indentation apart) produces the result you want?
$d = array(
0 => array(
'fullpath' => '../foil/alphanumeric/',
'depth' => 0
),
1 => array(
'fullpath' => '../foil/alphanumeric/letters/',
'depth' => 1
),
2 => array(
'fullpath' => '../foil/alphanumeric/numbers/',
'depth' => 1
),
3 => array(
'fullpath' => '../foil/alphanumeric/numbers/symbols/',
'depth' => 2
)
);
echo "<ul>\n";
$cdepth = 0; $rel = 1; $first = true; $veryfirst = true;
foreach($d as $e)
{
$mpath = "'" . ucfirst(basename($e['fullpath'])) ."'";
if ( $e['depth'] == $cdepth ) {
if ( $first && !$veryfirst) { echo "</li>\n";}
echo "<li rel=\"$rel\">", $mpath;
$rel++; $first = false; $veryfirst = false;
} else {
$depthdiff = $e['depth'] - $cdepth;
if ( $depthdiff < 0 ) {
for($i = 0; $i < -$depthdiff; $i++) {
echo "</ul>\n</li>\n";
}
} else {
for($i = 0; $i < $depthdiff; $i++) {
echo "\n<ul>\n";
$first = true;
// indeed buggy if $depthdiff > 1...
}
}
echo "<li rel=\"$rel\">", $mpath, "\n";
$rel++; $first = true;
}
$cdepth = $e['depth'];
}
for($i = 0; $i < $cdepth; $i++) {
echo "</ul>\n</li>\n";
}
echo "</ul>\n";
EDITED code: Still not perfect but you can work on it... :D
Upvotes: 2
Reputation: 145482
If you already have the correct depth values, then you don't need recursion. I have a similar function that I use for <ul>-<li>-generation:
function ulli($newlevel, &$level, $UL="ul", $once=1) {
if ($level == $newlevel) {
echo "</li>\n";
}
while ($level<$newlevel) {
$level++;
echo "\n <$UL>\n";
}
while ($level>$newlevel) {
if ($once-->0) { echo "</li>\n"; }
$level--;
echo " </$UL>"
. ($level>0 ? "</li>" : "") . "\n"; // skip for final </ul> (level=0)
}
}
It needs a current $level variable for reference (=$currentDepth). And you pass it your depth as $newlevel. It however needs the first depth to be 1.
Basic usage is like:
$currentDepth=0;
foreach ($array as $_) {
ulli($_["depth"]+1, $currentDepth);
echo "<li>$_[path]";
}
ulli(0, $currentDepth);
Well, quirky. But it worked for me.
Upvotes: 2