Solved

Drop down menu from flat file -- does not validate

Posted on 2006-06-20
5
290 Views
Last Modified: 2007-12-19
Hello,

I need to generate a CSS drop down menu from a flat text file.

MaUru gave me a head start:
http://www.experts-exchange.com/Web/Web_Languages/PHP/Q_21892373.html

But the end result does not validate: validator.w3.org and because of this it does not work with Mozilla.

Can you help fix the code so it validates?

I am running PHP 4.

Thank you very much!




<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd ">
<html>
<head>
<title>Suckerfish Dropdowns</title>

<style type="text/css">

body {
 font: 78%/1.5 arial, helvetica, serif;
 background: white url(bgbaba.gif);
 text-align: center;
 padding: 0;
 margin: 2em;
}

#container {
 width: 99em;
 background: #F4ECD9;
 text-align: left;
 border: 1px solid #eda;
 margin: 0 auto;
}

p {
 background: url(remorabg.gif) center no-repeat;
 margin: 1em 2em;
}

p#smurf {
 background: transparent;
 font-style: italic;
 text-align: center;
 font-weight: bold;
 color: #7C6240;
}

#smurf strong {
 font-size: 1.2em;
 color: black;
}

h1 {
 height: 108px;
 background: url(perciformes3.gif) bottom center no-repeat;
 text-indent: -999em;
 margin: 1em 0 0 0;
}

#nav, #nav ul {
 float: left;
 width: 99em;
 list-style: none;
 line-height: 1;
 background: white;
 font-weight: bold;
 padding: 0;
 border: solid #eda;
 border-width: 1px 0;
 margin: 0 0 1em 0;
}

#nav a {
 display: block;
 width: 10em;
 w\idth: 6em;
 color: #7C6240;
 text-decoration: none;
 padding: 0.25em 2em;
}

#nav a.daddy {
 background: url(rightarrow2.gif) center right no-repeat;
}

#nav li {
 float: left;
 padding: 0;
 width: 10em;
}

#nav li ul {
 position: absolute;
 left: -999em;
 height: auto;
 width: 14.4em;
 w\idth: 13.9em;
 font-weight: normal;
 border-width: 0.25em;
 margin: 0;
}

#nav li li {
 padding-right: 1em;
 width: 13em
}

#nav li ul a {
 width: 13em;
 w\idth: 9em;
}

#nav li ul ul {
 margin: -1.75em 0 0 14em;
}

#nav li:hover ul ul, #nav li:hover ul ul ul, #nav li.sfhover ul ul, #nav li.sfhover ul ul ul {
 left: -999em;
}

#nav li:hover ul, #nav li li:hover ul, #nav li li li:hover ul, #nav li.sfhover ul, #nav li li.sfhover ul, #nav li li li.sfhover ul {
 left: auto;
}

#nav li:hover, #nav li.sfhover {
 background: #eda;
}

#content {
 clear: left;
}

#content a {
 color: #7C6240;
}

#content a:hover {
 text-decoration: none;
}

#scaffolding {
 height: 70px;
 background: white url(/images/header_bg.gif) no-repeat;
 border: solid #eda;
 border-width: 1px 0 0 0;
 margin: 1em 0 0 0;
}

#scaffolding a {
 text-decoration: none;
 text-indent: -999em;
 display: block;
 height: 70px;
 background: url(/images/hdlogo_flip2.gif) no-repeat;
 background-position: 181px 0;
}

#scaffolding a:hover {
 background-position: 181px -70px;
}

</style>

<script type="text/javascript"><!--//--><![CDATA[//><!--

sfHover = function() {
 var sfEls = document.getElementById("nav").getElementsByTagName("LI");
 for (var i=0; i<sfEls.length; i++) {
  sfEls[i].onmouseover=function() {
   this.className+= " sfhover";
  }
  sfEls[i].onmouseout=function() {
   this.className=this.className.replace(new RegExp(" sfhover\\b"), "");
  }
 }
}
if (window.attachEvent) window.attachEvent ("onload", sfHover);

//--><!]]></script>

</head>
<body>
<div id="container">

<?
$s = '.|Percoidei|p.html|Description goes here
..|Remoras|r.html|This is a test
...|Echeneis|e.html|Sample Text
....|Sharksucker|s.html|Hello World
....|Whitefin Sharksucker|w.html|Random stuff here
...|Phtheirichthys|p.html|Fishy stuff
....|Slender Suckerfish|ss.html|Some words
.|Remora|re.html|Whatever goes here
..|Whalesucker|wh.html|This is for a description
...|Spearfish remora|sp.html|Some words
....|Marlinsucker|rm.html|Lorum Ispum
...|Remora|rr.html|Whatever goes here
....|Ceylonese remora|ce.html|Lorum Ispum';
$ulname = ' id="nav"';

$a = explode("\n", $s);

for ($i = 0; $i < count($a); $i++) {
     $n[] = explode("|", $a[$i]);
}

$lastdepth = 0;
$depth = 0;
for ($i = 0; $i < count($n); $i++) {


if (isset($n[$i][2]))
{

     global $ulname;
     $depth = strlen($n[$i][0]);
     if ($depth > $lastdepth) {
          echo mT($depth) . "<ul". $ulname .">\n";
          $ulname = null;
     }
     else if ($depth < $lastdepth) {
          echo mT($depth) . "</ul>\n";
     }
     echo mT($depth) . '<li><a href="' . $n[$i][2] . '" title="' . trim($n[$i][3]) . '">' . $n[$i][1] . '</a>' . "</li>\n";
     $lastdepth = $depth;
}
}
if ($lastdepth != 0) {
     for ($i = $lastdepth; $i > 0; $i--) {
          echo mT($i) . "</ul>\n";
     }
}

function mT($n) { //make tabs
     $result = '';
     for ($i = 0; $i < $n; $i++) {
          $result .= "  ";
     }
     return $result;
}
?>
</div>
</body>
</html>
0
Comment
Question by:hankknight
  • 5
5 Comments
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
Can you ...

1 - Show the View-source output.
2 - Use <?php rather than <?
3 - Supply a URL
4 - Let us what doesn't validate.

Any or all please?

Ah. I see about the validation.

Remove </li>.

Force of habit to always add <x></x> when I write code. Forgot that <li> doesn't need it.

The only other validation error I have (Using FF with HTML Validator Extension) is the doctype tag.

Change ...

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd ">

to ...

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

There is a trailing space in the dtd name.
0
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html>
<head>
<title>Suckerfish Dropdowns</title>

<style type="text/css">

body {
 font: 78%/1.5 arial, helvetica, serif;
 background: white url(bgbaba.gif);
 text-align: center;
 padding: 0;
 margin: 2em;
}

#container {
 width: 99em;
 background: #F4ECD9;
 text-align: left;
 border: 1px solid #eda;
 margin: 0 auto;
}

p {
 background: url(remorabg.gif) center no-repeat;
 margin: 1em 2em;
}

p#smurf {
 background: transparent;
 font-style: italic;
 text-align: center;
 font-weight: bold;
 color: #7C6240;
}

#smurf strong {
 font-size: 1.2em;
 color: black;
}

h1 {
 height: 108px;
 background: url(perciformes3.gif) bottom center no-repeat;
 text-indent: -999em;
 margin: 1em 0 0 0;
}

#nav, #nav ul {
 float: left;
 width: 99em;
 list-style: none;
 line-height: 1;
 background: white;
 font-weight: bold;
 padding: 0;
 border: solid #eda;
 border-width: 1px 0;
 margin: 0 0 1em 0;
}

#nav a {
 display: block;
 width: 10em;
 w\idth: 6em;
 color: #7C6240;
 text-decoration: none;
 padding: 0.25em 2em;
}

#nav a.daddy {
 background: url(rightarrow2.gif) center right no-repeat;
}

#nav li {
 float: left;
 padding: 0;
 width: 10em;
}

#nav li ul {
 position: absolute;
 left: -999em;
 height: auto;
 width: 14.4em;
 w\idth: 13.9em;
 font-weight: normal;
 border-width: 0.25em;
 margin: 0;
}

#nav li li {
 padding-right: 1em;
 width: 13em
}

#nav li ul a {
 width: 13em;
 w\idth: 9em;
}

#nav li ul ul {
 margin: -1.75em 0 0 14em;
}

#nav li:hover ul ul, #nav li:hover ul ul ul, #nav li.sfhover ul ul, #nav li.sfhover ul ul ul {
 left: -999em;
}

#nav li:hover ul, #nav li li:hover ul, #nav li li li:hover ul, #nav li.sfhover ul, #nav li li.sfhover ul, #nav li li li.sfhover ul {
 left: auto;
}

#nav li:hover, #nav li.sfhover {
 background: #eda;
}

#content {
 clear: left;
}

#content a {
 color: #7C6240;
}

#content a:hover {
 text-decoration: none;
}

#scaffolding {
 height: 70px;
 background: white url(/images/header_bg.gif) no-repeat;
 border: solid #eda;
 border-width: 1px 0 0 0;
 margin: 1em 0 0 0;
}

#scaffolding a {
 text-decoration: none;
 text-indent: -999em;
 display: block;
 height: 70px;
 background: url(/images/hdlogo_flip2.gif) no-repeat;
 background-position: 181px 0;
}

#scaffolding a:hover {
 background-position: 181px -70px;
}

</style>

<script type="text/javascript"><!--//--><![CDATA[//><!--

sfHover = function() {
 var sfEls = document.getElementById("nav").getElementsByTagName("LI");
 for (var i=0; i<sfEls.length; i++) {
  sfEls[i].onmouseover=function() {
   this.className+= " sfhover";
  }
  sfEls[i].onmouseout=function() {
   this.className=this.className.replace(new RegExp(" sfhover\\b"), "");
  }
 }
}
if (window.attachEvent) window.attachEvent ("onload", sfHover);

//--><!]]></script>

</head>
<body>
<div id="container">

<?php
function generateHTML($a_results)
      {
      $s_result = '';
      foreach($a_results as $s_key => $a_data)
            {
            $s_sub_menu = (isset($a_data['Children']) && (count($a_data['Children']) > 0)) ? generateHTML($a_data['Children']) : '';
            $s_class = ($s_sub_menu !== '') ? ' class="daddy"' : '';
            $s_result .= "<li><a href=\"#\"{$s_class}>{$s_key}</a>{$s_sub_menu}";
            }
      return "<ul>{$s_result}</ul>";
      }
// Get the menu.
$a_file = file('c:/menu.txt');

// Define results array.
$a_results = array();

// Define the keys to navigate each level whilst building.
$a_keys = array();

// Process each line into the array.
foreach($a_file as $s_line)
      {
      // Extract the parts.
      preg_match('`(\.*)\|?(.*?)\|(.*\.html)\|(.*)`sim', $s_line, $a_matches);

      // Determine the number of levels.
      $i_level = strlen($a_matches[1]) - 1;
      
      // Remove any remaining keys
      array_splice($a_keys, $i_level);
      
      // Populate the keys array
      $a_keys[$i_level] = $a_matches[2];
      
      // Build the result key
      $s_results_key = "['" . implode("']['Children']['", $a_keys) . "']";
      eval ("\$a_results['" . implode("']['Children']['", $a_keys) . "'] = array
            (
            'Children' => array(),
            'URL' => '{$a_matches[3]}',
            'Desc' => '{$a_matches[4]}',
            );");
      }

// Generate output.
$s_HTML_output = /*tidy_repair_string(*/generateHTML($a_results)/*, array('show-body-only' => True, 'indent' => 4))*/;
echo $s_HTML_output;
?>
</div>
</body>
</html>

produces output of ...

    * Percoidei
          o Remoras
                + Echeneis
                      # Sharksucker
                      # Whitefin Sharksucker
                + Phtheirichthys
                      # Slender Suckerfish
                + Remora
                      # Whalesucker
                      # Spearfish remora
                      # Marlinsucker
                      # Remora
                      # Ceylonese remora
                + Remorina
                      # White suckerfish
                + Rhombochirus
                      # Rosteochir
          o Tilefishes
                + Caulolatilus
                + Lopholatilus
                + Malacanthus
          o Bluefishes
                + Pomatomus
                + Scombrops
                + Sphyraenops
          o Tigerfishes
                + Amniataba
                + Bidyanus

(Hey! Cut and paste looks GOOD!).

And the validation report ...

-
0 errors / 0 warnings

0
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
Using the supplied script I get ...

#  $lastdepth) { echo mT($depth) . "\n"; $ulname = null; } else if ($depth < $lastdepth) { echo mT($depth) . "\n"; } echo mT($depth) . '' . $n[$i][1] . '' . "
\n"; $lastdepth = $depth; } } if ($lastdepth != 0) { for ($i = $lastdepth; $i > 0; $i--) { echo mT($i) . "\n"; } } function mT($n) { //make tabs $result = ''; for ($i = 0; $i < $n; $i++) { $result .= " "; } return $result; } ?>

Which is due to the short tags (gone in PHP6 and not recommend in PHP5).

Fixing that ...

Results in the same error I had with the </li>.

Removing that does seem to work (Hey- different behaviour) but still validation errors.

So. A nav id later ...

<?php
function generateHTML($a_results)
      {
      $s_result = '';
      foreach($a_results as $s_key => $a_data)
            {
            $s_sub_menu = (isset($a_data['Children']) && (count($a_data['Children']) > 0)) ? generateHTML($a_data['Children']) : '';
            $s_class = ($s_sub_menu !== '') ? ' class="daddy"' : '';
            $s_result .= "<li><a href=\"#\"{$s_class}>{$s_key}</a>{$s_sub_menu}";
            }
      return "<ul>{$s_result}</ul>";
      }
// Get the menu.
$a_file = file('c:/menu.txt');

// Define results array.
$a_results = array();

// Define the keys to navigate each level whilst building.
$a_keys = array();

// Process each line into the array.
foreach($a_file as $s_line)
      {
      // Extract the parts.
      preg_match('`(\.*)\|?(.*?)\|(.*\.html)\|(.*)`sim', $s_line, $a_matches);

      // Determine the number of levels.
      $i_level = strlen($a_matches[1]) - 1;
      
      // Remove any remaining keys
      array_splice($a_keys, $i_level);
      
      // Populate the keys array
      $a_keys[$i_level] = $a_matches[2];
      
      // Build the result key
      $s_results_key = "['" . implode("']['Children']['", $a_keys) . "']";
      eval ("\$a_results['" . implode("']['Children']['", $a_keys) . "'] = array
            (
            'Children' => array(),
            'URL' => '{$a_matches[3]}',
            'Desc' => '{$a_matches[4]}',
            );");
      }

// Generate output.
$s_HTML_output = preg_replace('`<ul>`sim', '<ul id="nav">', generateHTML($a_results), 1);
echo $s_HTML_output;
?>

and fully valid output and the navigation working fine.
0
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
Oh.

Change ...

// Get the menu.
$a_file = file('c:/menu.txt');

to

// Get the menu.
$a_file = file('./menu.txt');

as you did initially have the menu in a text file.
0
 
LVL 40

Accepted Solution

by:
RQuadling earned 500 total points
Comment Utility
Try ...

// Process each line into the array.
foreach($a_file as $s_line)
      {
      // Extract the parts.
      preg_match('`(\.*)\|?(.*?)\|(.*\.html)\|(.*)`sim', $s_line, $a_matches);

      // Determine the number of levels.
      $i_level = strlen($a_matches[1]) - 1;
      
      // Remove any remaining keys
      array_splice($a_keys, $i_level);
      
      // Populate the keys array
      $a_keys[$i_level] = htmlentities($a_matches[2]);
      
      // Build the result key
      $s_results_key = "['" . implode("']['Children']['", $a_keys) . "']";
      eval ("\$a_results['" . implode("']['Children']['", $a_keys) . "'] = array
            (
            'Children' => array(),
            'URL' => '" . addslashes($a_matches[3]) . "',
            'Desc' => '" . addslashes($a_matches[4]) . "',
            );");
      }

this code to deal with & and ' in their.

and

function generateHTML($a_results)
      {
      $s_result = '';
      foreach($a_results as $s_key => $a_data)
            {
            $s_sub_menu = (isset($a_data['Children']) && (count($a_data['Children']) > 0)) ? generateHTML($a_data['Children']) : '';
            $s_class = ($s_sub_menu !== '') ? ' class="daddy"' : '';
            $s_result .= "<li><a href=\"{$a_data['URL']}\"{$s_class}>{$s_key}</a>{$s_sub_menu}";
            }
      return "<ul>{$s_result}</ul>";
      }

to put the URL in.
0

Featured Post

Easy Project Management (No User Manual Required)

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Popularity Can Be Measured Sometimes we deal with questions of popularity, and we need a way to collect opinions from our clients.  This article shows a simple teaching example of how we might elect a favorite color by letting our clients vote for …
Both Easy and Powerful How easy is PHP? http://lmgtfy.com?q=how+easy+is+php (http://lmgtfy.com?q=how+easy+is+php)  Very easy.  It has been described as "a programming language even my grandmother can use." How powerful is PHP?  http://en.wikiped…
The viewer will learn how to dynamically set the form action using jQuery.
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now