new dhtmlmenu RT

Post custom hacks and enhancements for phpwcms here only. Maybe some of these things will be included in official release later.
Post Reply
rtilghman
Posts: 107
Joined: Tue 1. Mar 2005, 17:22

new dhtmlmenu RT

Post by rtilghman »

Okay, so I've been working on a new site for my company using PHPwcms. My PHP skills are rusty at best, but my DHTML and CS skills are pretty sharp. To that end I took the DHTMLMENU2 rt I found, fixed it, and created a kick-butt stylesheet that does almost EVERYTHING in CSS.

No wild scripts, no massive js files. All you have is the list apart style modifier to make it work in IE (about 10 lines of js), everything else is achieved with an intricate style cascade. I should note that this includes having parent elements REMAIN selected when a menu is open in IE... no small matter in CSS for anyone who has actually tackled this.

This is the working RT code. Copy this to a file in "phpwcms_template\inc_script\frontend_render" with a proper name to use it.

Code: Select all

<?php

function build_dhtmlmenu2($start=0, $class='', $activeclass='', $counter=0) {
   $class="class='".$class."'";
   $classactive="class='".$activeclass."'";
   $s = '';
   $g = '';
   foreach($GLOBALS['content']['struct'] as $key => $value) {
     
     if ($start == $GLOBALS['content']['struct'][$key]['acat_struct'] &&
         !$GLOBALS['content']['struct'][$key]['acat_hidden'] && $key)
      {
       $s .= '<li';
         if($key == $GLOBALS['aktion'][0] && $activeclass) $s .= ' '.$classactive;
         $s .= '>';

         if(!$GLOBALS['content']['struct'][$key]["acat_redirect"]) {
            $s .= '<a href="index.php?';
            if($GLOBALS['content']['struct'][$key]['acat_alias']) {
               $s .= $GLOBALS['content']['struct'][$key]['acat_alias'];
            } else {
               $s .= 'id='.$key.',0,0,1,0,0';
            }
            $s .= '">';
         } else {
            $redirect = get_redirect_link($GLOBALS['content']['struct'][$key]["acat_redirect"], ' ', '');
            $s .= '<a href="'.$redirect['link'].'"'.$redirect['target'].'>';
         }

         $s .= html_specialchars($GLOBALS['content']['struct'][$key]['acat_name']);
         $s .= '</a>';

         $s .= build_dhtmlmenu2($key, $class, $activeclass,$counter+1);

         $s .= "</li>\n";
      }
   }

   if($s) {
      $g  = "\n<ul";
      if(!$counter && $class) $g .= ' '.$class;
      $g .= ">\n".$s.'</ul>';
   }
   return $g;
} 

// parse the whole webpage $content["all"] is the fully rendered webpage your site displays
$content["all"] = (myTagParser ($content["all"]));
	
// parse the $string and replace all possible instances of the following {RT}'s
function myTagParser($string) {  
	$search[0] = '/\{DHTMLMENU:(.*?),(.*?),(.*?)\}/e';   
	$replace[0] = 'build_dhtmlmenu2("$1","$2","$3");';
	$string = preg_replace($search, $replace, $string);
	$string = str_replace('\'', '\'',$string);
	$string = str_replace('&quot;', '"',$string);
	return $string;	// spit out the final webpage for display
} 

?>
Next you'll need to add the styles. Copy the following and either insert it into its own stylesheet linked to your templates or into the global one used by phpwcms:

Code: Select all

#primaryNav {
	margin: 0px 0px 0px 0px;
	padding: 0px 0px 0px 0px;
	}

/* here we set the default display for the lists/nested lists */
#primaryNav ul {
	margin: 0px 0px 0px 0px;
	padding: 0px 0px 0px 0px;
	list-style: none;
	display: block;
	width: auto;
	}
	
#primaryNav ul ul {
	display: none;
	position: absolute;
	width: 192px;
	border-bottom: 1px solid #ccc;
	top: 20px;
	left: 0px;
	}

	/* Fix IE. Hide from IE Mac \*/
	* html #primaryNav ul ul { top: 30px; left: 0px; width: 170px;}
	/* End */
	
	
#primaryNav ul ul ul {
	display: none;
	position: absolute;
	left: 190px;
	top: -1px;
	}

	/* Fix IE. Hide from IE Mac \*/
	* html #primaryNav ul ul ul { left: 170px; top: -1px; }
	/* End */

/* here we set the default display for the list items/nested list items */
#primaryNav ul li {
	margin: 0px 0px 0px 0px;
	padding: 4px 0px 4px 0px;
	float: left;
	position: relative;
	font-weight: bold;
	}

#primaryNav ul li li {
	margin: 0px 0px 0px 0px;
	padding: 0px 0px 0px 0px;
	border: 1px solid #ccc;
	border-bottom: 0px;
	float: none;
	display: block;
	font-weight: normal;
	}

/* here we set the default display state for the links */
#primaryNav ul li a {
	padding: 5px 20px 5px 5px;
	display: inline;
	text-decoration: none;
	}
	
#primaryNav ul li li a {
	padding: 5px 10px 5px 10px;
	display: block;
	width: 170px;
	}

	/* Fix IE. Hide from IE Mac \*/
	* html #primaryNav ul li { float: left; height: 1%; }
	* html #primaryNav ul li a { height: 1%; }
	/* End */
	

/* here we set the ACTIVE class for ON menus, first for cascade */
#primaryNav ul.itemOff { color: #FF3300; /*color: #FF3300;*/ }

/* DEFINE DEFAULT LI/A APPEARANCE */
/* here we set the standard LI states - controls bg color */
#primaryNav ul li { background-color: transparent; color: #666666; }
#primaryNav ul li li { background-color: #efefef; color: #777; }
#primaryNav ul li li li { background-color: #ffffff; color: #777; }
#primaryNav ul li li li li { background-color: #f9f9f9; color: #777; }

/* here we set the standard A states - controls text color */
#primaryNav ul li a { color: inherit; }

	/* Fix IE. Hide from IE Mac \*/
	* html #primaryNav ul li a { color: #666666; }
	* html #primaryNav ul li li a { color: #777; }
	/* End */

/* DEFINE DEFAULT LI/A HOVER/ON APPEARANCE */
/* here we set the hover and "in" styles for elements */
	/* L1 on states */ 
#primaryNav li:hover, #primaryNav li.sfhover a { color: #FF3300; }
	/* L1 off states - for children */ 
#primaryNav li:hover li, #primaryNav li.sfhover li a { color: #777; }

	/* L2 on states */
#primaryNav li li:hover, #primaryNav li li.sfhover a { color: #FF3300; }
	/* L2 off states - for children */ 
#primaryNav li li:hover li, #primaryNav li li.sfhover li a { color: #777; }

	/* L3 on states */
#primaryNav li li li:hover, #primaryNav li li li.sfhover a { color: #FF3300; }
	/* L3 off states - for children */ 
#primaryNav li li li:hover li, #primaryNav li li li.sfhover li a { color: #777; }

	/* global states - bg colors */ 
#primaryNav li li:hover, #primaryNav li li.sfhover, #primaryNav li li li:hover, #primaryNav li li li.sfhover {
	background-color: #f9f9f9;
	}

/* DEFINE MENU APPEARANCE BEHAVIORS */
/* here we set the reveal/hide chains for the fly-out */
#primaryNav li:hover ul ul, #primaryNav li:hover ul ul ul {
	display: none;
	}
	
#primaryNav li:hover ul, #primaryNav li li:hover ul, #primaryNav li li li:hover ul {
	display: block;
	}

#primaryNav li.sfhover ul ul, #primaryNav li.sfhover ul ul ul, #primaryNav li li.sfhover ul ul {
	display: none;
	}
	
#primaryNav li.sfhover ul, #primaryNav li.sfhover ul, #primaryNav li li.sfhover ul, #primaryNav li li li.sfhover ul {
	display: block;
	}
Finally you'll need the small js script to swap styles in IE. Very small, but crucial for IE since it doesn't recognize pseudo classes. Just copy this into a js file and link to the template with the menu call.

Code: Select all

/////////////////////////////////////////////////////////////////////////////////////////
// DHTML MENU SWAP FIX
// This script solves the no-psuedo classes for IE problem with the dhtml menu

// Detect IE
var isIE = (navigator.userAgent.toLowerCase().indexOf("msie") > 0) ? true : false;

sfHover = function() {
	if (isIE) {
		var sfEls = document.getElementById("primaryNav").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);
That's it. Hope this helps anyone else who wants a nice, fully-functional DHTML menu for their site.

-rt
feios
Posts: 58
Joined: Sat 23. Jul 2005, 03:56
Location: Greece - Athens
Contact:

Post by feios »

Can we see any demo of this menu???
rtilghman
Posts: 107
Joined: Tue 1. Mar 2005, 17:22

Post by rtilghman »

Well, I can't post a link because its a dev server, its not really in a way I want anyone to go there, etc. However, I can post a picture of what it looks like with the exact code I posted above.

In the following example my mous would be over the third level element that has its text highlighted in red. This menu looks almost IDENTICAL in IE... god that took me forever.

Enjoy.

-rt

Image
cyrano
Posts: 1598
Joined: Sat 31. Jan 2004, 18:33
Location: Stuttgart
Contact:

Post by cyrano »

Nice work, will take a look on it, but what is the exact RT call?

I tried "{DHTMLMENUE} and {DHTMLMENU} but that didn't work.

Any suggestions?
Thank you.
Gruß/ regards cyrano
--------------------------------------------------------
templates -> http://www.128.weitzelmedia.de
planepix -> http://www.planepix.de
XING -> https://www.xing.com/profile/Thomas_Weitzel3
rtilghman
Posts: 107
Joined: Tue 1. Mar 2005, 17:22

Post by rtilghman »

Sorry, the RT tag is the same one used previously for the DHTMLMENU RT. the following is an example:

{DHTMLMENU:Start Level, Inactive Classname, Active Classname}

Example:

{DHTMLMENU:0,itemOff,itemOn}

This would generate a menu that started from the top menu of the site and had "class='itemOn'" set for the LI of the current area. This is kind of superfulous and useless (since you don't need to highlight navigation that is hidden, like a DHTML fly-out menu) but it was part of the script I started with)

What I would like to do is have the ability to have the parent item "active" when a child area is selected... which would make a lot more sense. So, for example, if you had a menu with 5 top links (visible) andthe user was in a page that resides in the pathway of "link 1" link 1 would have the ACTIVE class so you could have it highlighted.

To try and ground this, in the above example I'm within the "Our Company" pathway, and it is highlighted since its open. In a perfect world if I select any child of the "Our Company" pathway Our Company would REMAIN highlighted for the duration. Its not entirely necessary since I have a giant area header below the nav to reinforce location, but its a useful feature to have.

I can probably accomplish this on the client side by writing a script that recirsively searches parent nodes by type and, once it gets to the top, sets the class attribute directly, but it would be a HELL of a lot easier to do it at run time.

I really wish my PHP skills were sharper, but as an IA who just happens to be really technical I don't have time to become a PHP guru to boot.

Best,
Rick
User avatar
sustia
Posts: 651
Joined: Fri 2. Apr 2004, 22:29
Location: Lecce (Italy)
Contact:

Post by sustia »

Hi rtilghman, I like your menu :D

With which version it works?

I've tried with Release: 1.1-RC4, but it seems doesn't work..maybe my version is too old?
Campeones del mundo!
Vegetables!
frold
Posts: 2151
Joined: Tue 25. Nov 2003, 22:42

Post by frold »

sustia wrote:Hi rtilghman, I like your menu :D

With which version it works?

I've tried with Release: 1.1-RC4, but it seems doesn't work..maybe my version is too old?
yep, you need 1.1.9 as a minimum
http://www.studmed.dk Portal for doctors and medical students in Denmark
User avatar
sustia
Posts: 651
Joined: Fri 2. Apr 2004, 22:29
Location: Lecce (Italy)
Contact:

Post by sustia »

Ok, thanks a lot frold :D
Campeones del mundo!
Vegetables!
rtilghman
Posts: 107
Joined: Tue 1. Mar 2005, 17:22

Post by rtilghman »

Why is that? What's the major difference between pre-1.1.9 and post-1.1.9?

What I can say is that if you can generate a UL/LI hierarchy of your site from any point you can use this menu system with it. This is because everything is essentially dictated by CSS, and you can include a separate external style sheet with any template you create using a plain old fixed URL.

To configure the script to work with any list the only trick I can think of is to make sure that you have a uniquely defined container (unique ID) to reference for all the style rules. However, this is easily done by just applying an ID to the TD in which you call the UL in your template.

So, for example, if you use a Table for basic structure in your template just give the TD in which the UL appears the ID "primaryNav". Then link the style sheet to it, link an external JS file with the necesssary code in it, and as long as you can generate the UL inside that TD you're good to go.

FYI, the classes in the actual RT code are more or less superfluous in my application. Since the elements that get highlighted (the active menu item) is hidden I don't even use it... I just used this RT because it seemed to provide people the most flexibility of the options i found.

Hope this helps.

best,
Rick
User avatar
flip-flop
Moderator
Posts: 8178
Joined: Sat 21. May 2005, 21:25
Location: HAMM (Germany)
Contact:

Post by flip-flop »

Works fine under 1.2.3 DEV and 1.2.5 CVS on my dev-system.


Knut
>> HowTo | DOCU | FAQ | TEMPLATES/DOCS << ( SITE )
User avatar
sustia
Posts: 651
Joined: Fri 2. Apr 2004, 22:29
Location: Lecce (Italy)
Contact:

Post by sustia »

Hi, I've done all but it doesn't work for me (I'm using the 1.2.5 DEV on localhost)
All that I can see is this

Image
Campeones del mundo!
Vegetables!
frold
Posts: 2151
Joined: Tue 25. Nov 2003, 22:42

Post by frold »

sustia wrote:Hi, I've done all but it doesn't work for me (I'm using the 1.2.5 DEV on localhost)
All that I can see is this

Image
seems like the css is missing
http://www.studmed.dk Portal for doctors and medical students in Denmark
User avatar
sustia
Posts: 651
Joined: Fri 2. Apr 2004, 22:29
Location: Lecce (Italy)
Contact:

Post by sustia »

frold wrote: seems like the css is missing
I've included the css in the frontend.css by copy/paste from rtilghman's post.

In the head I put

Code: Select all

<script type="text/javascript" src="http://localhost/wcms_1.2.5/phpwcms_template/inc_js/menu.js"></script>
and in the body

Code: Select all

{DHTMLMENU:1,itemOff,itemOn}
:?
Campeones del mundo!
Vegetables!
rtilghman
Posts: 107
Joined: Tue 1. Mar 2005, 17:22

Post by rtilghman »

If the .js script weren't being parsed all that would happen is the menu wouldn't work in IE (it would still work in Firefox). Looking at your script it appears the style classes aren't being applied to your menu.

I would recommend you check to be sure that your inheritance id/class structure mirrors the one in the script. If it doesn't or you left something out the styles won't be applied to the UL of your menu.

For example, all my styles are appended with:

Code: Select all

#primaryNav
This entry before the individual styles rules (it leads all the entries) tells the browser to apply these styles to all elements INSIDE an element with the ID "primaryNav" (# = ID, . = class).

So, your menu has to be called inside or contained by a tag or element with the ID "primaryNav". I would recommend that you label the TD (assuming you use a table for basic structure) with this ID, thus guaranteeing your entire menu is contained in the ID.

So the following would be an example from my templates:

Code: Select all

<td width="10" rowspan="3">{SPACER:10x1}</td>
</tr>
<tr>
<td colspan="2">{SPACER:1x25}</td>
</tr>
<tr valign="top">
<td colspan="2" id="primaryNav">{DHTMLMENU:0,itemOff,itemOn}
</td>
</tr>
<tr>
<td colspan="4">{SPACER:1x5}</td>
</tr>
</table>
<!-- end head.global -->
As you can see, I call the DHTMLMENU rt inside a TD with id primaryNav, and then the style rules get applied properly.

BTW, I'm not anal, I just don't want to answer this question again and figured I would make absolutely, positively sure it was thoroughly addressed. :)

Best,
Rick
User avatar
sustia
Posts: 651
Joined: Fri 2. Apr 2004, 22:29
Location: Lecce (Italy)
Contact:

Post by sustia »

rtilghman wrote: For example, all my styles are appended with:

Code: Select all

#primaryNav
This entry before the individual styles rules (it leads all the entries) tells the browser to apply these styles to all elements INSIDE an element with the ID "primaryNav" (# = ID, . = class).

So, your menu has to be called inside or contained by a tag or element with the ID "primaryNav".
Thanks, the problem was this, now it works correctly :)
Campeones del mundo!
Vegetables!
Post Reply