I'm building navigation for a site and for the life of me I can't figure out recursion. I have all my data stored via MySQL using this design:
I've read several links on how recursion works and I must be slow because it's difficult for me to grasp. I've tried to write something and I know it is not even close to what I really need, but it's a start:
PDO
public function viewCategories()
{
$viewSQL = "SELECT * FROM categories";
try
{
$pdo = new PDO('mysql:host=localhost;dbname=store','root','');
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
$categoryVIEW = $pdo->prepare($viewSQL);
$categoryVIEW->execute();
$array = $categoryVIEW->fetchAll(PDO::FETCH_ASSOC);
$categoryVIEW->closeCursor();
$json = json_encode($array);
return $json;
}
catch(PDOexception $e)
{
return $e->getMessage();
exit();
}
}
Recursion
$return = json_decode($category->viewCategories(),true);
function buildNavigation($json)
{
foreach($json as $item)
{
if($item['category_id'] === $item['parent'])
{
print('<li>'.$item['category_name'].'</li>');
if($item['category_id'] === $item['parent'])
{
print('<li>match'.$item['category_name'].'</li>');
buildNavigation($json);
}
}
}
buildNavigation($return);
as expected this will never enter the condition. I did try to figure this out on my own since this is a good thing to have knowledge of, but I guess it's beyond my mental capacity :(
Thanks for having a look :)
UPDATE
I know this has been answered already, but is there a way I can do this to build an associative array? I have been playing around with a function that ALMOST works for me that I got from HERE, but it adds an extra array that I do NOT want.
Method
private function buildCategories($array,$parent)
{
$result = array();
foreach($array as $row)
{
if($row['parent'] == $parent)
{
$result[$row['category_name']] = $this->buildCategories($array,$row['category_id']);
}
}
return $result;
}
$json = json_encode($this->buildCategories($array,NULL));
return $json;
I want this:
{"reloading":{"components","presses and dies","tumblers & scales","tools & accessories","shotshell reloading"}
but what I get is this:
{"reloading":{"components":[],"presses and dies":[],"tumblers & scales":[],"tools & accessories":[],"shotshell reloading":[]}
Here's an example with recursion.
function buildNavigation($items, $parent = NULL)
{
$hasChildren = false;
$outputHtml = '<ul>%s</ul>';
$childrenHtml = '';
foreach($items as $item)
{
if ($item['parent'] == $parent) {
$hasChildren = true;
$childrenHtml .= '<li>'.$item['category_name'];
$childrenHtml .= buildNavigation($items, $item['category_id']);
$childrenHtml .= '</li>';
}
}
// Without children, we do not need the <ul> tag.
if (!$hasChildren) {
$outputHtml = '';
}
// Returns the HTML
return sprintf($outputHtml, $childrenHtml);
}
print buildNavigation($items);
That script produces the following output :
<ul>
<li>Menu 1</li>
<li>Menu 2
<ul>
<li>Sub Menu 2.1</li>
<li>Sub Menu 2.2</li>
<li>Sub Menu 2.3
<ul>
<li>Sub Menu 2.2.1</li>
<li>Sub Menu 2.2.2</li>
<li>Sub Menu 2.2.3</li>
</ul>
</li>
</ul>
</li>
<li>Menu 3</li>
</ul>
I have the same above code with little bit modification, so that a user can apply different css on each level of menu, now its showing classes of sub menu like child-class1 when its in 1st sub menu , and it will show child-class2 when its in 2nd sub menu and so on...
<?php
function buildNavigation($items, $parent = NULL, $n=NULL)
{
$hasChildren = false;
if ($parent == NULL)
{
$level=0;
$outputHtml = '<ul class="parent-class">%s</ul>';
}
else
{
if($n==NULL)
{
$level=1;
}
else
{
$level=$n;
}
$outputHtml = '<ul class="child-class'.$level.'">%s</ul>';
}
$childrenHtml = '';
foreach($items as $item)
{
if ($item['parent'] == $parent) {
$hasChildren = true;
$childrenHtml .= '<li>'.$item['ptitle'].'';
$next = ++$level;
$childrenHtml .= buildNavigation($items, $item['pageid'],$next);
$childrenHtml .= '</li>';
}
}
// Without children, we do not need the <ul> tag.
if (!$hasChildren) {
$outputHtml = '';
}
// Returns the HTML
return sprintf($outputHtml, $childrenHtml);
}
echo buildNavigation($ppages);
?>
it will show out put like this
<ul class="parent-class">
<li>
page 1
<ul class="child-class1">
<li>
this is child page
<ul class="child-class2">
<li>
child of child </li>
</ul>
</li>
</ul>
</li>
</ul>
I would like to thanks Mr #Maxime Morin.
Related
I got a dynamic menu that uses bootstrap, but one menu button has about 14 child items. Way too long for a website, so I want to split it in half.
This is the code that I'm trying to replicate:
<ul class="dropdown-menu dropdown-menu-large row" role="menu">
<li class="col-sm-6">
<ul>
<li>Life Insurance</li>
<li>Home Insurance</li>
<li>Travel Insurance</li>
<li>Pet Insurance</li>
</ul>
</li>
<li class="col-sm-6">
<ul>
<li>Boat Insurance</li>
<li>Auto Insurance</li>
<li>Bike Insurance</li>
<li>Business Insurance</li>
</ul>
</li>
</ul>
This is what I tried:
$tel = 1;
foreach ( $nmenuccr as $cmenu ) {
// If id matches and category id is 11 (services) split in half
if ( $cmenu['id'] && $cmenu['catid'] == '11' ){
if($tel == 1) {
$hmenu .= '<li class="col-sm-6"><ul>';
}
$hmenu.= '
<li>'.$cmenu['title'].'</li>
';
if(($tel % 7) == 0){
$hmenu .= '</ul></li> <li class="col-sm-6"><ul>';
}
$tel++;
if(($tel % 7) != 0){
$menu .= '</li>';
}
//Else use the normal dropdown layout
}else{
if (strlen($cmenu['title']) > 25){
$shortstrmen = substr($cmenu['title'], 0, 25) . '...';
$hmenu.= '
<li>'.$shortstrmen.'
';
}else{
$hmenu.= '
<li>'.$cmenu['title'].'
';
}
}
}
However this returns the following code:
https://jsfiddle.net/sms16v44/
Does anyone see what I am doing wrong?
Instead of trying to alter your code, I came up with the following. This allows you to automatically create sub menu's out of a menu. I hope it helps out.
It creates it like the following screenshot:
and the other function/way:
<?php
// recreating dummy menu data
function createDummyList() {
$nmenuccr = array();
for($i=0;$i<24;$i++) {
$a = array();
$a['id']=$i;
$a['catid']=$i;
$a['alias']="alias $i";
$a['title']="title $i";
array_push($nmenuccr, $a);
}
return $nmenuccr;
}
/**
* Parse a menu into smaller menu's
* #param type $menu the main menu
* #param type $class html class
* #param type $max_sub_items max items before creating a new submenu
* #param type $submenu (used for recursion)
* #return string
*/
function createMenuList(&$menu, $class, $max_sub_items) {
$out = "<ul class='$class'><li>";
// shift items
$submenu = array();
$i=0;
$loop=0;
while(count($menu) > 0) {
array_push($submenu, array_shift($menu));
$i++;
if ($i == $max_sub_items || count($menu) == 0) {
$out .= createList($submenu, $loop);
$out .= '<li>In between</li>';
$i=0;
$submenu = array();
$loop++;
}
}
$out .= "</li></ul>";
return $out;
}
/**
*
* #param type $list
* #param type $submenu_label
* #return string
*/
function createList(&$list, $loop) {
$out = '<ul>';
foreach($list as $l) {
$out .= '<li>'.$l['title'].'</li>';
}
$out .= '</ul>';
return $out;
}
/**
* Parse a menu into smaller menu's
* #param type $menu the main menu
* #param type $class html class
* #param type $max_sub_items max items before creating a new submenu
* #param type $submenu (used for recursion)
* #return string
*/
function createSubMenuList(&$menu, $class, $max_sub_items, $submenu = 0) {
// create new list
$out = "<ul class='$class'>";
// shift items
for($i=0;$i<$max_sub_items;$i++) {
$item = array_shift($menu);
// add item to list
if (isset($item)) {
$out .= '<li>'.$item['title'].'</li>';
}
}
// check if we're done
if (count($menu) > 0) {
$submenu++;
$out .= "<li class='submenu_$submenu'>";
// create submenu in parent menu
$out .= createSubMenuList($menu, $class, $max_sub_items, $submenu);
$out .= "</li>";
}
$out .= "</ul>";
return $out;
}
// call menu creation function
$list1=createDummyList();
$list2=createDummyList();
echo createSubMenuList($list1, 'hoofdmenu', 7);
echo "<hr />";
echo createMenuList($list2, 'hoofdmenu', 7);
?>
It would be easier to help if you could include the output array as comment too.
However, try this. Change this:
if(($tel % 7) != 0){
$menu .= '</li>';
}
to:
if(($tel % 7) != 0){
$menu .= '</ul></li>';
}
Hopefully it will work
Keepin it a junky piece of code, you can just quick-fix it this way:
$tel = 0;
/* .. */
// If id matches and category id is 11 (services) split in half
if ( $cmenu['id'] && $cmenu['catid'] == '11' ){
if(++$tel == 1) {
$hmenu .= '<li class="col-sm-6"><ul>';
}
$hmenu.= '<li>'.$cmenu['title'].'</li>';
if(($tel % 7) == 0){
if ($tel == 7) {
$hmenu .= '</ul></li><li class="col-sm-6"><ul>';
} else {
$hmenu .= '</ul></li>';
}
}
//Else use the normal dropdown layout
} // ..
Working example (updated):
http://sandbox.onlinephpfunctions.com/code/13fd6974cd66c847747f44a4be9b892aa47e4979
But you should refactor your $nmenuccr through a function, which will make it an array reflecting the target structure of menu to KISS the view-generating part of code.
Edit: updated operations on $tel.
Try this for any length of menu.....
<ul class="dropdown-menu dropdown-menu-large row" role="menu">
<?php
$counter = 1;
foreach ($nmenuccr as $cmenu ) {
if($counter == 1){
echo '<li class="col-sm-6"><ul>';
}//.... end of if() .....//
echo '<li>'.$cmenu['title'].'</li>';
$counter ++;
if($counter == 5){
echo "</ul></li>";
$counter = 1;
}//.... end of if() .....//
}//.... end of foreach() .....//
?>
</ul>
Your check for category ID 11 didn't seem pertinent to your question, so I didn't include that logic in there. Things become a lot simpler when you leave the opening and closing parts outside the loop. Then, you're only outputting your repeated item, and checking for the one case ($tel % 4) where you put a divider in.
<?php
$nmenuccr = [ // sample data
["alias"=>"life-insurance", "title"=>"Life Insurance"],
["alias"=>"life-insurance", "title"=>"Home Insurance"],
["alias"=>"life-insurance", "title"=>"Travel Insurance"],
["alias"=>"life-insurance", "title"=>"Pet Insurance"],
["alias"=>"life-insurance", "title"=>"Boat Insurance"],
["alias"=>"life-insurance", "title"=>"Auto Insurance"],
["alias"=>"life-insurance", "title"=>"Bike Insurance"],
["alias"=>"life-insurance", "title"=>"Business Insurance"],
];
$hmenu = "<li class=\"col-sm-6\">\n\t<ul>\n";
foreach ($nmenuccr as $tel=>$cmenu) {
if ($tel % 4 == 0 && $tel > 0) {
$hmenu .= "\t</ul>\n</li>\n<li class=\"col-sm-6\">\n\t<ul>\n";
}
$hmenu.= "\t\t<li>$cmenu[title]</li>\n";
}
$hmenu .= "\t</ul>\n</li>";
echo $hmenu;
Output:
<li class="col-sm-6">
<ul>
<li>Life Insurance</li>
<li>Home Insurance</li>
<li>Travel Insurance</li>
<li>Pet Insurance</li>
</ul>
</li>
<li class="col-sm-6">
<ul>
<li>Boat Insurance</li>
<li>Auto Insurance</li>
<li>Bike Insurance</li>
<li>Business Insurance</li>
</ul>
</li>
I've been doing some researching and discovered this nice website http://validator.w3.org/
After running a test i see that my navigation get loads of error.
The error i get is the ul in the coding. I don't close it off because i give it it styling if a condition is met else close it.
But this is not a valid solution according to w3 which gives me some errors.
Can you help me find a fix for my navigation so it gets valid?
With thanks Jim
<ul id="nav-container">
<?php
$select_category = mysql_query("SELECT * FROM menu WHERE hidden = 0 ORDER BY menu ASC");
while ($ln = mysql_fetch_array($select_category)) {
$idcat = $ln['nmr'];
$catname = $ln['menu'];
$catsname = str_replace(' ', '-', $ln['menu']);
echo '<li>';
if($catname == "carparts") {
echo '<span><strong>'.$catname.'</strong></span>';
} else {
echo '<span><strong>'.$catname.'</strong></span>';
}
This gives me the errors: (fixed)
echo '<ul';
if(isset($_GET['cats'])) {
if ($_GET['cats'] == $idcat) {
echo ' style="display:block;">';
} else {
echo '>';
}
The fix: also deleted the closing bracket at the end.
echo '<ul';
if(isset($_GET['cats']) && $_GET['cats'] == $idcat){
echo ' style="display:block;">';
} else {
echo '>';
}
/fix finish
//Error finish
$select_sub = mysql_query("SELECT * FROM submenu WHERE nmrmenu = '$idcat' AND hidden = 0");
while ($lsub = mysql_fetch_array($select_sub)) {
$subname = $lsub['submenu'];
$subsname = str_replace(' ', '-', $lsub['submenu']);
$pil = 'ยป';
$brnr = $lsub['nmr'];
if(isset($_GET['cat'])) {
if ($_GET['cat'] == $brnr) {
$subname = '<u>'.$lsub['submenu'].'</u>';
} else {
$subname = $lsub['submenu'];
}
}
echo '<li><span><strong> '.$subname.' </strong></span></li>';
}
echo '</ul>';
echo '</li>'; // to this location
}
echo '</li>'; //relocated this up one line
} **//Deleted this one!**
?>
</ul>
Update
The output gets like this which is horrible: (fixed)
<ul</li><li><span><strong>name</strong></span>
<ul</li><li><span><strong>name</strong></span><ul</li>
New: now the ul problem is gone, but it's complaining about the li's. Any clue why?
Error: document type does not allow element "li" here; missing one of "ul", "ol", "menu", "dir" start-tag
<ul id="nav-container">
<li>
<span><strong>name</strong></span>
<ul>
<li>
<span><strong> name </strong></span>
</li>
</ul>
</li>
</ul>
/update
You have </ul> and then immediately follow it with a <li>. You can't have a list item outside of a list.
I have a nested foreach loop running through categories in a database. When the user is viewing a category the category ID is set and that menu item gets it's class set as "active".
The issue I'm having is when a user is viewing a subcategory, I still need it's PARENT to be set to active.
// Run through category ID's and output info
foreach ($GLOBALS['AKB_CLASS_HELPER']->tree->nodesByPid[$catid] as $rowid) {
$row = $GLOBALS['AKB_CLASS_HELPER']->catsById[$rowid];
//Check to see if user has access
if (($accessible_cats !== false) && (!in_array($row['categoryid'],$accessible_cats)) && ($row['security'] == "private")) {
continue;
}
// If we're viewing a category, output "active" as a class in the menu
if (isset($GLOBALS['CategoryId'])
&& ($GLOBALS['CategoryId']) == $row['categoryid']) {
$activeCat = "active";
} else {
$activeCat = "";
}
//Pass through global variables
$GLOBALS['Link'] = GetUrl('category', $row['categoryid']);
$GLOBALS['Text'] = $GLOBALS['AKB_CLASS_TEMPLATE']->DisablePlaceholders(strip_tags($row['name']));
$GLOBALS['Active'] = $activeCat;
$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet('CategoryRowCell');
//If subcategories exist
if (isset($GLOBALS['AKB_CLASS_HELPER']->tree->nodesByPid[$rowid])
&& is_array($GLOBALS['AKB_CLASS_HELPER']->tree->nodesByPid[$rowid])
&& !empty($GLOBALS['AKB_CLASS_HELPER']->tree->nodesByPid[$rowid])) {
$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet('CategoryGridHeaderSub');
//For every subcategory, output data
foreach ($GLOBALS['AKB_CLASS_HELPER']->tree->nodesByPid[$rowid] as $subrowid) {
$subrow = $GLOBALS['AKB_CLASS_HELPER']->catsById[$subrowid];
//Here's the part I can't get working. Need to output "active" to the PARENT id($row I believe)
if (isset($GLOBALS['CategoryId'])
&& ($GLOBALS['CategoryId']) == $subrow['categoryid']) {
$activeCat = "active";
} else {
$activeCat = "";
}
//Set Global Variables
$GLOBALS['Link'] = GetUrl('category', $subrow['categoryid']);
$GLOBALS['Text'] = $GLOBALS['AKB_CLASS_TEMPLATE']->DisablePlaceholders(strip_tags($subrow['name']));
$GLOBALS['Active'] = $activeCat;
$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet('CategoryRowCellSub');
}
}
$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet('CategoryGridFooterSub');
}
So the part I need to figure out is in the nested foreach loop, how can I affect the parent ID or something of the like.
Current Output when viewing parents(Working perfectly)
<li class="categoryItem active">Parent 1
<ul class="categorySubList">
<li class="categorySubItem"><a class="categorylink" href="/categories/Parent+1/Subcategory+1/">Subcategory 1</a></li>
<li class="categorySubItem "><a class="categorylink" href="/categories/Parent+1/Subcategory+2/">Subcategory 2</a></li>
</ul>
Current Output when viewing children(not working)
<li class="categoryItem">Parent 1<!--this list item needs to be active-->
<ul class="categorySubList">
<li class="categorySubItem active"><a class="categorylink" href="/categories/Parent+1/Subcategory+1/">Subcategory 1</a></li>
<li class="categorySubItem "><a class="categorylink" href="/categories/Parent+1/Subcategory+2/">Subcategory 2</a></li>
</ul>
I am trying to add a dynamic recursive navigation list menu to a site of am working on.
The scenerio is that the menu has 2 levels related by a parentid(preid).
My issue is that I can display the 1st level list correctly, however I cannot get the second level to display properly. I am not sure where to add the UL and /UL tags for the second level.
This is what I am after
<ul>
<li>Item 1</li>
<li>item 2</li>
<li>item 3</li>
<ul>
<li>sub item 1</li>
<li>sub item 2</li>
</ul>
<li>Item 4</li>
<li>item 5</li>
<ul>
<li>sub item 1</li>
<li>sub item 2</li>
</ul>
<li>item 6</li>
</ul>
This is actually what i am getting with the below code:
<ul>
<li>item 1
<ul>
</ul>
</li>
<li>item 2
<ul>
<li>sub item 1</li>
<ul>
</ul>
<li>sub item 2</li>
<ul>
</ul>
</ul>
</li>
<li>Sports Injuries
<ul>
</ul>
</li>
</ul>
</li>
</ul>
Below is the class file I am using to create the menu:
class Dynamic_Menu
{
function getConfig()
{
$this->DB_SERVER = 'localhost';
$this->DB_USER = '***';
$this->DB_PASS = '***';
$this->DB_NAME = '***';
}
function __construct()
{
$this->getConfig();
$Conn = mysql_connect($this->DB_SERVER, $this->DB_USER, $this->DB_PASS);
if (!$Conn)
die("Error: ".mysql_errno($Conn).":- ".mysql_error($Conn));
$DB_select = mysql_select_db($this->DB_NAME, $Conn);
if (!$DB_select)
die("Error: ".mysql_errno($Conn).":- ".mysql_error($Conn));
}
function select_row($sql)
{
//echo $sql . "<br />";
if ($sql!="")
{
$result = mysql_query($sql) or die("Error: ".mysql_errno().":- ".mysql_error());
if ($result)
{
while($row = mysql_fetch_array($result))
$data[] = $row;
}
return $data;
}
}
function recordCount($sql)
{
if ($sql!="")
{
$result = mysql_query($sql) or die("Error: ".mysql_errno().":- ".mysql_error());
if ($result)
{
$cnt = mysql_num_rows($result);
return $cnt;
}
}
}
function getChild($id)
{
$menu = "";
$str = "";
$s = "SELECT * FROM vcms_sys_explorer WHERE preid = '$id' ";
$res = $this->select_row($s);
$menu .= '<ul>';
for ($i=0;$i<count($res);$i++)
{
$cnt_of_child = $this->recordCount("SELECT * FROM vcms_sys_explorer where preid = '".$res[$i][eid]."' ");
//if ($cnt_of_child > 0)
// $str = '';
//else
// $str = " (is sub menu item)";
$menu .= '<li>'. $res[$i][name].$str.'</li>';
$menu .= $this->getChild($res[$i][eid]);
}
$menu .= '</ul>';
return $menu;
}
function getMenu($parentid)
{
$menu = "";
$s = "SELECT * FROM vcms_sys_explorer WHERE preid = '$parentid' ";
$res = $this->select_row($s);
$menu .= '<ul>';
for ($i=0;$i<count($res);$i++)
{
$menu .= '<li>'.$res[$i][name].$this->getChild($res[$i][eid]).'</li>';
if ((count($res) - 1) > $i) {
}
}
$menu .= '</ul>';
return $menu;
}
}
I call the menu with:
$menu = new Dynamic_Menu();
$menu->getMenu(1);
Could someone please help and explain where I need to place the level 2 UL and /UL tags. I have been banging my head with this for the last 2 days.
Any help would be greatly appreciated, thanks...
In a nested list, sub-lists will always be contained within a list element-- that's what makes them nested. You can print a full list in just one function using this format (in generic code, but you should get the basic idea):
function get_list($parent) {
$children = query('SELECT * FROM table WHERE parent_id = '.$parent);
$items = array();
while($row = fetch_assoc($children)) {
$items[] = '<li>'.$row['name'].get_list($row['id']).'</li>';
}
if(count($items)) {
return '<ul>'.implode('', $items).'</ul>';
} else {
return '';
}
}
And this will give you a list structured properly as:
<ul>
<li>Item 1</li>
<li>Item 2
<ul>
<li>Item 2.1</li>
<li>Item 2.2</li>
</ul>
</li>
</ul>
All though this question is not the exact same as the question I posted 2 days ago, here is the result of what I was attempting to do with folders rather than a DB. The following will traverse the directory and all sub directories of the specified $path and spits out the results in a nested un-ordered list upon completion of running the script. Hope it helps.
<?php
function readDirs($path){
$dirHandle = opendir($path);
echo "<ul>";
while ($item = readdir($dirHandle)) {
$newPath = $path . "/" . $item;
if (is_dir($newPath) && $item != '.' && $item != '..') {
echo "<li><a href='$newPath'>$item</a>";
readDirs($newPath);
}
}
echo "</li></ul>";
}
$path = "./galleries";
readDirs($path);
?>
I need to take some simple UL tag generated in PHP (Joomla 1.5) and wrap each anchor tag's text content with a SPAN tag. The incoming HTML looks like this:
<ul>
<li>
Home
</li>
<li>
Watch UNC-TV
</li>
<li>
<a href="#" >Contact</a>
</li>
</ul>
The output needs to look like this:
<ul id="top-nav" class="flatList">
<li class="selected">
<a href="#"><span class="embed embed-top-nav">Home</span>
<p >news, highlights</p></a>
</li>
<li>
<a href="#"><span class="embed embed-top-nav">Watch UNC-TV</span>
<p>schedule, local programs</p></a>
</li>
<li id="nav-last">
<a href="#"><span class="embed embed-top-nav">Contact</span>
<p>feedback, connect, share</p></a>
</li>
</ul>
Also note the class added to the active LI tag ("selected") and the class added to the last one in the list ("nav-last"). This is in Joomla 1.5, where I'm overriding the mod_mainmenu module used by the Main Menu. The code uses the SimpleXML library to read and write the HTML in the modMainMenuXMLCallback(&$node, $args):
<?php
defined('_JEXEC') or die('Restricted access');
if ( ! defined('fancyMenuPatch') )
{
function fancyMenuPatch($result,$tag){
// Replace UL tag with ours.
// Replace LI tag with ours.
// Add to the start of the UL tag.
$begin_ul = "<ul id=\"top-nav\" class=\"flatList\">";
$begin_li = "<li>"; //not sure what to do with this.
// do the replacement
$result = str_replace("<ul>",$begin_ul, $result);
$result = str_replace("<li>", $begin_li, $result);
return $result;
}
define('fancyMenuPatch', true);
}
if ( ! defined('modMainMenuXMLCallbackDefined') )
{
function modMainMenuXMLCallback(&$node, $args)
{
$user = &JFactory::getUser();
$menu = &JSite::getMenu();
$active = $menu->getActive();
$path = isset($active) ? array_reverse($active->tree) : null;
if (($args['end']) && ($node->attributes('level') >= $args['end']))
{
$children = $node->children();
foreach ($node->children() as $child)
{
if ($child->name() == 'ul') {
$node->removeChild($child);
}
}
}
if ($node->name() == 'ul') {
foreach ($node->children() as $child)
{
if ($child->attributes('access') > $user->get('aid', 0)) {
$node->removeChild($child);
}
}
}
if (($node->name() == 'li') && isset($node->ul)) {
$node->addAttribute('class', 'parent');
}
if (isset($path) && (in_array($node->attributes('id'), $path) || in_array($node->attributes('rel'), $path)))
{
if ($node->attributes('class')) {
$node->addAttribute('class', $node->attributes('class').' active');
} else {
$node->addAttribute('class', 'active');
}
}
else
{
if (isset($args['children']) && !$args['children'])
{
$children = $node->children();
foreach ($node->children() as $child)
{
if ($child->name() == 'ul') {
$node->removeChild($child);
}
}
}
}
if (($node->name() == 'li') && ($id = $node->attributes('id'))) {
if ($node->attributes('class')) {
$node->addAttribute('class', $node->attributes('class').' item'.$id);
} else {
$node->addAttribute('class', 'item'.$id);
}
}
if (isset($path) && $node->attributes('id') == $path[0]) {
$node->addAttribute('id', 'current');
} else {
$node->removeAttribute('id');
}
$node->removeAttribute('rel');
$node->removeAttribute('level');
$node->removeAttribute('access');
}
define('modMainMenuXMLCallbackDefined', true);
}
ob_start();
modMainMenuHelper::render($params, 'modMyMainMenuXMLCallback');
$menu_html = ob_get_contents();
ob_end_clean();
if($params->get('menutype')=="primarynav"){
$tag = $params->get('tag_id');
}
//output the menu!
echo fancyMenuPatch($menu_html,$tag);
?>
Thank you.
Ok so here is how you want to do this. Jump out of the default.php script you posted above. As Joomla! uses the core mainmenu module for all menus and trees down from that you will need to edit the helper script. This should stick regardless of any 3rd party menu extension you may be using.
rootdirectory/modules/mod_mainmenu/helper.php
Now jump down to the switch statement at line 358. Specifically we want to edit line 363. It looks like this:
$data = ''.$image.$tmp->name.'';
Now edit it to be this:
$data = '<span class="embed embed-top-nav">'.$image.$tmp->name.'</span>';
there you go, now menus utilized by the Joomla! getMenu class will add this span tag around the links.
Note that you may also want to do this to line 375 for links that will open in a new window et cetra. Also note Louis' funny comment " // hrm...this is a bit dickey".
cheers