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 Rhinorhino on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

2 problems with my dhtml menu

Status
Not open for further replies.

tonyx666

MIS
Joined
Apr 13, 2006
Messages
214
Location
GB
hi you lot.. i have a problem with a drop down menu ive made. and i need to get it working as soon as i can so any help would really be appreciated

the menu is here, it seems to work but there are a couple of problems..

http://bb.1asphost.com/antonyx6/menu/dropdown.html


Problem 1: Im using the dreamweaver rollover image code for the rollover buttons.. in my body tag it says to load all the images being used like so..

Code:
<body onLoad="MM_preloadImages('fleet.jpg','fleet2.jpg','exec.jpg','exec2.jpg..etc')">

The problem is that when the page loads, and you mouse over one of the menu items.. the 2nd rollover image hasnt already loaded and it takes a few moments for it to appear..

Question 1: is there anyway to ensure that all the rollover images load immediately so this delay affect does not occur.



Problem 2: As you go from one menu column to another, i realised i could alter the delay time using this..

Code:
function at_hide()
{
  c = document.getElementById(this["at_child"]);

  c["at_timeout"] = setTimeout("document.getElementById('"+c.id+"').style.visibility = 'hidden'", [b]0.8[/b]);


}

this makes the transition from one menu to the next pretty instant which is what i want.. but there is a problem.. sometimes when the mouse is over the top item for too long or too short a time.. you move down towards the menu items for that selection and they disappear...

Question 2: Can i ensure that the transition between the menus is instant like it is currently but also make sure that the menu items below the chosen menu heading will always be active and selectable always if the mouse is hovering over the menu header..

i am fairly profficient with html and css but my javascript is not wonderful which i why im having trouble customising this system..

here is the tutorial i used..
http://www.dynamicdrive.com/dynamicindex1/dropdowncontrol.htm


if these 2 issues could be resolved then i think the menu will be ready and i will be very grateful..

below is the javascript code for the actual page with the divs and the js functions.. thanks again.

js menu functions
Code:
// <script>

// Copyright (C) 2005 Ilya S. Lyubinskiy. All rights reserved.
// Technical support: [URL unfurl="true"]http://www.php-development.ru/[/URL]
//
// YOU MAY NOT
// (1) Remove or modify this copyright notice.
// (2) Distribute this code, any part or any modified version of it.
//     Instead, you can link to the homepage of this code:
//     [URL unfurl="true"]http://www.php-development.ru/javascripts/smart-forms.php.[/URL]
//
// YOU MAY
// (1) Use this code on your website.
// (2) Use this code as a part of another product provided that
//     its main use is not creating javascript menus.
//
// NO WARRANTY
// This code is provided "as is" without warranty of any kind, either
// expressed or implied, including, but not limited to, the implied warranties
// of merchantability and fitness for a particular purpose. You expressly
// acknowledge and agree that use of this code is at your own risk.

// If you find my script useful, you can support my site in the following ways:
// 1. Vote for the script at HotScripts.com (you can do it on my site)
// 2. Link to the homepage of this script or to the homepage of my site:
//    [URL unfurl="true"]http://www.php-development.ru/javascripts/smart-forms.php[/URL]
//    [URL unfurl="true"]http://www.php-development.ru/[/URL]
//    You will get 50% commission on all orders made by your referrals.
//    More information can be found here:
//    [URL unfurl="true"]http://www.php-development.ru/affiliates.php[/URL]


// ----- Popup Control ---------------------------------------------------------

function at_display(x)
{
  win = window.open();
  for (var i in x) win.document.write(i+' = '+x[i]+'<br>');
}

// ----- Show Aux -----

function at_show_aux(parent, child)
{
  var p = document.getElementById(parent);
  var c = document.getElementById(child);

  var top  = (c["at_position"] == "y") ? p.offsetHeight+2 : 0;
  var left = (c["at_position"] == "x") ? p.offsetWidth +2 : 0;

  for (; p; p = p.offsetParent)
  {
    top  += p.offsetTop;
    left += p.offsetLeft;
  }

  c.style.position   = "absolute";
  c.style.top        = top +'px';
  c.style.left       = left+'px';
  c.style.visibility = "visible";
}

// ----- Show -----

function at_show()
{
  p = document.getElementById(this["at_parent"]);
  c = document.getElementById(this["at_child" ]);

  at_show_aux(p.id, c.id);

  clearTimeout(c["at_timeout"]);
}

// ----- Hide -----

function at_hide()
{
  c = document.getElementById(this["at_child"]);

  c["at_timeout"] = setTimeout("document.getElementById('"+c.id+"').style.visibility = 'hidden'", 0.8);
}

// ----- Click -----

function at_click()
{
  p = document.getElementById(this["at_parent"]);
  c = document.getElementById(this["at_child" ]);

  if (c.style.visibility != "visible") at_show_aux(p.id, c.id);
  else c.style.visibility = "hidden";

  return false;
}

// ----- Attach -----

// PARAMETERS:
// parent   - id of visible html element
// child    - id of invisible html element that will be dropdowned
// showtype - "click" = you should click the parent to show/hide the child
//            "hover" = you should place the mouse over the parent to show
//                      the child
// position - "x" = the child is displayed to the right of the parent
//            "y" = the child is displayed below the parent
// cursor   - Omit to use default cursor or check any CSS manual for possible
//            values of this field

function at_attach(parent, child, showtype, position, cursor)
{
  p = document.getElementById(parent);
  c = document.getElementById(child);

  p["at_parent"]     = p.id;
  c["at_parent"]     = p.id;
  p["at_child"]      = c.id;
  c["at_child"]      = c.id;
  p["at_position"]   = position;
  c["at_position"]   = position;

  c.style.position   = "absolute";
  c.style.visibility = "hidden";

  if (cursor != undefined) p.style.cursor = cursor;

  switch (showtype)
  {
    case "click":
      p.onclick     = at_click;
      p.onmouseout  = at_hide;
      c.onmouseover = at_show;
      c.onmouseout  = at_hide;
      break;
    case "hover":
      p.onmouseover = at_show;
      p.onmouseout  = at_hide;
      c.onmouseover = at_show;
      c.onmouseout  = at_hide;
      break;
  }
}


and my page at the moment
Code:
<html>
<head>

<title>Dropdown Sample</title>

<script type="text/javascript" src="dropdown.js">
</script>

<script type="text/javascript" src="image.js">
</script>

</head>
<body onLoad="MM_preloadImages('fleet.jpg','fleet2.jpg','exec.jpg','exec2.jpg','acc.jpg','acc2.jpg',
'quote.jpg','quote2.jpg','air.jpg','air2.jpg','sea.jpg',sea2.jpg','day.jpg','day2.jpg','enq.jpg',
'enq2.jpg','book.jpg','book2.jpg','faq.jpg','faq2.jpg','site.jpg','site2.jpg','tc.jpg','tc2.jpg',
'gen.jpg','gen2.jpg','hotels.jpg','hotels2.jpg','events.jpg','events2.jpg')">

<h3>Dropdown Sample</h3>

<!-- Dropdown Menu -->

<div id="menu_parent"
     style="width: 47px; border:0px; padding: 0px 0px; float:left;">
<img src="home.jpg"/>
</div>

<div id="menu2_parent"
     style="width: 63px; border:0px; padding: 0px 0px; float:left;">
<img src="services.jpg"/>
</div>
<div id="menu2_child"
     style="position: absolute; visibility: hidden; background: #ffffff;">
<a href="prop_other.asp" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('Image1','','fleet2.jpg',1)"><img 
src="fleet.jpg" name="Image1" width="144" height="26" border="0"></a><br>
<a href="prop_other.asp" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('Image2','','exec2.jpg',1)"><img 
src="exec.jpg" name="Image2" width="144" height="26" border="0"></a><br>
<a href="prop_other.asp" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('Image3','','acc2.jpg',1)"><img 
src="acc.jpg" name="Image3" width="144" height="26" border="0"></a><br>
</div>

<script type="text/javascript">
at_attach("menu2_parent", "menu2_child", "hover", "y", "pointer");
</script>

<div id="menu3_parent"
     style="width: 47px; border:0px; padding: 0px 0px; float:left;">
<img src="rates.jpg"/>
</div>

<div id="menu3_child"
     style="position: absolute; visibility: hidden; background: #ffffff;">
	 <a href="prop_other.asp" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('Image4','','quote2.jpg',1)"><img 
src="quote.jpg" name="Image4" width="144" height="26" border="0"></a><br>
<a href="prop_other.asp" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('Image5','','air2.jpg',1)"><img 
src="air.jpg" name="Image5" width="144" height="26" border="0"></a><br>
<a href="prop_other.asp" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('Image6','','sea2.jpg',1)"><img 
src="sea.jpg" name="Image6" width="144" height="26" border="0"></a><br>
<a href="prop_other.asp" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('Image7','','day2.jpg',1)"><img 
src="day.jpg" name="Image7" width="144" height="26" border="0"></a><br>
</div>

<script type="text/javascript">
at_attach("menu3_parent", "menu3_child", "hover", "y", "pointer");
</script>

<div id="menu4_parent"
     style="width: 137px; border:0px; padding: 0px 0px; float:left;">
<img src="enqbook.jpg"/>
</div>

<div id="menu4_child"
     style="position: absolute; visibility: hidden; background: #ffffff;">
	 <a href="prop_other.asp" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('Image8','','enq2.jpg',1)"><img 
src="enq.jpg" name="Image8" width="144" height="26" border="0"></a><br>
<a href="prop_other.asp" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('Image9','','book2.jpg',1)"><img 
src="book.jpg" name="Image9" width="144" height="26" border="0"></a><br>

</div>

<script type="text/javascript">
at_attach("menu4_parent", "menu4_child", "hover", "y", "pointer");
</script>

<div id="menu5_parent"
     style="width: 35px; border:0px; padding: 0px 0px; float:left;">
<img src="info.jpg"/>
</div>

<div id="menu5_child"
     style="position: absolute; visibility: hidden; background: #ffffff;">
	 <a href="prop_other.asp" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('Image10','','faq2.jpg',1)"><img 
src="faq.jpg" name="Image10" width="144" height="26" border="0"></a><br>
<a href="prop_other.asp" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('Image11','','tc2.jpg',1)"><img 
src="tc.jpg" name="Image11" width="144" height="26" border="0"></a><br>
<a href="prop_other.asp" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('Image12','','site2.jpg',1)"><img 
src="site.jpg" name="Image12" width="144" height="26" border="0"></a><br>
</div>

<script type="text/javascript">
at_attach("menu5_parent", "menu5_child", "hover", "y", "pointer");
</script>


<div id="menu6_parent"
     style="width: 44px; border:0px; padding: 0px 0px; float:left;">
<img src="links.jpg"/>
</div>

<div id="menu6_child"
     style="position: absolute; visibility: hidden; background: #ffffff;">
	 <a href="prop_other.asp" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('Image13','','gen2.jpg',1)"><img 
src="gen.jpg" name="Image13" width="144" height="26" border="0"></a><br>
<a href="prop_other.asp" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('Image14','','hotels2.jpg',1)"><img 
src="hotels.jpg" name="Image14" width="144" height="26" border="0"></a><br>
<a href="prop_other.asp" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('Image15','','events2.jpg',1)"><img 
src="events.jpg" name="Image15" width="144" height="26" border="0"></a><br>
</div>

<script type="text/javascript">
at_attach("menu6_parent", "menu6_child", "hover", "y", "pointer");
</script>

<div id="menu7_parent"
     style="width: 59px; border:0px; padding: 0px 0px; float:left;">
<img src="contact.jpg"/>
</div>

</body>
</html>
 
First problem:
The idea of pre-loading the images is of course to have them loaded and ready when the page needs to use them but calling the pre-load code from the onload event in the body tag is not going to make this happen. The onload event only executes AFTER the page has completed loading so what is happening is that your page loads then it starts loading the images and the user has time to go galavanting across the page before all the images may have arrived.

Since your pre-load function is in an include what you might be able to do is to put a call to that function at the top of your on-page javascript that occurs after your include statement. The call to the function would then occur as soon as that bit of the page is processed while the document is still loading and helps to ensure the images load prior to the HTML portions of the page.
I think there are sometimes timing issues with pre-loading and some browsers but give it a shot.

Second problem.
I did not delve deeply into your code. I think that what you are trying to do is set a timer delay so that if the mouse moves off of the main menu item you want it to delay slightly before it closes off the sub menu items.
I think you have it close to what you need but again have not looked very intently at what you have coded, I do not have much time at the moment.

Here is the general approach and you can check it against what you have.
In your mouseover event you make the sub menu visible.
In the mouseoff event you set a timer to call the function that will hide the sub menu. I find that a delay of 500 works nicely. Remember that the time is in milliseconds so 500 is a half second. I think you have like .8 there.
Instead of trying to execute a command with the timer (not sure if that works) have it call a function to do the work.

Do the event like this:
Code:
//Global Variable for timer:
var tID;

//[b]onmouseout event[/b] for your menu link.
onmouseout="closeSubmenu(subMenu1);"

function closeSubmenu(mnuName) {
  if (window.tID) clearTimeout(tID); //Clear any already existing timer.
  tID = window.setTimeout("hideMenuObject("+mnuName+")",500); //Set new timer
 }

function hideMenuObject(mnuName) {
  mnuName.style.visibility = "hidden";
}

The above handles making sure the sub menu stays open for at least a half second after the mouse leaves the main menu item. This is good if the mouse is moving somewhere other than to another top menu item. If however the mouse moves onto another top menu item you want the the last menu item to close immediately so, in your function that shows the sub menu item to begin with you want to start out by making certain the timer is reset just like you do at the beginning of the closeSubMenu function with this line:

if (window.tID) clearTimeout(tID); //Clear any already existing timer.

Not sure I am being clear and not just rambling here is the quick breakdown:
1. onmouseover event calls function to show submenu.
2. show submenu function clears any existing timer then displays the appropriate sub menu.
3. onmouseout event calls function to set timer for closing the sub menu.
4. set closing timer function first cancels any existing timer then sets a new timer to execute the close sub menu function.
5. close sub menu function hides the sub menu.

With this method the sub menu will stay open for the specified amount of time unless the mouse moves to another top menu item which first cancels the old timer so the sub menu will close immediately.

Good luck.


Paranoid? ME?? Who wants to know????
 
ok, changing the 0.8 value to 500 has completely removed problem 2..

the submenu remains visible below its menu counterpart no matter how long the mouse stays on the menu selector item..

hooray..

however, gettin rid of that issue has left the transition between the menus too slow.. it can be seen here
http://bb.1asphost.com/antonyx6/menu/dropdown.html

im sure your method will apply to this mr owl. but im not confident in javascript enough to modify a general template to my own code which i am barely gettin to grips with.

also about the images being loaded..

are you suggesting that i should place some kind of function in the external js file that loads the images and prepares them for the menu as soon as the page loads.. ?

how would i go about this?
 
One the first part, in the function at_show() move the clearTimeOut line above the at_show_aux(p.id, c.id); line.

If that does not do it then try having the clearTimeOut line as the first AND last lines. I have not yet puzzled out why they have it at the end of the function. The idea as I see it is to cancel any existing timer prior to displaying any new data.

For the second part:
Take this out of the body tag:
onLoad="MM_preloadImages('fleet.jpg','fleet2.jpg','exec.jpg','exec2.jpg..etc')"

And put this directly beneath the lines loading the image.js file.
Code:
MM_preloadImages('fleet.jpg','fleet2.jpg','exec.jpg','exec2.jpg','acc.jpg','acc2.jpg',
'quote.jpg','quote2.jpg','air.jpg','air2.jpg','sea.jpg',sea2.jpg','day.jpg','day2.jpg','enq.jpg',
'enq2.jpg','book.jpg','book2.jpg','faq.jpg','faq2.jpg','site.jpg','site2.jpg','tc.jpg','tc2.jpg',
'gen.jpg','gen2.jpg','hotels.jpg','hotels2.jpg','events.jpg','events2.jpg')";
[code]

The idea is to have the images load right after the .js file loads and not wait for the rest of the page.
If you make the call to MM_preloadImages from the onload event then it executes after the whole page has already loaded instead of before.


Paranoid?  ME??    Who wants to know????
 
ok i have put the menu on a faster host.

my show function looks like this
Code:
function at_show()
{
  p = document.getElementById(this["at_parent"]);
  c = document.getElementById(this["at_child" ]);
  clearTimeout(c["at_timeout"]);
  at_show_aux(p.id, c.id);
  clearTimeout(c["at_timeout"]);
  
}

and the head of my page looks like this..
Code:
<head>

<title>Dropdown Sample</title>

<script type="text/javascript" src="dropdown.js">
</script>

<script type="text/javascript" src="image.js">

MM_preloadImages('fleet.jpg','fleet2.jpg','exec.jpg','exec2.jpg',
'acc.jpg','acc2.jpg','quote.jpg','quote2.jpg','air.jpg','air2.jpg',
'sea.jpg','sea2.jpg','day.jpg','day2.jpg','enq.jpg','enq2.jpg',
'book.jpg','book2.jpg','faq.jpg','faq2.jpg','site.jpg','site2.jpg',
'tc.jpg','tc2.jpg','gen.jpg','gen2.jpg','hotels.jpg','hotels2.jpg',
'events.jpg','events2.jpg')
</script>

</head>

the timeout function is still not making the transition between the menu columns instant.. infact if you run the mouse along the menu headers from left to right they leave a little pattern of fading menus..

the only way i can make that transition quicker is by reducing the number 500.. (which is incidently why i had it on 0.8 in the first place.. but having it that low gave me that original problem of the submenus dissappearing).

also the loading of the images is taking too long.. each image is less then 3 or 4 kb each.. so on my broadband it should be much much quicker.. is it because i am loading 2 external js files that it takes so long??

also having the MM image loads at the above point still gives me that annoying delay when the menu parts are moused over..

im open to any suggestion.. and can modify any part of it at your will...
i wait in anticipation..

here is what the menu looks like now with the changes in your previous post made

http://heathrowminicab.com/menu/dropdown.html
 
Put the call to the MM_preloadImages function in it's own script tags. It should look like this:

Code:
<head>

<title>Dropdown Sample</title>

<script type="text/javascript" src="dropdown.js">
</script>

<script type="text/javascript" src="image.js">
</script>
<script type="text/javascript">
  MM_preloadImages('fleet.jpg','fleet2.jpg','exec.jpg','exec2.jpg',
'acc.jpg','acc2.jpg','quote.jpg','quote2.jpg','air.jpg','air2.jpg',
'sea.jpg','sea2.jpg','day.jpg','day2.jpg','enq.jpg','enq2.jpg',
'book.jpg','book2.jpg','faq.jpg','faq2.jpg','site.jpg','site2.jpg',
'tc.jpg','tc2.jpg','gen.jpg','gen2.jpg','hotels.jpg','hotels2.jpg',
'events.jpg','events2.jpg')
</script>
</head>
See if that makes a difference.

One problem though is that you are not loading the images for your main menu items in the preload script, you are only loading the images for the sub menus that use the mouseovers. So those images may not be loaded by the time you need to use them but the sub menu images should be.

As for the timer issue, the code is complicated by attaching event handlers to the items themselves and I have never done that. It will take longer than I have available to figure out the code.

It might be simpler for you to find a different script for handling the menus. I am sure I could figure it out but we are just packing to leave on vacation and I will not be back for over a week.

Good luck.

Paranoid? ME?? Who wants to know????
 
listen mate u have helped me more than enough..

go.. enjoy your vacation.. ill try and get around it.. if i still need your help in a weeks time then ill give you a shout.. thanks again.

can anyone else help me?
 
tonyx666 did you get your script problems resolved?

Paranoid? ME?? Who wants to know????
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top