was looking at category nesting a while ago, with something that might be useful for an admin menu too:
http://forum.opencart.com/index.php/top ... tml#msg854
it runs a single query to get the details as JNeuhoff suggested, then works through the result to build an associative array of the menu contents.
the time taken to run the initial query and the subsequent function is negligible - but still, there's room for optimisation in the query (e.g. replacing the joined tables with selects that only include the required columns). if it's any use, i could modify it to look at menu, menu_to_menu (and maybe menu_description - is localisation going to be db or file-based?).
would be great to have a more sensible menu system, js seems over the top/obstructive given the nature of the task.
http://forum.opencart.com/index.php/top ... tml#msg854
it runs a single query to get the details as JNeuhoff suggested, then works through the result to build an associative array of the menu contents.
the time taken to run the initial query and the subsequent function is negligible - but still, there's room for optimisation in the query (e.g. replacing the joined tables with selects that only include the required columns). if it's any use, i could modify it to look at menu, menu_to_menu (and maybe menu_description - is localisation going to be db or file-based?).
would be great to have a more sensible menu system, js seems over the top/obstructive given the nature of the task.
OK, assuming the following DB tables (I think each sub-menu can only have exactly one parent...):
menu:
menu_id menu_parent_id title icon href sort_order
........................
........................
menu_description:
menu_id language_id desc-whatever
............
............
You could use the following PHP code for generating HTML view of nested menus, using only one database query, whose results are stored in a session object (to make it even faster):
The rendering magic of the UL and LI elements has of course to be CSS-driven, you could use the stylesheets from ADX Menu ( http://www.aplus.co.yu/adxmenu/) for this.
menu:
menu_id menu_parent_id title icon href sort_order
........................
........................
menu_description:
menu_id language_id desc-whatever
............
............
You could use the following PHP code for generating HTML view of nested menus, using only one database query, whose results are stored in a session object (to make it even faster):
Code: Select all
<?php
// Viewer support functions for HTML templates
//
// use OpenCart's admin/config.php
//
require_once("config.php");
//
// find the last update date of the menu DB tables
//
function lastMenusUpdate() {
$sql = "SHOW TABLE STATUS FROM ".DB_NAME." LIKE 'menu%';";
$rows = mysql_query($sql) or die('Query failed: ' . mysql_error());
$result = "0000-00-00 00:00:00";
while ($row = mysql_fetch_array($rows, MYSQL_ASSOC)) {
$lastUpdate = $row['Update_time'];
if ($lastUpdate > $result) {
$result = $lastUpdate;
}
}
return $result;
}
//
// get an array of menu items from a database query and/or session object
//
function getMenus( $languageId ) {
if ( (!isset($_SESSION['menus'])) ||
(!isset($_SESSION['menus_date'])) ||
($_SESSION['menus_date'] < lastMenusUpdate())
) {
$menus = array();
$sql = "SELECT m.menu_id, m.parent_menu_id, m.title, m.icon, m.href, m.sort_order, md.* ";
$sql .= "FROM `menu` m ";
$sql .= "INNER JOIN menu_description md ON md.menu_id = m.menu_id ";
$sql .= "AND md.language_id =$languageId ";
$sql .= "ORDER BY m.parent_menu_id, m.sort_order, m.menu_id;";
$result = mysql_query($sql) or die('Query failed: ' . mysql_error());
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$menus[] = $row;
}
$_SESSION['menus'] = &$menus;
$_SESSION['menus_date'] = date( "Y-m-d H:i:s" );
mysql_free_result($result);
}
return $_SESSION['menus'];
}
//
// generate an HTML view of (possibly nested) menus, using UL and LI HTML-elements
//
function generateMenusView( &$menus, $id, $level, $noRaquo=FALSE ) {
$listItems = "";
$style = "";
$width = 0;
$j = count( $menus );
for ($i=0; $i<$j; $i++) {
$menu = $menus[$i];
if ($menu['parent_menu_id'] != $id) {
continue;
}
$title = $category['title'];
$href = HTTP_SERVER."index.php?".htmlentities(urlencode($menu['href']));
$subList = generateMenusView( $menus, $menu['menu_id'], $level+2, $noRaquo );
$indent = str_repeat( " ", $level+1 );
$listItems .= ($i != 0) ? $indent : "";
$listItems .= "<li><a href=\"$href\">";
if (strlen($subList)>0) {
if ($id==0) {
$listItems .= htmlentities($title);
$listItems .= ($noRaquo) ? "" : " »";
}
else {
$listItems .= ($noRaquo) ? "" : " <span style=\"float:right;\">»</span>";
$listItems .= htmlentities($title);
}
}
else {
$listItems .= htmlentities($title);
}
$listItems .= "</a>";
$width = max( $width, strlen($title) );
$listItems .= ($subList != "") ? "\n".$subList : "";
$listItems .= ($subList != "") ? $indent : "";
$listItems .= "</li>\n";
}
$result = "";
if (strlen($listItems) > 0) {
if ($id>0) {
$width = round($width * 12.5) + (($width <= 10) ? 12.5*2 : 0);
$indent = str_repeat( " ", $level );
$result = $indent;
$result .= "<ul style=\"width:$width"."px;\">\n".$listItems;
$result .= $indent;
$result .= "</ul>\n";
}
else {
$result = $listItems;
}
}
return $result;
}
?>
Last edited by JNeuhoff on Tue Aug 19, 2008 7:50 pm, edited 1 time in total.
Export/Import Tool * SpamBot Buster * Unused Images Manager * Instant Option Price Calculator * Number Option * Google Tag Manager * Survey Plus * OpenTwig
You mean the tables are no good for multilevel nested?JNeuhoff wrote: OK, assuming the following DB tables (I think each sub-menu can only have exactly one parent...):
LOL you really like that adxmenu eh? The css is easy once we get the table out into an unordered list.JNeuhoff wrote: The rendering magic of the UL and LI elements has of course to be CSS-driven, you could use the stylesheets from ADX Menu ( http://www.aplus.co.yu/adxmenu/) for this.
Last edited by Qphoria on Tue Aug 19, 2008 9:18 pm, edited 1 time in total.
While it isn't what we want just yet (as it uses multiple queries), I have a 10-line method working:
[php]
function index() {
.......
$this->listMenu(0);
.......
}
function listMenu ($parent, $level=0) {
$database =& $this->locator->get('database');
$sql = "SELECT menu_id, title, icon, href
FROM ad_menu
WHERE parent_id = " . $parent . " order by sort_order";
$res = $database->query($sql);
while (list ($title, $id) = mysql_fetch_row($res)) {
$indent = str_repeat('---', $level);
echo "$indent $title";
$this->listMenu ($id, $level+1);
}
}
[/php]
Using 1 table (image attached)
I've checked a few other carts and a multi-query method is actually what they use for store front categories. I think for a storefront, the less db queries the better. For the backend, its not really that important. But I think we should keep working towards that goal. At least we have a possible backup plan with this. It even supports proper sort order per menu, per level
[php]
function index() {
.......
$this->listMenu(0);
.......
}
function listMenu ($parent, $level=0) {
$database =& $this->locator->get('database');
$sql = "SELECT menu_id, title, icon, href
FROM ad_menu
WHERE parent_id = " . $parent . " order by sort_order";
$res = $database->query($sql);
while (list ($title, $id) = mysql_fetch_row($res)) {
$indent = str_repeat('---', $level);
echo "$indent $title";
$this->listMenu ($id, $level+1);
}
}
[/php]
Using 1 table (image attached)
I've checked a few other carts and a multi-query method is actually what they use for store front categories. I think for a storefront, the less db queries the better. For the backend, its not really that important. But I think we should keep working towards that goal. At least we have a possible backup plan with this. It even supports proper sort order per menu, per level
Last edited by Qphoria on Wed Aug 20, 2008 2:50 am, edited 1 time in total.
Well, I was thinking that the menus are strictly in a hierarchy, with no limit to the number of nested levels. No sub-menu can have more than one parent, it really is a sort ofYou mean the tables are no good for multilevel nested?
menu ---- many-to-one ----menu
hence we don't need the 'menu_to_menu' table. All we need is a foreign key in the menu table itself: 'parent_menu_id' in this case.
Last edited by JNeuhoff on Tue Aug 19, 2008 10:52 pm, edited 1 time in total.
Export/Import Tool * SpamBot Buster * Unused Images Manager * Instant Option Price Calculator * Number Option * Google Tag Manager * Survey Plus * OpenTwig
Ahh.. good news! I managed to modify ogun's code to work with the admin menu!
It currently makes a proper tree for all levels, but only makes 2 levels. I'm sure that can be modified pretty easily. It even appears to respect sort_order.
From what I could tell, there was a problem that I ran into with returning the output variable from the recursive tree listing. I am not a complete pro with recursive loops yet so for now I just made the output a global variable so I didn't have to worry about returning anything and losing what was already there, this may have been a problem for you too when you first made this.
I actually like this setup too because it is all combined into one file instead of using external libraries. Only 2 small functions.
It also doesn't rely on a "path" which makes it ideal for the Admin menu as well as being more versatile on the categories side
Nice work ogun!
I will work on getting multiple levels going and style up a demo.
Stay tuned.
It currently makes a proper tree for all levels, but only makes 2 levels. I'm sure that can be modified pretty easily. It even appears to respect sort_order.
From what I could tell, there was a problem that I ran into with returning the output variable from the recursive tree listing. I am not a complete pro with recursive loops yet so for now I just made the output a global variable so I didn't have to worry about returning anything and losing what was already there, this may have been a problem for you too when you first made this.
I actually like this setup too because it is all combined into one file instead of using external libraries. Only 2 small functions.
It also doesn't rely on a "path" which makes it ideal for the Admin menu as well as being more versatile on the categories side
Nice work ogun!
I will work on getting multiple levels going and style up a demo.
Stay tuned.
Last edited by Qphoria on Wed Aug 20, 2008 4:25 am, edited 1 time in total.
Ahoy! We are soooo close! My eyes are crossing looking at the css. I got the listing working perfect and the css works for the first 2 levels, but shows ALL 3rd levels at the same time. Need to figure out how to hide the 3rd levels until hovering their parent. I think it's like some one-liner that I'm overlooking.
Maybe you guys can take a look:
DEMO (user:demo / pass:demo) - Put your mouse over "Admin->Configuration". Notice all menus after that popout, especially the User sub and the Localisation sub overlapping. Need to hide them until you mouse over the parent menu.
If you got FF Web developer then take a crack at EditCSS (menu.css), otherwise to just look at the css here
The menu structure is a simple UL based menu, each sub goes down by one ul:
Maybe you guys can take a look:
DEMO (user:demo / pass:demo) - Put your mouse over "Admin->Configuration". Notice all menus after that popout, especially the User sub and the Localisation sub overlapping. Need to hide them until you mouse over the parent menu.
If you got FF Web developer then take a crack at EditCSS (menu.css), otherwise to just look at the css here
The menu structure is a simple UL based menu, each sub goes down by one ul:
Code: Select all
<div class="adminMenu">
<ul>
<li>Admin
<ul>
<li>Home</li>
<li>Catalog</li>
<li>Configuration
<ul>
<li>Setting</li>
....
....
....
</ul>
</li>
</ul>
</li>
</ul>
</div>
Last edited by Qphoria on Wed Aug 20, 2008 9:44 pm, edited 1 time in total.
that's looking great 
if you don't mind waiting until tomorrow evening i can have a go at the css then. got a vertical cascading menu that i should be able to convert to horizontal easily enough. iirc there's also a bit of js that needs to go into the page header to make the menu behave in the same way between different versions of ie and firefox.

if you don't mind waiting until tomorrow evening i can have a go at the css then. got a vertical cascading menu that i should be able to convert to horizontal easily enough. iirc there's also a bit of js that needs to go into the page header to make the menu behave in the same way between different versions of ie and firefox.
Oh noes! not js! I assume you mean the csshover.htc bit. Cursed IE6ogun wrote: that's looking great
if you don't mind waiting until tomorrow evening i can have a go at the css then. got a vertical cascading menu that i should be able to convert to horizontal easily enough. iirc there's also a bit of js that needs to go into the page header to make the menu behave in the same way between different versions of ie and firefox.
Indeed!Cursed IE6
As you know, I always use the ADX Menu (CSS styles for nested unordered lists), and in all web browsers its CSS-only rendering, but IE6 always requires some terrible Javascript-based workarounds.
Export/Import Tool * SpamBot Buster * Unused Images Manager * Instant Option Price Calculator * Number Option * Google Tag Manager * Survey Plus * OpenTwig
It is a good start and from my limited testing...
Firefox = behaves nicely in firefox 2.0.0.16
IE6 = menu bar but no menus (yes this browser is a travesty but still in common use)
IE7 = not tested
Safari = menus disappear unexpectedly with fast mouse movement
Opera = behaves nicely in Opera 9.51
However, in all browsers, the menus disappear instantly when the mouse moves out of the menu area. They should really persist for a little while to allow for slight user inaccuracy with the mouse.
Before you spend too much more time trying to get a "pure" css menu, have a look at http://apptools.com/rants/jsmenu.php for an interesting discussion and some techniqes for what you are trying to do.
cheers
Bruce
Firefox = behaves nicely in firefox 2.0.0.16
IE6 = menu bar but no menus (yes this browser is a travesty but still in common use)
IE7 = not tested
Safari = menus disappear unexpectedly with fast mouse movement
Opera = behaves nicely in Opera 9.51
However, in all browsers, the menus disappear instantly when the mouse moves out of the menu area. They should really persist for a little while to allow for slight user inaccuracy with the mouse.
Before you spend too much more time trying to get a "pure" css menu, have a look at http://apptools.com/rants/jsmenu.php for an interesting discussion and some techniqes for what you are trying to do.
cheers
Bruce
IE7 works perfect.bruce wrote:
IE6 = menu bar but no menus (yes this browser is a travesty but still in common use)
IE7 = not tested
FF3.x works perfect.
I know, I still need to add the csshover.htc for IE6, as well as some IE fixes.
There's actually another "hack" i saw for IE6 and other compatibility issue that doesn't seem to require the js for ie6. Take a look at the source of this demo. This is claimed to be the definitive perfect css only menu with full support across all browsers without js. It uses conditional IE6 statements to add "extras" when using IE6. I haven't added those conditional statements to this menu tho.
Well yea, that's of course the single downside of having no javascript.bruce wrote: However, in all browsers, the menus disappear instantly when the mouse moves out of the menu area. They should really persist for a little while to allow for slight user inaccuracy with the mouse.
I'm not against a little bit of javascript for making it a bit more "robust". I was just against the existing way of putting the entire menu into a javascript script file. For delay we can add a simple onHover script to the links and put a 3 line timer function while keeping the menu completely designed by css and stored in the database.bruce wrote: Before you spend too much more time trying to get a "pure" css menu, have a look at http://apptools.com/rants/jsmenu.php for an interesting discussion and some techniqes for what you are trying to do.
Last edited by Qphoria on Fri Aug 22, 2008 8:06 am, edited 1 time in total.
that's looking great Qphoria, nice work!
would be tempted to go for a straightforward ie conditional statement in the header around the csshover fix rather than taking the cssplay route. there are still people out there with ancient browsers, but they probably don't have any money so an online shop doesn't need to worry about them too much
for the disappearing menus on mouseout, an invisible area around the menus (e.g. some padding in the containing ULs) would cover most user inaccuracies with the mouse.
would it be worth waiting for this:
would be tempted to go for a straightforward ie conditional statement in the header around the csshover fix rather than taking the cssplay route. there are still people out there with ancient browsers, but they probably don't have any money so an online shop doesn't need to worry about them too much

for the disappearing menus on mouseout, an invisible area around the menus (e.g. some padding in the containing ULs) would cover most user inaccuracies with the mouse.
would it be worth waiting for this:
..before going much further? maybe Daniel's already removed the js/changed how the menu works.Daniel wrote: You can expect a demo of the new admin section soon.
Who is online
Users browsing this forum: No registered users and 2 guests