Firefox problem with dhtml menu and Google Adsense

Discussion in 'HTML & Website Design' started by CheapyD, Jun 30, 2005.

  1. #1
    Hi there, I hope you can help me.

    I use these simple drop down menus on my site and wanted to add a Google Adsense banner underneath it. Everything is fine in IE, but the menu doesn't function properly in Firefox when it drops down infront of the Google Ad.

    The menus work fine in all browsers when there is no Google Ad in the way.

    You can check it out here:
    http://www.cheapassgamer.com/archives/000992.php

    Thanks!
     
    CheapyD, Jun 30, 2005 IP
  2. CheapyD

    CheapyD Peon

    Messages:
    23
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #2
    $10 paypal to anyone who figures this out!
     
    CheapyD, Jul 1, 2005 IP
  3. CheapyD

    CheapyD Peon

    Messages:
    23
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #3
    Here is where I got the menubar code from:
    http://www.brainjar.com/dhtml/menubar/

    $10 offer still stands
     
    CheapyD, Jul 3, 2005 IP
  4. J.D.

    J.D. Peon

    Messages:
    1,198
    Likes Received:
    65
    Best Answers:
    0
    Trophy Points:
    0
    #4
    Your menus interfere with Google's code. Stick the following HTML into this page to see it for yourself:

    <div style="height: 50px;">&nbsp;</div>

    <div class="blog" style="border: 1px solid red;">
    <!-- google ads -->

    Google's iframe will be outlined with a red border. Your menus will disappear as soon as the mouse pointer crosses iframe's boundary.

    Another thing. Don't identify your doctype as XHTML - it's nowhere near XHTML and will confuse some browsers (there're hundreds of errors).

    J.D.
     
    J.D., Jul 3, 2005 IP
  5. CheapyD

    CheapyD Peon

    Messages:
    23
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #5
    Right, I kinda knew they were interfering with Google's code, which is why I posted here. ;)
    Thanks for the heads up with the doctype.
    Any ideas on how to fix the menu problem?
    I got $10 paypal if you do...
    Remember, all is well in IE, its FireFox having the problem.
     
    CheapyD, Jul 4, 2005 IP
  6. J.D.

    J.D. Peon

    Messages:
    1,198
    Likes Received:
    65
    Best Answers:
    0
    Trophy Points:
    0
    #6
    IE is special-cased in your code all over the place. It's really different code.

    Your problem is that once the mouse pointer hovers above one of the iframes, the HTML document in the relevant iframe begins receiving mouse events, which are not bubbling to your menu div's and a's because iframe's content is a standalone HTML document.

    What you can try is to make buttonOrMenuMouseout return right away, which will prevent the sub-menu from disappearing. However, you will need some other mechanism to hide sub-menus when the pointer no longer hovers over any of the items. You can try adding an event handler to the body tag and hide active sub-menus when the pointer is not hovering above any menus.

    You can also try changing website layout to avoid having an iframe underneath your menu.

    Can't help you more, sorry.

    J.D.
     
    J.D., Jul 5, 2005 IP
  7. CheapyD

    CheapyD Peon

    Messages:
    23
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #7
    Maybe something can be added to the menu's javascript that will make FireFox work as IE?

    //******************************************************************
    // Do not remove this notice.
    //
    // Copyright 2000-2004 by Mike Hall.
    // See http://www.brainjar.com for terms of use.
    //*****************************************************************************
    
    //----------------------------------------------------------------------------
    // Code to determine the browser and version.
    //----------------------------------------------------------------------------
    
    function Browser() {
    
      var ua, s, i;
    
      this.isIE    = false;  // Internet Explorer
      this.isOP    = false;  // Opera
      this.isNS    = false;  // Netscape
      this.version = null;
    
      ua = navigator.userAgent;
    
      s = "Opera";
      if ((i = ua.indexOf(s)) >= 0) {
        this.isOP = true;
        this.version = parseFloat(ua.substr(i + s.length));
        return;
      }
    
      s = "Netscape6/";
      if ((i = ua.indexOf(s)) >= 0) {
        this.isNS = true;
        this.version = parseFloat(ua.substr(i + s.length));
        return;
      }
    
      // Treat any other "Gecko" browser as Netscape 6.1.
    
      s = "Gecko";
      if ((i = ua.indexOf(s)) >= 0) {
        this.isNS = true;
        this.version = 6.1;
        return;
      }
    
      s = "MSIE";
      if ((i = ua.indexOf(s))) {
        this.isIE = true;
        this.version = parseFloat(ua.substr(i + s.length));
        return;
      }
    }
    
    var browser = new Browser();
    
    //----------------------------------------------------------------------------
    // Code for handling the menu bar and active button.
    //----------------------------------------------------------------------------
    
    var activeButton = null;
    
    /* [MODIFIED] This code commented out, not needed for activate/deactivate
       on mouseover.
    
    // Capture mouse clicks on the page so any active button can be
    // deactivated.
    
    if (browser.isIE)
      document.onmousedown = pageMousedown;
    else
      document.addEventListener("mousedown", pageMousedown, true);
    
    function pageMousedown(event) {
    
      var el;
    
      // If there is no active button, exit.
    
      if (activeButton == null)
        return;
    
      // Find the element that was clicked on.
    
      if (browser.isIE)
        el = window.event.srcElement;
      else
        el = (event.target.tagName ? event.target : event.target.parentNode);
    
      // If the active button was clicked on, exit.
    
      if (el == activeButton)
        return;
    
      // If the element is not part of a menu, reset and clear the active
      // button.
    
      if (getContainerWith(el, "DIV", "menu") == null) {
        resetButton(activeButton);
        activeButton = null;
      }
    }
    
    [END MODIFIED] */
    
    function buttonClick(event, menuId) {
    
      var button;
    
      // Get the target button element.
    
      if (browser.isIE)
        button = window.event.srcElement;
      else
        button = event.currentTarget;
    
      // Blur focus from the link to remove that annoying outline.
    
      button.blur();
    
      // Associate the named menu to this button if not already done.
      // Additionally, initialize menu display.
    
      if (button.menu == null) {
        button.menu = document.getElementById(menuId);
        if (button.menu.isInitialized == null)
          menuInit(button.menu);
      }
    
      // [MODIFIED] Added for activate/deactivate on mouseover.
    
      // Set mouseout event handler for the button, if not already done.
    
      if (button.onmouseout == null)
        button.onmouseout = buttonOrMenuMouseout;
    
      // Exit if this button is the currently active one.
    
      if (button == activeButton)
        return false;
    
      // [END MODIFIED]
    
      // Reset the currently active button, if any.
    
      if (activeButton != null)
        resetButton(activeButton);
    
      // Activate this button, unless it was the currently active one.
    
      if (button != activeButton) {
        depressButton(button);
        activeButton = button;
      }
      else
        activeButton = null;
    
      return false;
    }
    
    function buttonMouseover(event, menuId) {
    
      var button;
    
      // [MODIFIED] Added for activate/deactivate on mouseover.
    
      // Activates this button's menu if no other is currently active.
    
      if (activeButton == null) {
        buttonClick(event, menuId);
        return;
      }
    
      // [END MODIFIED]
    
      // Find the target button element.
    
      if (browser.isIE)
        button = window.event.srcElement;
      else
        button = event.currentTarget;
    
      // If any other button menu is active, make this one active instead.
    
      if (activeButton != null && activeButton != button)
        buttonClick(event, menuId);
    }
    
    function depressButton(button) {
    
      var x, y;
    
      // Update the button's style class to make it look like it's
      // depressed.
    
      button.className += " menuButtonActive";
    
      // [MODIFIED] Added for activate/deactivate on mouseover.
    
      // Set mouseout event handler for the button, if not already done.
    
      if (button.onmouseout == null)
        button.onmouseout = buttonOrMenuMouseout;
      if (button.menu.onmouseout == null)
        button.menu.onmouseout = buttonOrMenuMouseout;
    
      // [END MODIFIED]
    
      // Position the associated drop down menu under the button and
      // show it.
    
      x = getPageOffsetLeft(button);
      y = getPageOffsetTop(button) + button.offsetHeight;
    
      // For IE, adjust position.
    
      if (browser.isIE) {
        x += button.offsetParent.clientLeft;
        y += button.offsetParent.clientTop;
      }
    
      button.menu.style.left = x - 2 + "px";
      button.menu.style.top  = y - 2 + "px";
      button.menu.style.visibility = "visible";
    }
    
    function resetButton(button) {
    
      // Restore the button's style class.
    
      removeClassName(button, "menuButtonActive");
    
      // Hide the button's menu, first closing any sub menus.
    
      if (button.menu != null) {
        closeSubMenu(button.menu);
        button.menu.style.visibility = "hidden";
      }
    }
    
    //----------------------------------------------------------------------------
    // Code to handle the menus and sub menus.
    //----------------------------------------------------------------------------
    
    function menuMouseover(event) {
    
      var menu;
    
      // Find the target menu element.
    
      if (browser.isIE)
        menu = getContainerWith(window.event.srcElement, "DIV", "menu");
      else
        menu = event.currentTarget;
    
      // Close any active sub menu.
    
      if (menu.activeItem != null)
        closeSubMenu(menu);
    }
    
    function menuItemMouseover(event, menuId) {
    
      var item, menu, x, y;
    
      // Find the target item element and its parent menu element.
    
      if (browser.isIE)
        item = getContainerWith(window.event.srcElement, "A", "menuItem");
      else
        item = event.currentTarget;
      menu = getContainerWith(item, "DIV", "menu");
    
      // Close any active sub menu and mark this one as active.
    
      if (menu.activeItem != null)
        closeSubMenu(menu);
      menu.activeItem = item;
    
      // Highlight the item element.
    
      item.className += " menuItemHighlight";
    
      // Initialize the sub menu, if not already done.
    
      if (item.subMenu == null) {
        item.subMenu = document.getElementById(menuId);
        if (item.subMenu.isInitialized == null)
          menuInit(item.subMenu);
      }
    
      // [MODIFIED] Added for activate/deactivate on mouseover.
    
      // Set mouseout event handler for the sub menu, if not already done.
    
      if (item.subMenu.onmouseout == null)
        item.subMenu.onmouseout = buttonOrMenuMouseout;
    
      // [END MODIFIED]
    
      // Get position for submenu based on the menu item.
    
      x = getPageOffsetLeft(item) + item.offsetWidth;
      y = getPageOffsetTop(item);
    
      // Adjust position to fit in view.
    
      var maxX, maxY;
    
      if (browser.isIE) {
        maxX = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft) +
          (document.documentElement.clientWidth != 0 ? document.documentElement.clientWidth : document.body.clientWidth);
        maxY = Math.max(document.documentElement.scrollTop, document.body.scrollTop) +
          (document.documentElement.clientHeight != 0 ? document.documentElement.clientHeight : document.body.clientHeight);
      }
      if (browser.isOP) {
        maxX = document.documentElement.scrollLeft + window.innerWidth;
        maxY = document.documentElement.scrollTop  + window.innerHeight;
      }
      if (browser.isNS) {
        maxX = window.scrollX + window.innerWidth;
        maxY = window.scrollY + window.innerHeight;
      }
      maxX -= item.subMenu.offsetWidth;
      maxY -= item.subMenu.offsetHeight;
    
      if (x > maxX)
        x = Math.max(0, x - item.offsetWidth - item.subMenu.offsetWidth
          + (menu.offsetWidth - item.offsetWidth));
      y = Math.max(0, Math.min(y, maxY));
    
      // Position and show the sub menu.
    
      item.subMenu.style.left = x + "px";
      item.subMenu.style.top  = y + "px";
      item.subMenu.style.visibility = "visible";
    
      // Stop the event from bubbling.
    
      if (browser.isIE)
        window.event.cancelBubble = true;
      else
        event.stopPropagation();
    }
    
    function closeSubMenu(menu) {
    
      if (menu == null || menu.activeItem == null)
        return;
    
      // Recursively close any sub menus.
    
      if (menu.activeItem.subMenu != null) {
        closeSubMenu(menu.activeItem.subMenu);
        menu.activeItem.subMenu.style.visibility = "hidden";
        menu.activeItem.subMenu = null;
      }
      removeClassName(menu.activeItem, "menuItemHighlight");
      menu.activeItem = null;
    }
    
    // [MODIFIED] Added for activate/deactivate on mouseover. Handler for mouseout
    // event on buttons and menus.
    
    function buttonOrMenuMouseout(event) {
    
      var el;
    
      // If there is no active button, exit.
    
      if (activeButton == null)
        return;
    
      // Find the element the mouse is moving to.
    
      if (browser.isIE)
        el = window.event.toElement;
      else if (event.relatedTarget != null)
          el = (event.relatedTarget.tagName ? event.relatedTarget : event.relatedTarget.parentNode);
    
      // If the element is not part of a menu, reset the active button.
    
      if (getContainerWith(el, "DIV", "menu") == null) {
        resetButton(activeButton);
        activeButton = null;
      }
    }
    
    // [END MODIFIED]
    
    
    
      
    
    Code (markup):
     
    CheapyD, Jul 5, 2005 IP
  8. CheapyD

    CheapyD Peon

    Messages:
    23
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #8
    //----------------------------------------------------------------------------
    // Code to initialize menus.
    //----------------------------------------------------------------------------
    
    function menuInit(menu) {
    
      var itemList, spanList;
      var textEl, arrowEl;
      var itemWidth;
      var w, dw;
      var i, j;
    
      // For IE, replace arrow characters.
    
      if (browser.isIE) {
        menu.style.lineHeight = "2.5ex";
        spanList = menu.getElementsByTagName("SPAN");
        for (i = 0; i < spanList.length; i++)
          if (hasClassName(spanList[i], "menuItemArrow")) {
            spanList[i].style.fontFamily = "Webdings";
            spanList[i].firstChild.nodeValue = "4";
          }
      }
    
      // Find the width of a menu item.
    
      itemList = menu.getElementsByTagName("A");
      if (itemList.length > 0)
        itemWidth = itemList[0].offsetWidth;
      else
        return;
    
      // For items with arrows, add padding to item text to make the
      // arrows flush right.
    
      for (i = 0; i < itemList.length; i++) {
        spanList = itemList[i].getElementsByTagName("SPAN");
        textEl  = null;
        arrowEl = null;
        for (j = 0; j < spanList.length; j++) {
          if (hasClassName(spanList[j], "menuItemText"))
            textEl = spanList[j];
          if (hasClassName(spanList[j], "menuItemArrow"))
            arrowEl = spanList[j];
        }
        if (textEl != null && arrowEl != null) {
          textEl.style.paddingRight = (itemWidth 
            - (textEl.offsetWidth + arrowEl.offsetWidth)) + "px";
          // For Opera, remove the negative right margin to fix a display bug.
          if (browser.isOP)
            arrowEl.style.marginRight = "0px";
        }
      }
    
      // Fix IE hover problem by setting an explicit width on first item of
      // the menu.
    
      if (browser.isIE) {
        w = itemList[0].offsetWidth;
        itemList[0].style.width = w + "px";
        dw = itemList[0].offsetWidth - w;
        w -= dw;
        itemList[0].style.width = w + "px";
      }
    
      // Mark menu as initialized.
    
      menu.isInitialized = true;
    }
    
    //----------------------------------------------------------------------------
    // General utility functions.
    //----------------------------------------------------------------------------
    
    function getContainerWith(node, tagName, className) {
    
      // Starting with the given node, find the nearest containing element
      // with the specified tag name and style class.
    
      while (node != null) {
        if (node.tagName != null && node.tagName == tagName &&
            hasClassName(node, className))
          return node;
        node = node.parentNode;
      }
    
      return node;
    }
    
    function hasClassName(el, name) {
    
      var i, list;
    
      // Return true if the given element currently has the given class
      // name.
    
      list = el.className.split(" ");
      for (i = 0; i < list.length; i++)
        if (list[i] == name)
          return true;
    
      return false;
    }
    
    function removeClassName(el, name) {
    
      var i, curList, newList;
    
      if (el.className == null)
        return;
    
      // Remove the given class name from the element's className property.
    
      newList = new Array();
      curList = el.className.split(" ");
      for (i = 0; i < curList.length; i++)
        if (curList[i] != name)
          newList.push(curList[i]);
      el.className = newList.join(" ");
    }
    
    function getPageOffsetLeft(el) {
    
      var x;
    
      // Return the x coordinate of an element relative to the page.
    
      x = el.offsetLeft;
      if (el.offsetParent != null)
        x += getPageOffsetLeft(el.offsetParent);
    
      return x;
    }
    
    function getPageOffsetTop(el) {
    
      var y;
    
      // Return the x coordinate of an element relative to the page.
    
      y = el.offsetTop;
      if (el.offsetParent != null)
        y += getPageOffsetTop(el.offsetParent);
    
      return y;
    }
    Code (markup):
     
    CheapyD, Jul 5, 2005 IP
  9. J.D.

    J.D. Peon

    Messages:
    1,198
    Likes Received:
    65
    Best Answers:
    0
    Trophy Points:
    0
    #9
    I don't think this will work (unless there's some hack I don't know about). FF uses W3C's XML/DOM event model and IE uses their own event distribution mechanism. As far as I can see, the code uses intensively event's properties to figure out where the mouse pointer is and one of the iframes just happens to be in the way. Yesterday I tried to place menu and iframes positionally and move the menu in front of one of iframe's using z-index, but it didn't help much (well, it's not really a solution, but if iframe overlaps with the menu, the menu kinda works, but it flickers and overlaping doesn't look any good).

    I also tried to play with event capturing/bubbling, but iframe doesn't seem to handle events as it should.

    The menu looks funny in Opera - the menu is actually behind the Google iframe and if you move your mouse fast enough, you can skip the iframe and continue with the menu below the ads.

    You can try modifying the function I mentioned and come up with another menu deactivation mechanism (an event handler for body should do the trick, but you'd have to know what actually to deactivate - I did a quick test with activeButton and it didn't work right away, so you'll need to try a few things).

    J.D.
     
    J.D., Jul 5, 2005 IP
  10. CheapyD

    CheapyD Peon

    Messages:
    23
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #10
    I'm not even close to being able to do something like that...
    Cheap Video Games = Expert!
    Programming = Noob!
     
    CheapyD, Jul 5, 2005 IP
  11. J.D.

    J.D. Peon

    Messages:
    1,198
    Likes Received:
    65
    Best Answers:
    0
    Trophy Points:
    0
    #11
    Try contacting the guy who developed this menu script - he may be interested in fixing this bug. You can also try using some other menus (e.g. www.dhtmlcentral.com). The one you are using doesn't really work with Opera either. I can only imagine the bad things it does with Mac/Linux browsers.

    J.D.
     
    J.D., Jul 5, 2005 IP
  12. netprophet

    netprophet Banned

    Messages:
    288
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    0
    #12
    Firefox doesn't support some dhtml effect. Because this effect especially for internet explorer. Some effect shows especially for firefox but not for internet explorer.
     
    netprophet, Sep 21, 2006 IP