PDA

View Full Version : Pop-It Menu Submenu Capability



warrenta
02-01-2009, 04:11 AM
1) Script Title: Pop-It Menu

2) Script URL (on DD): http://www.dynamicdrive.com/dynamicindex1/popit.htm

3) Describe problem: I have been using this script with success for some time so I really don't want to have to change my entire website and all it's web pages to go to another menu system. Over time my single vertical list menu has grown too long to be used on a single web page. Some of my menu choices can be grouped together as categories. This led me to try to implement a submenu capability. I modified some of my linkset contents to specify a second level submenu capability by simply calling showmenu() again to access a different linkset variable...ie linkset[0] contains the main menu links while linkset[1] contains the submenu links for the first main menu shoice. This looks like:

var linkset=new Array()
//SPECIFY MENU SETS AND THEIR LINKS. FOLLOW SYNTAX LAID OUT

linkset[0]='--CHOOSE ONE--'
linkset[0]+='<hr>' //Optional Separator
linkset[0]+='<a style="text-decoration: none" href="#" onClick="showmenu(event,linkset[1],'130px')" onMouseout="delayhidemenu()">Player Skills</a>'
linkset[0]+='<a target="_blank" style=" text-decoration: none" href="../rhcstdforms/stdformsframe.htm?stdteamroster.htm">Team Roster</a>'
linkset[0]+='<a target="_blank" style=" text-decoration: none" href="../rhcstdforms/stdformsframe.htm?stdteamnote1.htm">Team Note 1</a>'

linkset[1]='--CHOOSE SKILLS--'
linkset[1]+='<hr>' //Optional Separator
linkset[1]+='<a target="_blank" style=" text-decoration: none" href="../rhcstdforms/stdformsframe.htm?stdplayereval1.htm">Skating</a>'
linkset[1]+='<a target="_blank" style=" text-decoration: none" href="../rhcstdforms/stdformsframe.htm?stdplayereval2.htm">Puckhandling</a>'
linkset[1]+='<a target="_blank" style=" text-decoration: none" href="../rhcstdforms/stdformsframe.htm?stdplayereval3.htm">Shooting/Scoring</a>'

////No need to edit beyond here

Linkset[0] is the main menu that contains the Player Skills category entry which calls showmenu() again to display the linkset[1] sumenu links to Skating, Puckhandling, Shooting/Scoring web pages.

This works fine on IE7 but fails without any error message on Firefox and Chrome. The submenu in linkset[1] just will not display in these browsers. Can anyone help me to get this to work?

ddadmin
02-02-2009, 02:49 AM
Try adding a backslash (\) before the semicolons in your code below:


linkset[0]+='<a style="text-decoration: none" href="#" onClick="showmenu(event,linkset[1], \'130px\')" onMouseout="delayhidemenu()">Player Skills</a>'

Having said that, this script really wasn't designed to work with nested levels, so the behavior of the sub menus won't exactly be perfect even if you got it working. I have plans to update Pop-it menu eventually to support nested levels.

warrenta
02-02-2009, 05:56 AM
Thanks for the response. Unfortunately it didn't change anything...it still works in IE but not in Chrome or Firefox. This script is essential to me. I update the linkset menu contents dynamically on each web page with a server side perl script and a JITc javascript routine. How soon will you get around to updating this script to provide true submenu capability? How about some scrollbars on the menu list so that the user can access a long menu list until then? Or even allowing multiple links horizontally on each menu option? I am going to have to scrap this menu system soon if I don't get any help....

ddadmin
02-02-2009, 06:10 AM
With the changes the script does work for me in both FF 3.x and Chrome. Using the default demo code, here is the modified version:


<style type="text/css">

#popitmenu{
position: absolute;
background-color: white;
border:1px solid black;
font: normal 12px Verdana;
line-height: 18px;
z-index: 100;
visibility: hidden;
}

#popitmenu a{
text-decoration: none;
padding-left: 6px;
color: black;
display: block;
}

#popitmenu a:hover{ /*hover background color*/
background-color: #CCFF9D;
}

</style>

<script type="text/javascript">

/***********************************************
* Pop-it menu- Dynamic Drive (www.dynamicdrive.com)
* This notice MUST stay intact for legal use
* Visit http://www.dynamicdrive.com/ for full source code
***********************************************/

var defaultMenuWidth="150px" //set default menu width.

var linkset=new Array()
//SPECIFY MENU SETS AND THEIR LINKS. FOLLOW SYNTAX LAID OUT

linkset[0]='<a href="http://dynamicdrive.com">Dynamic Drive</a>'
linkset[0]+='<a href="http://www.javascriptkit.com">JavaScript Kit</a>'
linkset[0]+='<a href="http://www.codingforums.com" onMouseover="showmenu(event,linkset[0], \'180px\')" onMouseout="delayhidemenu()" style="position:relative">Coding Forums</a>'
linkset[0]+='<a href="http://www.cssdrive.com">CSS Drive</a>'
linkset[0]+='<a href="http://freewarejava.com">Freewarejava</a>'

linkset[1]='<a href="http://msnbc.com">MSNBC</a>'
linkset[1]+='<a href="http://cnn.com">CNN</a>'
linkset[1]+='<a href="http://news.bbc.co.uk">BBC News</a>'
linkset[1]+='<a href="http://www.washingtonpost.com">Washington Post</a>'

////No need to edit beyond here

var ie5=document.all && !window.opera
var ns6=document.getElementById

if (ie5||ns6)
document.write('<div id="popitmenu" onMouseover="clearhidemenu();" onMouseout="dynamichide(event)"></div>')

function iecompattest(){
return (document.compatMode && document.compatMode.indexOf("CSS")!=-1)? document.documentElement : document.body
}

function showmenu(e, which, optWidth){
if (!document.all&&!document.getElementById)
return
clearhidemenu()
menuobj=ie5? document.all.popitmenu : document.getElementById("popitmenu")
menuobj.innerHTML=which
menuobj.style.width=(typeof optWidth!="undefined")? optWidth : defaultMenuWidth
menuobj.contentwidth=menuobj.offsetWidth
menuobj.contentheight=menuobj.offsetHeight
eventX=ie5? event.clientX : e.clientX
eventY=ie5? event.clientY : e.clientY
//Find out how close the mouse is to the corner of the window
var rightedge=ie5? iecompattest().clientWidth-eventX : window.innerWidth-eventX
var bottomedge=ie5? iecompattest().clientHeight-eventY : window.innerHeight-eventY
//if the horizontal distance isn't enough to accomodate the width of the context menu
if (rightedge<menuobj.contentwidth)
//move the horizontal position of the menu to the left by it's width
menuobj.style.left=ie5? iecompattest().scrollLeft+eventX-menuobj.contentwidth+"px" : window.pageXOffset+eventX-menuobj.contentwidth+"px"
else
//position the horizontal position of the menu where the mouse was clicked
menuobj.style.left=ie5? iecompattest().scrollLeft+eventX+"px" : window.pageXOffset+eventX+"px"
//same concept with the vertical position
if (bottomedge<menuobj.contentheight)
menuobj.style.top=ie5? iecompattest().scrollTop+eventY-menuobj.contentheight+"px" : window.pageYOffset+eventY-menuobj.contentheight+"px"
else
menuobj.style.top=ie5? iecompattest().scrollTop+event.clientY+"px" : window.pageYOffset+eventY+"px"
menuobj.style.visibility="visible"
return false
}

function contains_ns6(a, b) {
//Determines if 1 element in contained in another- by Brainjar.com
while (b.parentNode)
if ((b = b.parentNode) == a)
return true;
return false;
}

function hidemenu(){
if (window.menuobj)
menuobj.style.visibility="hidden"
}

function dynamichide(e){
if (ie5&&!menuobj.contains(e.toElement))
hidemenu()
else if (ns6&&e.currentTarget!= e.relatedTarget&& !contains_ns6(e.currentTarget, e.relatedTarget))
hidemenu()
}

function delayhidemenu(){
delayhide=setTimeout("hidemenu()",500)
}

function clearhidemenu(){
if (window.delayhide)
clearTimeout(delayhide)
}

if (ie5||ns6)
document.onclick=hidemenu

</script>

<body>

<a href="#" onMouseover="showmenu(event,linkset[0])" onMouseout="delayhidemenu()">Webmaster Links</a><br>
<a href="#" onMouseover="showmenu(event,linkset[1], '180px')" onMouseout="delayhidemenu()">News sites</a>


How about some scrollbars on the menu list so that the user can access a long menu list until then?

That's pretty simple to do actually. Just modify the CSS for the drop down menu so it contains an explicit height plus an overflow property:


#popitmenu{
position: absolute;
background-color: white;
border:1px solid black;
font: normal 12px Verdana;
line-height: 18px;
z-index: 100;
visibility: hidden;
height: 200px;
overflow-y: scroll;
}

warrenta
02-03-2009, 01:34 AM
The code you supplied adds the excape character to the submenu entry and as you said it works fine in my tests as well in FF and Chrome as well as IE. Unfortunately you used a onMouseover command in the linkset[0] main submenu entry....so multiple uses now become impossible...there is no way to get your mouse to go over another such submenu choice. My original solution in my code above was to use an onClick command so that you could bypass one or more submenu choices in the list to get to the one you wanted. This is consistent with the way the menu works for all other entries...you have to click on an entry to make it work. When I do this any submenu choice no longer works in FF or Chrome but for some reason is still functioning in IE. So it is the onClick command in a submenu entry that is problematic. Can you take another look at this please?

ddadmin
02-03-2009, 08:30 AM
You can change it so the sub menu is revealed onClick. The trick is to also disable the sub menus from hiding when a link inside them is clicked on. Here would be the result:


<style type="text/css">

#popitmenu{
position: absolute;
background-color: white;
border:1px solid black;
font: normal 12px Verdana;
line-height: 18px;
z-index: 100;
visibility: hidden;
}

#popitmenu a{
text-decoration: none;
padding-left: 6px;
color: black;
display: block;
}

#popitmenu a:hover{ /*hover background color*/
background-color: #CCFF9D;
}

</style>

<script type="text/javascript">

/***********************************************
* Pop-it menu- Dynamic Drive (www.dynamicdrive.com)
* This notice MUST stay intact for legal use
* Visit http://www.dynamicdrive.com/ for full source code
***********************************************/

var defaultMenuWidth="150px" //set default menu width.

var linkset=new Array()
//SPECIFY MENU SETS AND THEIR LINKS. FOLLOW SYNTAX LAID OUT

linkset[0]='<a href="http://dynamicdrive.com">Dynamic Drive</a>'
linkset[0]+='<a href="http://www.javascriptkit.com">JavaScript Kit</a>'
linkset[0]+='<a href="http://www.codingforums.com" onClick="showmenu(event,linkset[0], \'180px\'); return false" style="position:relative">Coding Forums</a>'
linkset[0]+='<a href="http://www.cssdrive.com">CSS Drive</a>'
linkset[0]+='<a href="http://freewarejava.com">Freewarejava</a>'

linkset[1]='<a href="http://msnbc.com">MSNBC</a>'
linkset[1]+='<a href="http://cnn.com">CNN</a>'
linkset[1]+='<a href="http://news.bbc.co.uk">BBC News</a>'
linkset[1]+='<a href="http://www.washingtonpost.com">Washington Post</a>'

////No need to edit beyond here

var ie5=document.all && !window.opera
var ns6=document.getElementById

if (ie5||ns6)
document.write('<div id="popitmenu" onMouseover="clearhidemenu();" onMouseout="dynamichide(event)"></div>')

function iecompattest(){
return (document.compatMode && document.compatMode.indexOf("CSS")!=-1)? document.documentElement : document.body
}

function showmenu(e, which, optWidth){
if (!document.all&&!document.getElementById)
return
clearhidemenu()
menuobj=ie5? document.all.popitmenu : document.getElementById("popitmenu")
menuobj.innerHTML=which
menuobj.style.width=(typeof optWidth!="undefined")? optWidth : defaultMenuWidth
menuobj.contentwidth=menuobj.offsetWidth
menuobj.contentheight=menuobj.offsetHeight
eventX=ie5? event.clientX : e.clientX
eventY=ie5? event.clientY : e.clientY
//Find out how close the mouse is to the corner of the window
var rightedge=ie5? iecompattest().clientWidth-eventX : window.innerWidth-eventX
var bottomedge=ie5? iecompattest().clientHeight-eventY : window.innerHeight-eventY
//if the horizontal distance isn't enough to accomodate the width of the context menu
if (rightedge<menuobj.contentwidth)
//move the horizontal position of the menu to the left by it's width
menuobj.style.left=ie5? iecompattest().scrollLeft+eventX-menuobj.contentwidth+"px" : window.pageXOffset+eventX-menuobj.contentwidth+"px"
else
//position the horizontal position of the menu where the mouse was clicked
menuobj.style.left=ie5? iecompattest().scrollLeft+eventX+"px" : window.pageXOffset+eventX+"px"
//same concept with the vertical position
if (bottomedge<menuobj.contentheight)
menuobj.style.top=ie5? iecompattest().scrollTop+eventY-menuobj.contentheight+"px" : window.pageYOffset+eventY-menuobj.contentheight+"px"
else
menuobj.style.top=ie5? iecompattest().scrollTop+event.clientY+"px" : window.pageYOffset+eventY+"px"
menuobj.style.visibility="visible"
return false
}

function contains_ns6(a, b) {
//Determines if 1 element in contained in another- by Brainjar.com
while (b.parentNode)
if ((b = b.parentNode) == a)
return true;
return false;
}

function hidemenu(){
if (window.menuobj)
menuobj.style.visibility="hidden"
}

function dynamichide(e){
if (ie5&&!menuobj.contains(e.toElement))
hidemenu()
else if (ns6&&e.currentTarget!= e.relatedTarget&& !contains_ns6(e.currentTarget, e.relatedTarget))
hidemenu()
}

function delayhidemenu(){
delayhide=setTimeout("hidemenu()",500)
}

function clearhidemenu(){
if (window.delayhide)
clearTimeout(delayhide)
}

//if (ie5||ns6)
//document.onclick=hidemenu

</script>

<body>

<a href="#" onMouseover="showmenu(event,linkset[0])" onMouseout="delayhidemenu()">Webmaster Links</a><br>
<a href="#" onMouseover="showmenu(event,linkset[1], '180px')" onMouseout="delayhidemenu()">News sites</a>

warrenta
02-04-2009, 01:07 AM
Thank you so much. This script now works fine in all browsers and it now provides a simple submenu capability. I added some code to center the text in each menu choice. I also added some code to align both the middle of the main menu and the submenus in the same place so that they overlap each other. Here is my final code:


<style type="text/css">

#popitmenu{
position: absolute;
background-color: white;
border:1px solid black;
font: normal 12px Verdana;
line-height: 18px;
z-index: 100;
visibility: hidden;
}

#popitmenu a{
text-decoration: none;
text-align: center;
padding-left: 6px;
color: black;
display: block;
}

#popitmenu a:hover{ /*hover background color*/
background-color: #CCFF9D;
}

</style>

<script type="text/javascript">

/***********************************************
* Pop-it menu- Dynamic Drive (www.dynamicdrive.com)
* This notice MUST stay intact for legal use
* Visit http://www.dynamicdrive.com/ for full source code
***********************************************/

var defaultMenuWidth="150px" //set default menu width.

var linkset=new Array()
//SPECIFY MENU SETS AND THEIR LINKS. FOLLOW SYNTAX LAID OUT

linkset[0]='<a href="http://dynamicdrive.com">Dynamic Drive</a>'
linkset[0]+='<a href="http://www.javascriptkit.com">JavaScript Kit</a>'
linkset[0]+='<a href="#" onClick="showmenu(event,linkset[2], \'180px\', \'sub\'); return false" style="position:relative">Coding Forums</a>'
linkset[0]+='<a href="#" onClick="showmenu(event,linkset[3], \'180px\', \'sub\'); return false" style="position:relative">CSS Drive</a>'
linkset[0]+='<a href="http://freewarejava.com">Freewarejava</a>'

linkset[1]='<a href="http://msnbc.com">MSNBC</a>'
linkset[1]+='<a href="http://cnn.com">CNN</a>'
linkset[1]+='<a href="http://news.bbc.co.uk">BBC News</a>'
linkset[1]+='<a href="http://www.washingtonpost.com">Washington Post</a>'

linkset[2]='<a href="http://msnbc.com">FORUM #1</a>'
linkset[2]+='<a href="http://cnn.com">FORUM #2</a>'
linkset[2]+='<a href="http://news.bbc.co.uk">FORUM #3</a>'
linkset[2]+='<a href="http://www.washingtonpost.com">FORUM #4</a>'

linkset[3]='<a href="http://www.cssdrive.com">CSS DRIVE #1</a>'
linkset[3]+='<a href="http://www.cssdrive.com">CSS DRIVE #2</a>'
linkset[3]+='<a href="http://www.cssdrive.com">CSS DRIVE #3</a>'
linkset[3]+='<a href="http://www.cssdrive.com">CSS DRIVE #4</a>'


////No need to edit beyond here

var ie5=document.all && !window.opera
var ns6=document.getElementById

if (ie5||ns6)
document.write('<div id="popitmenu" onMouseover="clearhidemenu();" onMouseout="dynamichide(event)"></div>')

function iecompattest(){
return (document.compatMode && document.compatMode.indexOf("CSS")!=-1)? document.documentElement : document.body
}

function showmenu(e, which, optWidth, subMenu){
if (!document.all&&!document.getElementById)
return
clearhidemenu()
menuobj=ie5? document.all.popitmenu : document.getElementById("popitmenu")
menuobj.innerHTML=which
menuobj.style.width=(typeof optWidth!="undefined")? optWidth : defaultMenuWidth
menuobj.contentwidth=menuobj.offsetWidth
menuobjwidthmiddle=menuobj.contentwidth / 2
menuobj.contentheight=menuobj.offsetHeight
eventX=ie5? event.clientX : e.clientX
eventY=ie5? event.clientY : e.clientY
// if this is a submenu request use previous menu horizontal and vertical positions
if(subMenu=="sub"){
menuobj.style.left=saveleft-menuobjwidthmiddle+"px"
menuobj.style.top=savetop+"px"
}
else
{
//Find out how close the mouse is to the corner of the window
var rightedge=ie5? iecompattest().clientWidth-eventX : window.innerWidth-eventX
var bottomedge=ie5? iecompattest().clientHeight-eventY : window.innerHeight-eventY
//if the horizontal distance isn't enough to accomodate the width of the menu
if (rightedge<menuobj.contentwidth){
//move the horizontal position of the menu to the left by it's width
menuobj.style.left=ie5? iecompattest().scrollLeft+eventX-menuobj.contentwidth+"px" : window.pageXOffset+eventX-menuobj.contentwidth+"px"
//save the desired horizontal position for the submenu coming next
saveleft=ie5? iecompattest().scrollLeft+eventX : window.pageXOffset+eventX
}else{
//position the horizontal position of the middle of the menu where the mouse was clicked
menuobj.style.left=ie5? iecompattest().scrollLeft+eventX-menuobjwidthmiddle+"px" : window.pageXOffset+eventX-menuobjwidthmiddle+"px"
//save the desired horizontal position for the submenu coming next
saveleft=ie5? iecompattest().scrollLeft+eventX : window.pageXOffset+eventX
}
//if the vertical distance isn't enough to accomodate the height of the menu
if (bottomedge<menuobj.contentheight){
//move the vertical position of the menu to the top by it's height
menuobj.style.top=ie5? iecompattest().scrollTop+eventY-menuobj.contentheight+"px" : window.pageYOffset+eventY-menuobj.contentheight+"px"
//save the desired vertical position for the submenu coming next
savetop=ie5? iecompattest().scrollTop+eventY-menuobj.contentheight+"px" : window.pageYOffset+eventY-menuobj.contentheight+"px"
}else{
//move the vertical position of the menu to where the mouse was clicked
menuobj.style.top=ie5? iecompattest().scrollTop+event.clientY+"px" : window.pageYOffset+eventY+"px"
//save the desired vertical position for the submenu coming next
savetop=ie5? iecompattest().scrollTop+event.clientY : window.pageYOffset+eventY
}
}
menuobj.style.visibility="visible"
return false
}

function contains_ns6(a, b) {
//Determines if 1 element in contained in another- by Brainjar.com
while (b.parentNode)
if ((b = b.parentNode) == a)
return true;
return false;
}

function hidemenu(){
if (window.menuobj)
menuobj.style.visibility="hidden"
}

function dynamichide(e){
if (ie5&&!menuobj.contains(e.toElement))
hidemenu()
else if (ns6&&e.currentTarget!= e.relatedTarget&& !contains_ns6(e.currentTarget, e.relatedTarget))
hidemenu()
}

function delayhidemenu(){
delayhide=setTimeout("hidemenu()",500)
}

function clearhidemenu(){
if (window.delayhide)
clearTimeout(delayhide)
}

//if (ie5||ns6)
//document.onclick=hidemenu

</script>

</script>

<body>

<a href="#" onMouseover="showmenu(event,linkset[0])" onMouseout="delayhidemenu()">Webmaster Links</a><br>
<a href="#" onMouseover="showmenu(event,linkset[1], '180px')" onMouseout="delayhidemenu()">News sites</a>

warrenta
02-06-2009, 12:38 AM
One last thought....Here is a way to get some men and submenu centered headings:


var linkset=new Array()
//SPECIFY MENU SETS AND THEIR LINKS. FOLLOW SYNTAX LAID OUT

linkset[0]='<a href="#">MENU CHOICES</a>'
linkset[0]+='<hr>'
linkset[0]+='<a href="http://dynamicdrive.com">Dynamic Drive</a>'
linkset[0]+='<a href="http://www.javascriptkit.com">JavaScript Kit</a>'
linkset[0]+='<a href="#" onClick="showmenuxx(event,linkset[2], \'100px\', \'sub\'); return false" style="position:relative">Coding Forums</a>'
linkset[0]+='<a href="#" onClick="showmenuxx(event,linkset[3], \'100px\', \'sub\'); return false" style="position:relative">CSS Drive</a>'
linkset[0]+='<a href="http://freewarejava.com">Freewarejava</a>'

linkset[1]='<a href="#">MENU CHOICES</a>'
linkset[1]+='<hr>'
linkset[1]+='<a href="http://msnbc.com">MSNBC</a>'
linkset[1]+='<a href="http://cnn.com">CNN</a>'
linkset[1]+='<a href="http://news.bbc.co.uk">BBC News</a>'
linkset[1]+='<a href="http://www.washingtonpost.com">Washington Post</a>'

linkset[2]='<a href="#">SUBMENU CHOICES</a>'
linkset[2]+='<hr>'
linkset[2]+='<a href="http://msnbc.com">FORUM #1</a>'
linkset[2]+='<a href="http://cnn.com">FORUM #2</a>'
linkset[2]+='<a href="http://news.bbc.co.uk">FORUM #3</a>'
linkset[2]+='<a href="http://www.washingtonpost.com">FORUM #4</a>'

linkset[3]='<a href="#">SUBMENU CHOICES</a>'
linkset[3]+='<hr>'
linkset[3]+='<a href="http://www.cssdrive.com">CSS DRIVE #1</a>'
linkset[3]+='<a href="http://www.cssdrive.com">CSS DRIVE #2</a>'
linkset[3]+='<a href="http://www.cssdrive.com">CSS DRIVE #3</a>'
linkset[3]+='<a href="http://www.cssdrive.com">CSS DRIVE #4</a>'


////No need to edit beyond here

ddadmin
02-06-2009, 07:13 AM
Please try and format any code in your post using the CODE tags. It just makes it easier to read. :)