Hover Images Work in FF & NN, but not IE

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • RMWChaos
    New Member
    • Oct 2007
    • 137

    Hover Images Work in FF & NN, but not IE

    I have four pieces of code to automatically build my navigation buttons and choose which page to load: 1) a hover script, which swaps the images onmouseover and onmouseout, 2) a DOM loader, which automatically creates and removes DOM elements, 3) a nav script, which builds the nav buttons depending on the page being viewed, and 4) a page loader script that clears out the content area and inserts the newly selected content.

    What should happen is this: NAVInit selects the images to use depending on the page being viewed, and submits them to the DOMLoader to remove the old elements and create the new elements. Part of the DOM creation process includes the attributes 'onmouseover=' and 'onmouseout=', which intiate the HOVERLoader script to swap out images, and an 'onclick=' attribute, which calls the PAGELoader script to load the new content and reset the nav buttons.

    This all works in FF2.2.08 and NN9, but the onmouseover, onmouseout, and onclick do not work in IE7 (dang Microsoft again!). IE7 does not give any errors, however.

    The strange thing is, I know that these three attributes all work in IE7 when the DOM Elements are created manually. So, what is going on here? The only thing that I can think of is in the way I create my strings. You'll see in the mouseOver and mouseOut vars I use in the NAVLoader script.

    Not sure how much of the code you want to see, but I will try to include only the relevant parts. Because there is so much code here, I will add them in separate replies to this post.

    Thanks in advance for your feedback.
  • RMWChaos
    New Member
    • Oct 2007
    • 137

    #2
    HOVERLoader script:

    [code=javascript]
    function mouseHover(imag ePath, imageId)

    {

    var image = document.getEle mentById(imageI d);

    image.src = imagePath;

    };
    [/code]

    Simple enough.

    Comment

    • RMWChaos
      New Member
      • Oct 2007
      • 137

      #3
      DOMLoader script:

      [code=javascript]
      function removeDOM(id) // Remove DOM Elements Function //

      {

      var idExist = document.getEle mentById(id);

      if (idExist) // Delete child node. //

      {

      idExist.parentN ode.removeChild (idExist);

      }

      else // Node does not exist, exit //

      {

      return;

      };

      };

      function removeAllChildN odes(node) // Remove All Child Nodes from a Parent Node //

      {

      var parentExist = document.getEle mentById(node);

      if (parentExist && parentExist.has ChildNodes())

      {

      while (parentExist.ch ildNodes.length > 0) // Remove the Child Nodes while the Parent Node has Them //

      {

      parentExist.rem oveChild(parent Exist.firstChil d);

      };

      }

      else // Parent does not exist or does not have child nodes //

      {

      return;

      };

      };

      function createDOM(attri b) // Create DOM Elements Function //

      {

      var defaultAttribs =

      {

      'dom' : 'div',

      'parent' : 'body'

      };

      for (var index in defaultAttribs) // Assign listed default attribs to 'undefined' attribs //

      {

      if(typeof attrib[index] == 'undefined')

      {

      attrib[index] = defaultAttribs[index];

      };

      };

      var idExist = document.getEle mentById(attrib .id);

      var createElement = document.create Element(attrib. dom);

      var parentExist = document.getEle mentById(attrib .parent);

      if (typeof attrib.id == 'undefined') // If 'id' is 'undefined', alert user and exit //

      {

      alert("There is no 'id' to create the node.");

      return;

      };

      if (attrib.dom == 'text') // Change createElement to createTextNode & assign parentExist to 'attrib.id' //

      {

      createElement = document.create TextNode(attrib .text);

      parentExist = document.getEle mentById(attrib .id);

      }

      else if (attrib.dom == 'script') // Assign parentExist to <head> //

      {

      parentExist = document.getEle mentsByTagName( 'HEAD')[0];

      };

      if (attrib.parent == 'body') // Assign parentExist to <body> //

      {

      if (document.getEl ementsByTagName ) // W3C HTML DOM Level 1+ Standard (preferred method) //

      {

      parentExist = document.getEle mentsByTagName( 'BODY')[0];

      }

      else if (document.body) // Microsoft Implementation Shortcut //

      {

      parentExist = document.body;

      }

      else if (document.layer s) // Netscape Navigator 4+ //

      {

      parentExist = document.tags['BODY'];

      }

      else // Alert user //

      {

      alert("Browser does not support known means to access <body>.");

      };

      }

      else if (!parentExist) // Create missing parent or target node first //

      {

      var body = document.getEle mentsByTagName( 'BODY')[0];

      var createParent = document.create Element('div');

      createParent.id = attrib.parent;

      body.appendChil d(createParent) ;

      if (attrib.dom != 'text')

      {

      parentExist = document.getEle mentById(attrib .parent);

      };

      };

      if (parentExist) // Set attribs and create element //

      {

      if (attrib.dom != 'text')

      {

      createElement = document.create Element(attrib. dom);

      for (index in attrib)

      {

      createElement.s etAttribute(ind ex, attrib[index]);

      };

      };

      parentExist.app endChild(create Element);

      };

      };
      [/code]

      Longer, but not really all that complex. Just a whole lot of 'if' and 'if...else' statements to cover as many possibilities as possible.

      Comment

      • RMWChaos
        New Member
        • Oct 2007
        • 137

        #4
        NAVLoader script:

        [code=javascript]
        var page = new Array("home", "guides", "specs", "links", "join", "news", "forum", "kills", "corp", "members");

        var pageSelected = "home";

        function navInit()

        {

        for (var x in page)

        {

        var imageId = "divnav" + page[x];

        var divNavExist = document.getEle mentById(imageI d);

        if (divNavExist)

        {

        removeDOM(image Id);

        };

        if (pageSelected == page[x])

        {

        var pathSelected = "../images/selected" + page[x] + ".jpg";

        var alreadyHere = 'NavCon indicates that you are already here.';

        createDOM({

        'dom' : 'img',

        'id' : imageId,

        'alt' : alreadyHere,

        'title' : alreadyHere,

        'src' : pathSelected,

        'onclick' : 'alert("Is your NavCon malfunctioning? You are already here!")'

        });

        }

        else if (pageSelected != page[x])

        {

        var altName = "Jump to " + page[x] + " sector";

        var pathHover = "../images/hover" + page[x] + ".jpg";

        var pathDefault = "../images/default" + page[x] + ".jpg";

        var mouseOver = "mouseHover ('" + pathHover + "', '" + imageId + "')";

        var mouseOut = "mouseHover ('" + pathDefault + "', '" + imageId + "')";

        var loadPage = "pageLoader (" + x + ")";

        createDOM({

        'dom' : 'img',

        'id' : imageId,

        'alt' : altName.capital ize(),

        'title' : altName.capital ize(),

        'src' : pathDefault,

        'onmouseover' : mouseOver,

        'onmouseout' : mouseOut,

        'onclick' : loadPage

        });

        };

        };

        };

        [/code]

        A little more complex, but not too bad.

        Comment

        • RMWChaos
          New Member
          • Oct 2007
          • 137

          #5
          PAGELoader script:

          [code=javascript]
          function pageLoader(page Num) // Initiate Page Selection

          {

          pageSelected = page[pageNum]; // Set var to the new page

          navInit(); // reset nav buttons using new pageSelected var

          removeAllChildN odes('content') ; // clear the content area

          switch(pageNum) // load the new content

          {

          // several different cases depending on the nav button selected

          };

          [/code]

          I shortened this one by not including all the switch cases.

          Comment

          • Dasty
            Recognized Expert New Member
            • Nov 2007
            • 101

            #6
            Quite a pain to read the whole stuff. But your problem is in how you assign event handlers to new created objects. No, IE has no problem with events on new created objects. After I digged your code i found that you basically are doing it like this:

            [PHP]newElement.setA ttribute('oncli ck','what to do in string format');
            [/PHP]
            You can not assign strings as event handler. I was even surprised that FF accepted it (and evalued it by default). The problem is, that you can assign just functions (refs). So to fast fix, you can do this:

            [PHP]//instead:
            newElement.setA ttribute('oncli ck','what to do in string format');
            //do this:
            newElement.setA ttribute('oncli ck',new Function('what to do in string format'));[/PHP]

            (it will create anonymous function for each object)

            Comment

            • RMWChaos
              New Member
              • Oct 2007
              • 137

              #7
              Dasty,

              Thank you very much for your time reviewing my code--I know it couldn't have been easy--and for your suggested fix. All my code is modular so that I don't have repeat multiple lines in each script. For instance, several different scripts use the DOMLoader and HOVERLoader scripts to generate content.

              I thought the problem might be with my mouseOver, mouseOut, and pageLoader vars, just couldn't figure out what it was. I was under the impression that the string would be converted before DOMLoader added it as an attribute; guess not.

              You are basically saying I should do this:

              [code=javascript]
              //instead of this
              onmouseover : mouseOver,

              //do this
              onmouseover : new Function(mouseO ver),
              [/code]

              That is a quick fix. Let me give it a try and I will report back the results.

              Comment

              • RMWChaos
                New Member
                • Oct 2007
                • 137

                #8
                Dasty,

                That worked great in IE, but now FF and NN don't work. I did the fix two ways:

                [code=javascript]
                //first like this
                var mouseOver = new Function ("mouseHover ('" + pathHover + "', '" + imageId + "')");
                onmousover : mouseOver

                //then like this
                var mouseOver = "mouseHover ('" + pathHover + "', '" + imageId + "')";
                onmousover : new Function (mouseOver)
                [/code]

                I suppose that I could include a browser check to see if it is IE, then include "new Function" in the mouseOver, mouseOut, and loadPage vars. That just seems a bit clunky to me. Perhaps there is another way.

                Comment

                • RMWChaos
                  New Member
                  • Oct 2007
                  • 137

                  #9
                  Well, this is the code I ended up going with for now:

                  [code=javascript]
                  // This works only for MSIE
                  if (navigator.appN ame == "Microsoft Internet Explorer")
                  {
                  var mouseOver = new Function("mouse Hover('" + pathHover + "', '" + imageId + "')");
                  var mouseOut = new Function("mouse Hover('" + pathDefault + "', '" + imageId + "')");
                  var loadPage = new Function("pageL oader(" + x + ")");
                  }
                  // This works for Mozilla, FF, NN9, etc.
                  else
                  }
                  var mouseOver = "mouseHover ('" + pathHover + "', '" + imageId + "')";
                  var mouseOut = "mouseHover ('" + pathDefault + "', '" + imageId + "')";
                  var loadPage = "pageLoader (" + x + ")";
                  };
                  [/code]

                  It works, but I would really like to know why one set of variables does not work for all browsers.

                  Perhaps the problem I should be working on instead is a better way to create my onmouseover, onmouseout, and onclick attributes.

                  I'm going for modularity and eliminating redundancy; so having to rewrite these vars twice really annoys me. :-|

                  Comment

                  • Dasty
                    Recognized Expert New Member
                    • Nov 2007
                    • 101

                    #10
                    Originally posted by RMWChaos
                    Well, this is the code I ended up going with for now:

                    [code=javascript]
                    // This works only for MSIE
                    if (navigator.appN ame == "Microsoft Internet Explorer")
                    {
                    var mouseOver = new Function("mouse Hover('" + pathHover + "', '" + imageId + "')");
                    var mouseOut = new Function("mouse Hover('" + pathDefault + "', '" + imageId + "')");
                    var loadPage = new Function("pageL oader(" + x + ")");
                    }
                    // This works for Mozilla, FF, NN9, etc.
                    else
                    }
                    var mouseOver = "mouseHover ('" + pathHover + "', '" + imageId + "')";
                    var mouseOut = "mouseHover ('" + pathDefault + "', '" + imageId + "')";
                    var loadPage = "pageLoader (" + x + ")";
                    };
                    [/code]

                    It works, but I would really like to know why one set of variables does not work for all browsers.

                    Perhaps the problem I should be working on instead is a better way to create my onmouseover, onmouseout, and onclick attributes.

                    I'm going for modularity and eliminating redundancy; so having to rewrite these vars twice really annoys me. :-|
                    No way. Do yourself a favor and forget that something like navigator.appNa me even exists. Nobody forces browser to identify itself right. Especially minor browsers are happy to identify themselves as one of the major browsers. So parsing appName is not the way - never. (google javascript browser identification and you'll find some more useful pseudo - solutions)

                    But back to your problem:

                    To be honest I am quite surprised of setAttribute behavior. I always thought that:

                    object[parameter_name] = value

                    is equivalent with:

                    object.setAttri bute(parameter_ name, value);

                    but obviously it is not. But I know, that obj.onclick = value; is working fine in all browsers. So try this (can not test it so check for typos):
                    [PHP]
                    for (index in attrib)
                    {
                    createElement.s etAttribute(ind ex, attrib[index]);
                    };
                    [/PHP]

                    change to:
                    [PHP]
                    for (index in attrib)
                    {
                    createElement[index] = attrib[index];
                    };
                    [/PHP]

                    It should work with events. (And ofc, use that new Function() for event handlers) Please run some tests and let us know.

                    Comment

                    • gits
                      Recognized Expert Moderator Expert
                      • May 2007
                      • 5388

                      #11
                      Originally posted by Dasty
                      I always thought that:

                      [CODE=javascript]object[parameter_name] = value;
                      [/CODE]
                      is equivalent with:

                      [CODE=javascript]object.setAttri bute(parameter_ name, value);[/CODE]

                      but obviously it is not. But I know, that obj.onclick = value; is working fine in all browsers.
                      in some cases that seems to be equivalent ... but simply try it with the 'readonly' or 'disabled' attributes. there is a difference between setting an objects javascript-property (your first code) and setting an attribute of the dom-node (the second variation) ... in case you set the attribute 'readonly' with setAttribute(); you HAVE to remove it to make the node to accept input again ... we have to use removeAttribute () for that. we cannot set the attribute to false with set attribute here. but you may set the property node.readonly = false; BUT: with that we are mixing up the two ways ... and it is good practice to use ONE way to avoid confusion especially in case you have to debug your code later on :)

                      kind regards

                      Comment

                      • Dasty
                        Recognized Expert New Member
                        • Nov 2007
                        • 101

                        #12
                        Originally posted by gits
                        in some cases that seems to be equivalent ... but simply try it with the 'readonly' or 'disabled' attributes. there is a difference between setting an objects javascript-property (your first code) and setting an attribute of the dom-node (the second variation) ... in case you set the attribute 'readonly' with setAttribute(); you HAVE to remove it to make the node to accept input again ... we have to use removeAttribute () for that. we cannot set the attribute to false with set attribute here. but you may set the property node.readonly = false; BUT: with that we are mixing up the two ways ... and it is good practice to use ONE way to avoid confusion especially in case you have to debug your code later on :)

                        kind regards
                        Good to know, did not know that (thank you). Makes sense now (i just thought that removeAttribute would be the same as "delete obj.property" ... but you can not delete obj.readOnly for example as you said). But while he can not use setAttribute for assigning event handlers and he can not assign all properties by just simple JS property assignment, then he has to divide events and attributes and work with them in different ways.

                        Comment

                        • RMWChaos
                          New Member
                          • Oct 2007
                          • 137

                          #13
                          [QUOTE=Dasty]change to:
                          [PHP]
                          for (index in attrib)
                          {
                          createElement[index] = attrib[index];
                          };
                          [/PHP]

                          Aha! You just solved a problem I was having that forced me to use the first method. I couldn't figure out how to set the index attribute because I had forgotten that .index is equiv to [index], and .index would not work. Now I can change that code and get around that problem.

                          I'll try it out and get back to you.

                          Comment

                          • RMWChaos
                            New Member
                            • Oct 2007
                            • 137

                            #14
                            Alright, that worked in all browsers! Setting the dom-node attribute is exactly what I wanted to do in the first place (ergo "DOMLoader" ) ;-)).

                            Thank you for your help!

                            Comment

                            Working...