SitePoint Sponsor

User Tag List

Results 1 to 12 of 12

Hybrid View

  1. #1
    SitePoint Member
    Join Date
    Jun 2007
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Help! Need my menu to be 'Click on, Roll Off'

    Hi there,

    Been browsing through the pages of this amazing forum and haven't seen my specific problem addressed, so here goes:

    I have this drop-down menu:
    http://www.darraghcostello.com/javascript/cms/page.html

    that calls this .js file:
    http://www.darraghcostello.com/javas...ts_dropdown.js

    I inherited this .js menu from the original designer that the client hired but now the client wants to change how it behaves.

    Specificially,

    • The menu should not 'drop-down' until it is clicked on by the mouse.
    • It should disappear - or roll back up - when the user rolls away with their mouse.


    I think this is refered to as 'click on & roll off'.

    I'm hoping this should be a fairly straight forward edit to the .js file.

    I would be hugely grateful if anyone could take the time to have a go at it.

    Deek.


    This is the code:

    // Dropdown
    sfHover = function() {
    var sfEls = document.getElementById("nav_dropdown").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);

    // Generic Scripts
    function MM_jumpMenu(targ,selObj,restore){ //v3.0
    eval(targ+".location='"+selObj.options[selObj.selectedIndex].value+"'");
    if (restore) selObj.selectedIndex=0;
    }



    // Connect Login Scripts
    var userpwdFocus = false;
    function hadFocus(set)
    {
    if (set) userpwdFocus = true;
    return userpwdFocus;
    }



    function login()
    {
    document.cplogin.user.value=document.userid.user.value;
    document.cplogin.submit();
    }

  2. #2
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Unfortunately in this case it isn't so simple because the only browser to use that javascript is Internet Explorer 5.5/6. Practically all other modern browsers handle CSS decently and so do not need javascript to get this effect to work. In your case, this is the method's downfall because there is no such thing as :click for CSS, only :hover.

    This means that to make it work on click, you will need to use javascript for all browsers, which has its downfall in that it's not as accessible any more since those with javascript turned off won't be able to use the menu. However, if you're prepared to accept this, then all you need to do is replace
    Code:
    sfEls[i].onmouseover=function() {
    with
    Code:
             sfEls[i].onclick=function() {
    and also replace this:
    Code:
     if (window.attachEvent) window.attachEvent("onload", sfHover);
    with this:
    Code:
     if (window.addEventListener) window.addEventListener('load', sfHover, false);
    else if (window.attachEvent) window.attachEvent("onload", sfHover);
    And in the CSS change this:
    Code:
    #nav_dropdown li:hover ul, #nav_dropdown li.sfhover ul
    to this:
    Code:
    #nav_dropdown li.sfhover ul
    This is a quick fix using existing code, though. For neatness' sake (possibly pedantry's too) you should rename the sfhover class name to something more meaningful, like "active", and possibly the function name too.

  3. #3
    SitePoint Member
    Join Date
    Jun 2007
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Raffles - Thanks for you very quick reply.

    I have just updated that line in the .js file - take a look.

    I've just looked at it on OSX/Firefox, XP-IE & Firefox and it behaves pretty much the same as it did.

    CSS: I removed:

    #nav_dropdown li:hover ul, #nav_dropdown li.sfhover ul { /* lists nested under hovered list items */
    left: auto;
    }

  4. #4
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Yes, it works for me too. One thing is that when it is clicked, the window is reloaded, stopping people from being able to click on the menu unless they're very quick. This is because for some reason you have this:
    HTML Code:
    <a href="javascript:window.location.reload()" onfocus="document.getElementById('nav2_dropdown').style.left = 'auto';">
    Instead of that javascript for the href attribute, just use "#". And you also don't need the onfocus attribute (that is handled by the sfHover function) - I'd get rid of that too.

  5. #5
    SitePoint Member
    Join Date
    Jun 2007
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Right, I've just tidied up the HTML to read:

    <ul id="nav_dropdown">
    <li><a href="#">My MAIN MENU</a>
    <ul id="nav2_dropdown">

    And have saved that to this page instead:

    http://www.darraghcostello.com/javas...cms/page2.html

    It doesn't work! I reckon your close though, if you leave it as:
    <ul id="nav_dropdown">
    <li><a href="#" onfocus="document.getElementById('nav2_dropdown').style.left = 'auto';">

    as this page does: http://www.darraghcostello.com/javas...cms/page9.html

    Hmmmm....

    Btw, I did look at pure HTML/CSS options but I figured this would be a quicker option. Maybe not!

  6. #6
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Well, it doesn't work because you haven't changed this line in the javascript like I said above:
    Code:
    if (window.attachEvent) window.attachEvent("onload", sfHover);
    You need to add the addEventListener line for it to work in browsers other than Internet Explorer. It also won't work because you need to add the following CSS to your CSS file (which I said earlier about changing it but you seem to have removed completely):
    Code:
    #nav_dropdown li.sfhover ul {left:auto}
    Pure HTML/CSS options won't work because, like I said earlier, there is no reliable method of styling things based on clicks, unlike hover states.

  7. #7
    SitePoint Member
    Join Date
    Jun 2007
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Raffles -

    Apologies - I had taken a shortcut (as if posting to a javascript forum wasn't shortcut enough) and had only made the changes I saw in the (abbreviated) version of your post when it arrived as an email.

    Anyway - all your suggested edits are now in place:
    http://www.darraghcostello.com/javascript/cms/page.html

    I hate to say it, mate, but it's still a problem.

    I don't expect you to waste any more time on this, but if you do it would be very much appreciated.

    Deek,
    Dublin.

  8. #8
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Ah, I think this is because the event is bubbling all the way to the child list items (the problem I see is that the clicking works but on mouseout the dropdown is still there). This is the ideal scenario for using addEventListener and its capturing/bubbling option, but IE doesn't support that, so a less neat method is necessary.
    Code:
    sfHover = function() {
    var sfEl = document.getElementById("nav_dropdown").getElementsByTagName("LI")[0];
    sfEl.onclick=function() {
    this.className+=" sfhover";
    }
    sfEl.onmouseout=function(e) {
    if (!e) var e = window.event;
    	var tg = (window.event) ? e.srcElement : e.target;
    	if (tg.nodeName != 'LI') return;
    	var reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement;
    	while (reltg != tg && reltg.nodeName != 'BODY')
    		reltg= reltg.parentNode
    	if (reltg== tg) return;
    this.className=this.className.replace(new RegExp(" sfhover\\b"), "");
    }
    }
    if (window.addEventListener) window.addEventListener('load', sfHover, false);
    else if (window.attachEvent) window.attachEvent("onload", sfHover);
    I also trimmed it down (removed loop) because it seems you only need one dropdown (i.e. you don't need that one to have submenus branching off it - correct me if I'm wrong).

    I copied the targeting snippet from here (that site is a great resource) and I think it should work. If it doesn't, I'll have another look at it tomorrow, I need to sleep now. Hope it does work though!

  9. #9
    SitePoint Member
    Join Date
    Jun 2007
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Sleep?? I'm not paying you to slee..., oh , right, yes, sleep - good idea

    I've put the new code in and.... nearly.... it does 'click on' but that's it - can't get it to disappear then.

    http://www.darraghcostello.com/javascript/cms/page.html


    D'oh!

  10. #10
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Right, I clearly needed that sleep because I didn't realise that snippet does not apply to this situation because all the anchors have block display and overlap their parents completely. I've tested this and it works:
    Code javascript:
    sfHover = function() {
    var sfEl = document.getElementById("nav_dropdown").getElementsByTagName("LI")[0];
    sfEl.onclick=function() {
    this.className+=" sfhover";
    }
    sfEl.onmouseout=function(e) {
      if (!e) var e = window.event;
        var reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement;
        if (reltg.parentNode.parentNode.id == 'nav2_dropdown') return;
      this.className='';
    }
    }
    if (window.addEventListener) window.addEventListener('load', sfHover, false);
    else if (window.attachEvent) window.attachEvent("onload", sfHover);
    Much simpler and should be bullet-proof. Sorry it took so long to get it right!

  11. #11
    SitePoint Member
    Join Date
    Jun 2007
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Raffles - what can I say - you are a bloody genius !!!

    http://www.darraghcostello.com/javascript/cms/page.html

    It's working perfectly.

    I'm really quite taken aback sometimes at the generosity of strangers. To give your time and expertise like that is really something.

    Thank you very much for doing that for me. I shall 'pay it forward' somehow today!

  12. #12
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    You're welcome.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •