Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

DHTML Menus and Frames - part 2

Status
Not open for further replies.

Einstein47

Programmer
Joined
Nov 29, 2001
Messages
737
Location
US
Ok, I have been able to accomplish somethings with scripting a menu to cross the Frames limitation. As you can see in my example page:
You will notice that the menu hides nicely when you scroll, or click off of the menu area. However, once you select a menu link, the menus no longer hide. You can click on another button and the menu for that item displays, but I can't get the menus to hide once the first "main content" page is replaced.

Also, just a little quirk in FF, the first menu will display at the far left of the "main content" frame. After that all menus display correctly below their respective buttons.

You might note in this example that only a few of the buttons are active. That is on purpose. My real code has all the correct links to my JSP pages, but for a working example I needed to create dummy HTML pages and I didn't want to waste time doing that when you can see the functionality (or lack thereof) without all the extra busy work.

If you need me to post any code you can't get access to (such as ".js" files). Please ask, and I'll post it here.

Einstein47
For best results: hand wash in cold, tumble dry low.
For not so good results: drag through puddles, pound on rocks, air dry on tree branch.
[[]Starbase47.com]
 
For anyone who cares, I got past my second page errors. I had to re-attach the even listeners on every link processed. The menu object resides in the top frame, but the event at triggered from the main content frame and need to be re-attached all the time.

My next task is creating multi-tier menus. There are several scripts on the internet, but I will need to dissect them to make them work for me.

Once I get a good solution - I'll make sure to write up a FAQ so if anyone else might need multi-layer menu navigation to work with frames, they will have one place to look.

Einstein47
For best results: hand wash in cold, tumble dry low.
For not so good results: drag through puddles, pound on rocks, air dry on tree branch.
[[]Starbase47.com]
 
[blue]WOO HOO - I am so close I can taste it!!![/blue]

Looky here:
Ok, none of the links work on my test site, but the funtionality as far as the sub menus displaying and hiding is working. I am only concerned with IE 6 at this point, because there is a bug in FireFox where the first time you click a menu it doesn't display. I'll work on that later.

One pressing question I have is the displaying of the submenus always on the right. When I am at a button on the far right like "Admin" you can't see all the options. I need to find a way to make the menus spill down to the left when I am too close to the edge. Any advice on this?

Also, all of my menus are the same width. I know that I have hard coded each to be a set size. But, how would I go about resizing the menus so that they aren't always the default set size? If you click on "Victim" you will see what I mean. There is tons more space to the right than is needed. Is it even possible to resize the width after a DIV is displayed?

Einstein47
For best results: hand wash in cold, tumble dry low.
For not so good results: drag through puddles, pound on rocks, air dry on tree branch.
[[]Starbase47.com]
 
Okay people - This is it! Check out the above link and see the power of dynamic menus.

The last things I had to do were deal with the Help menu - it doesn't display off the screen anymore, and the Admin menu where the Roles submenu shows up on the right. Those were tricky.

Here is the main code that controls that:
Code:
<script type="text/javascript">
var menuDiv;
var win;
function setInnerHTML(x,menu) {
    if (menu.length > 0) {
      menuDiv = window.frames["mainFrame"].document.getElementById("menuDiv");
      if (win && menuDiv && menuDiv.style) {
        win.populate(menu);
        win.showPopup(x,0);
      }
      else {
        var newElement = window.frames["mainFrame"].document.createElement("div");
        newElement.setAttribute("name", "menuDiv");
        newElement.setAttribute("id", "menuDiv");
        window.frames["mainFrame"].document.body.appendChild(newElement);
        with (window.frames["mainFrame"].document.getElementById("menuDiv").style) {
            position = "absolute";
            backgroundColor = "transparent";
            color = "MenuText";
            width = "auto";
            margin = "0";
            padding = "0";
            fontFamily = "Arial";
            fontSize = "8pt";
            overflow = "visible";
        }
        if (document.all) {
          with (window.frames["mainFrame"].document.styleSheets[0]) {
            addRule("#menuDiv ul","margin:0;padding:0;list-style-type:none;width:210px;border:2px outset ThreeDFace;background:Menu;");
            addRule("#menuDiv ul li","position: relative;background:Menu;overflow:visible;");
            addRule("#menuDiv ul li ul","position: absolute;width:155px;top:0;visibility:hidden;background:Menu;");
            addRule("#menuDiv ul li a","font-family:Arial;font-size: 8pt;display:block;overflow:auto;padding:1px 5px;color:MenuText;background-color:ThreeDFace;text-decoration:none;");
            addRule("#menuDiv a:hover","color:HighlightText;background-color:Highlight;");
            addRule("#menuDiv hr","padding:0;margin-top:-2px;color:ThreeDDarkShadow;");
            addRule("#menuDiv .subfolderstyle","padding-right:0;background: url(ArrowPopup.gif) no-repeat center right;");
            addRule("* html #menuDiv ul li","float: left; height: 1%;");
            addRule("* html #menuDiv ul li a","height: 1%;");
          }
        }
        else if (document.getElementById) {
            var x = window.frames["mainFrame"].document.styleSheets[0];
            x.insertRule("#menuDiv ul {margin:0;padding:0;list-style-type:none;width:210px;border:2px outset ThreeDFace;background:Menu;}",x.cssRules.length);
            x.insertRule("#menuDiv ul li {position: relative;background:Menu;overflow:visible;}",x.cssRules.length);
            x.insertRule("#menuDiv ul li ul {position: absolute;width:155px;top:0;visibility:hidden;background:Menu;}",x.cssRules.length);
            x.insertRule("#menuDiv ul li a {font-family:Arial;font-size: 8pt;display:block;overflow:auto;padding:1px 6px 1px 3px;color:MenuText;background-color:ThreeDFace;text-decoration:none;}",x.cssRules.length);
            x.insertRule("#menuDiv a:hover {color:HighlightText;background-color:Highlight;}",x.cssRules.length);
            x.insertRule("#menuDiv hr {margin-top:0px;margin-bottom:0px;padding:0px;color:ThreeDDarkShadow;}",x.cssRules.length);
            x.insertRule("#menuDiv .subfolderstyle {padding-right:0;background: url(ArrowPopup.gif) no-repeat center right;}",x.cssRules.length);
        }

        win = new PopupMenu('menuDiv');
        win.autoHide();
        if (!win.listenerAttached) {
            win.listenerAttached = true;
            win.attachListener();
        }
        win.populate(menu);
        win.showPopup(x,0);
        menuDiv = window.frames["mainFrame"].document.getElementById("menuDiv");
      }
      // Run script to convert unordered list to menus
      buildsubmenus();
	// if main menu is too wide and the right edge extends off the screen, move it left
	var clientWidth = parseInt(window.frames["mainFrame"].document.body.clientWidth,10);
	var done = false;
	var elemWidth = parseInt(menuDiv.offsetWidth,10);
	while (((getLeftPos(menuDiv)+elemWidth) > clientWidth) && !done) {
		menuDiv.style.left = (getLeftPos(menuDiv) - 2) + "px";
		elemWidth = parseInt(menuDiv.offsetWidth,10);
	}
    }
}

/* menu click handler to identify popup windows from main content href. */
function goMenu(url) {
    var urlStr = "";
    osList = false;
    if (url.charAt(0) == "p") {
        urlStr = "window.open('"+url.substr(1)
            +"','child','toolbar=no,width=700,height=500,resizable=yes,scrollbars=yes')";
        if (win && win.hidePopup) win.hidePopup();
    }
    else {
        urlStr = "window.frames[\"mainFrame\"].document.location.href='" + url +"';";
        win = null;
        menuDiv = null;
    }
    eval(urlStr);
}

/* This function will shrink the width of the given DIV until it can no longer
   shrink, or until the height gets larger and then it will increase the size
   slightly. */
    function resizeMenu(menuDivObj)
    {
		// When submenus have no spaces, the width can only be reduced so far
		var origHeight = menuDivObj.offsetHeight;
		var prevWidth = 0;
		while (origHeight == menuDivObj.offsetHeight
						&& menuDivObj.offsetWidth != prevWidth) {
			prevWidth = menuDivObj.offsetWidth;
			menuDivObj.style.width = (menuDivObj.offsetWidth-3)+"px";
		}
		menuDivObj.style.width = (menuDivObj.offsetWidth+6)+"px";
    }
    
    function getLeftPos(inputObj)
    {
        var returnValue = inputObj.offsetLeft;
        while((inputObj = inputObj.offsetParent) != null)returnValue += inputObj.offsetLeft;
        return parseInt(returnValue,10);
    }

/*
	SuckerTree Vertical Menu 1.1 (Nov 8th, 06)
	By Dynamic Drive: [URL unfurl="true"]http://www.dynamicdrive.com/style/[/URL]
*/

var menuids=["suckermenu"] //Enter id(s) of SuckerTree UL menus, separated by commas

function buildsubmenus() {
	var menuObj = window.frames["mainFrame"].document.getElementById(menuids[0]);
	resizeMenu(menuObj);
	var clientWidth = parseInt(window.frames["mainFrame"].document.body.clientWidth,10);
	for (var i=0; i<menuids.length; i++) {
		var ultags=window.frames["mainFrame"].document.getElementById(menuids[i]).getElementsByTagName("ul")
	    for (var t=0; t<ultags.length; t++){
	// First thing resize the submenus
			resizeMenu(ultags[t]);
			ultags[t].parentNode.getElementsByTagName("a")[0].className="subfolderstyle"
			//if this is a first level submenu
			if (ultags[t].parentNode.parentNode.id==menuids[i]) {
			//dynamically position first level submenus to the right of main menu item
				ultags[t].style.left=ultags[t].parentNode.offsetWidth+"px" 
			}
			else { //else if this is a sub level submenu (ul)
			//position menu to the right of menu item that activated it
				var myLeft = ultags[t].parentNode.getElementsByTagName("a")[0];
				var leftEdge = parseInt(getLeftPos(myLeft))+parseInt(myLeft.offsetWidth);
				var elemWidth = parseInt(ultags[t].offsetWidth);
				if ((leftEdge+elemWidth) < clientWidth)
					ultags[t].style.left=myLeft.offsetWidth+"px" 
				else {
				// the submenu needs to be placed to the right of the parent UL item
					ultags[t].style.left=(-elemWidth)+"px";
				}
			}
		    ultags[t].parentNode.onmouseover=function(){
		    	this.getElementsByTagName("ul")[0].style.display="block"
				this.style.backgroundColor = "Highlight";
				this.style.color = "HighlightText";
		    }
		    ultags[t].parentNode.onmouseout=function(){
		    	this.getElementsByTagName("ul")[0].style.display="none"
				this.style.backgroundColor = "Menu";
				this.style.color = "MenuText";
		    }
    	}
		for (var t=ultags.length-1; t>-1; t--) { 
			//loop through all sub menus again, and use "display:none" to hide menus 
			//(to prevent possible page scrollbars)
			ultags[t].style.visibility="visible"
			ultags[t].style.display="none"
		}
	}
}

</script>
Sorry for all the tabs - I hope it isn't too hard to read. If you have any questions, feel free to ask. I feel so empowered with this code. I can take on the world - well, maybe not.

Einstein47
For best results: hand wash in cold, tumble dry low.
For not so good results: drag through puddles, pound on rocks, air dry on tree branch.
[&#91;]Starbase47.com]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top