Link to home
Start Free TrialLog in
Avatar of Lance_Frisbee
Lance_FrisbeeFlag for United States of America

asked on

IE BUG - Find the JavaScript Error!

I have a dropdown navigation script that I finally got working... but now it is crapping out in Internet Explorer on PC and in MAC. It works perfectly in Firefox (PC and MAC) (imagine that) and on Safari (MAC). I can't seem to track down and fix the error.

I am going to paste my source file... and my include files. Please help me out if you would be so kind... This fix is needed in a hurry, so any fast help would be excellent. Thank you.

REMEMBER - This is only an IE Error - I have browser handling in the script...

<!-- THIS IS THE SOURCE HTML FILE -->

http://www.lancefrisbee.com/test/dropdown

<!-- THIS IS THE CONTENTS OF THE TWO JAVASCRIPT FILES THAT COULD BE THE STEM OF THE PROBLEM -->

<!-- file #1: menucode.css (more likely root of the error) -->

//<!--

function Browser() {

  var ua, s, i;

  this.isIE    = false;  // Internet Explorer
  this.isOP    = false;  // Opera
  this.isSA    = false;  // Safari
  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;
  }

// Detect Safari for special case positioning fix
  s = "Safari";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isSA = true;
    this.version = parseFloat(ua.substr(i + s.length));
  }


  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;
            if (browser.isIE)
  {
            activeButton.src = "_gfx/" + activeButton.id + "-on.jpg";
  }
  else
  {
      var images = activeButton.getElementsByTagName("img");
      for (ti = 0; ti < images.length; ti++)
      {
            var thisImage = images[ti];
            if ((thisImage.src) && (activeButton.id)){
            thisImage.src = "_gfx/" + thisImage.id + "-on.jpg";
            }
      }
      }
  }
  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 + "px";
  button.menu.style.top  = y + "px";
  if (browser.isOP) {
  y -= 18;
  button.menu.style.top  = y + "px";
  }
  button.menu.style.visibility = "visible";

  // For IE; size, position and show the menu's IFRAME as well.

  if (button.menu.iframeEl != null)
  {
    button.menu.iframeEl.style.left = button.menu.style.left;
    button.menu.iframeEl.style.top  = button.menu.style.top;
    button.menu.iframeEl.style.width  = button.menu.offsetWidth + "px";
    button.menu.iframeEl.style.height = button.menu.offsetHeight + "px";
    button.menu.iframeEl.style.display = "";
  }
}

function resetButton(button) {

  // Restore the button's style class.
 
 
      if (browser.isIE)
        {
            button.src = "_gfx/" + button.id + "-off.jpg";
        }
        else
        {
            var images = button.getElementsByTagName("img");
            for (ti = 0; ti < images.length; ti++)
            {
                  var thisImage = images[ti];
                  if ((thisImage.src) && (button.id))
                  {
                  thisImage.src = "_gfx/" + thisImage.id + "-off.jpg";
                  }
            }
      }
 
  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";

    // For IE, hide menu's IFRAME as well.

    if (button.menu.iframeEl != null)
      button.menu.iframeEl.style.display = "none";
  }
}

//----------------------------------------------------------------------------
// 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 || browser.isSA) {
    maxX = document.documentElement.scrollLeft + window.innerWidth;
    maxY = document.documentElement.scrollTop  + window.innerHeight;
  }
  else 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";
  // Safari sets the sub-menu too far to the right and too far down - adjust positioning to bring them closer to what they should be
  if (browser.isSA) {
  x -= 8;
  y -= 16;
  item.subMenu.style.left       = x + "px";
  item.subMenu.style.top        = y + "px";
  }
  if (browser.isOP) {
  y -= 15;
  item.subMenu.style.top        = y + "px";
  }
  item.subMenu.style.visibility = "visible";

  // For IE; size, position and display the menu's IFRAME as well.

  if (item.subMenu.iframeEl != null)
  {
    item.subMenu.iframeEl.style.left    = item.subMenu.style.left;
    item.subMenu.iframeEl.style.top     = item.subMenu.style.top;
    item.subMenu.iframeEl.style.width   = item.subMenu.offsetWidth + "px";
    item.subMenu.iframeEl.style.height  = item.subMenu.offsetHeight + "px";
    item.subMenu.iframeEl.style.display = "";
  }

  // 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";

    // For IE, hide the sub menu's IFRAME as well.

    if (menu.activeItem.subMenu.iframeEl != null)
      menu.activeItem.subMenu.iframeEl.style.display = "none";

    menu.activeItem.subMenu = null;
  }

  // Deactivate the active menu item.

  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 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";
  }

  // Fix the IE display problem (SELECT elements and other windowed controls
  // overlaying the menu) by adding an IFRAME under the menu.

  if (browser.isIE) {
    menu.iframeEl = menu.parentNode.insertBefore(document.createElement("IFRAME"), menu);
    menu.iframeEl.style.display = "none";
    menu.iframeEl.style.position = "absolute";
  }

  // 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;
}

// -->



<!-- FILE#2: menuinit.css -->

function addEvent(elm, evType, fn, useCapture)
{
      // addEvent
      // cross-browser event handling for IE5+,  NS6 and Mozilla
      // By Scott Andrew
      if (elm.addEventListener)
      {
            elm.addEventListener(evType, fn, useCapture);
             return true;
      }
      else if (elm.attachEvent)
      {
            var r = elm.attachEvent("on"+evType, fn);
            return r;
      }
      else
      {
               // alert("Handler could not be added");
        }
}

function removeEvent(elm, evType, fn, useCapture)
{
      // removeEvent
      // cross-browser event handling for IE5+,  NS6 and Mozilla
      // By Scott Andrew
      if (elm.removeEventListener)
      {
                elm.removeEventListener(evType, fn, useCapture);
                return true;
        }
      else if (elm.detatchEvent)
      {
                var r = elm.detachEvent("on"+evType, fn);
                return r;
        }
      else
      {
             //  alert("Handler could not be removed");
        }
}



function menu_init()
{
      // Find all divTag with class menubar and assign functions to A and IMG tags
      if (!document.getElementsByTagName)
      {
      return;
      }
      var divTag = document.getElementsByTagName("div");
      for (di=0;di<divTag.length;di++)
      {
            var thisDiv = divTag[di];
            if (((' '+thisDiv.className+' ').indexOf("menuBar") != -1) && (thisDiv.id))
            {
                  menu_makemenu(thisDiv);
            }
            else
            {
                    if (((' '+thisDiv.className+' ').indexOf("menu") != -1) && (thisDiv.id))
                   {
                   menu_makesubmenu(thisDiv);
                   }
            }
      }
}

function menu_makemenu(menu)
{
      var anchors = menu.getElementsByTagName("a");
      for (i = 0; i < anchors.length; i++)
      {
            var thisAnchor = anchors[i];
            if (((' '+thisAnchor.className+' ').indexOf("menuButton") != -1) && (thisAnchor.id))
            {
                  var images = thisAnchor.getElementsByTagName("img");
                  for (ti = 0; ti < images.length; ti++)
                  {
                        var thisImage = images[ti];
                        if ((thisImage.src) && (thisAnchor.id))
                        {
                              thisImage.style.width = (thisImage.width);
                              thisImage.style.height = (thisImage.height + 0.1);
                        }
                  }      
                  if (thisAnchor.id)
                  {
                        thisAnchor.onmouseover=function(event){
                        buttonMouseover(event, this.id+"menu");
                        }
                        thisAnchor.onmouseout=function(event){
                        buttonOrMenuMouseout(event);
                        }
                  }
            }
      }
}


function menu_makesubmenu(menu)
{
      if ((!((' '+menu.id+' ').indexOf("submenu") != -1)))
      {      
                      menu.onmouseover=function(event){
                   menuMouseover(event);
                   }
      }
      var anchors = menu.getElementsByTagName("a");
      tagged = 0;
      for (si = 0; si < anchors.length; si++)
      {
            var thisAnchor = anchors[si];
            if (((' '+thisAnchor.className+' ').indexOf("menuItem") != -1) && (menu.id))
            {
                  if(thisAnchor.id )
                  {
                        var spans = thisAnchor.getElementsByTagName("span");
                        for (sti = 0; sti < spans.length; sti++)
                        {
                              var thisSpan = spans[sti];
                              if (((' '+thisSpan.className+' ').indexOf("menuItemText") != -1) && (thisAnchor.id))
                              {
                              
                                       thisAnchor.onmouseover=function(event){
                                    menuItemMouseover(event, this.id+"menu");
                                    }
                                    sti = spans.length;
                              }
                        }
                  }      

            }
      }
}



Open http://www.lancefrisbee.com/testing/dropdown in Firefox to see how it should act, then again in IE - and you'll see what I'm talking about.

Any help would be GREATLY appreciated and rewarded in kind.

Thank you,

Lance



Avatar of Zvonko
Zvonko
Flag of North Macedonia image

At what point does the error occure in IE?
I see same behavior in IE and FireFox.
Avatar of Lance_Frisbee

ASKER

Is it WORKING in both, or BROKE in both?

For me, it's on mouseover in IE, not on page load. In MAC IE 5.2, the dropdowns don't work at all. I'm starting to care less and less about MAC IE... Does it EVER work? :)

Thanks for the fast reply. I have to leave the office for a 4:30pm PST meeting, but I'll return afterwards to straighten this out and address any replies/advice I may have here.

Thanks again.

Lance
ASKER CERTIFIED SOLUTION
Avatar of Zvonko
Zvonko
Flag of North Macedonia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of smaccari
smaccari

Zvonko, i did not know about this tool it's great ;o) Thanks for this link!
(soory to be out of subject though ;o)
Lance,
If you are tring to pinpoint the location of a javascript error you can try out
http://jsbughunter.com
its a service I have (currently at no charge), you will have to add a piece of code to your page
and then you will be able to see reports of javascript errors that people that surf your page get.

SnowFlake.
So everyone is seeing this correctly with no errors? If so... I can live with it being stupid on just my machine... I don't know why that would be. (Wait yes I do... the computers here at work are outdated.) But still, if it is working correctly in IE for PC, that's my main concern. I would just do an alternate-styled navigation, but this client has 50+ pages, theres really no way around a dropdown menu.

Thanks to Zvonko and Snowflake for the page resources... I will check those out.

If any people reading this thread can let me know if this is working in both IE and Firefox with no Javascript errors, that would be excellent.

http://www.lancefrisbee.com/test/dropdown is the URL once again.

I've already heard from Zvonko (thanks)

Thanks again everyone for your input!

Lance
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thank you everyone for your replies... it ended up not being an issue as I am on an incredibly outdated machine. Enjoy the points as I was very slow in response. My apologies!

Thanks again,

Lance