views:

306

answers:

2

I already started this in javascript so I don't want to use jquery but can somejavascript expert look at my code and tell me what I'm doing wrong and or right? Let me tell you what I am trying to accomplish here. I have a menu that consists of four buttons and when you hover over them, they change color and then underneath a heading image is displayed when you hover over the heading, the button should go back to its original color, and then underneath the heading appears another image that contains some text. For the most part the code works ok except in Firefox sometimes the headings shift around and I am assuming that this is because when visible the text image doesn't exist, so the heading falls to where the text would be, I don't have this problem in IE. The biggest problem is the onmouseout. I don't want the original button to go back to the color right away because I need time to be able to roll over the heading to show the text, so I was trying to use a setTimeout function to pause for a few seconds but it didn't work.

Here's the code:

window.onload = rollover;
function rollover()
var images = document.getElementsByTagName("img"); // Get all the images in the document
var roll = new RegExp("roll");
var preload = [];
var fileLoc = "images/rollovers/";
for ( var i=0; i<images.length; i++) 
{
 if (images[i].id.match(roll)) // Loop through all the images in document and look for match on 'roll'
 {
  preload[i] = new Image();
  preload[i].src = fileLoc + images[i].id + "_over.gif"; // Preload the _overs into an array.
  images[i].onmouseover = function()  // Add a mouseover event to image
  {
   this.src = fileLoc + this.id + "_over.gif"; // When rolled over, this file now equals the _over image
   var currentButton = this.id; // Grab the id of the current image
   var imageHeader = document.getElementById("current_title"); //Grab all images that are titled 'current_title'
   var newHeaderImage = new Image();
   newHeaderImage.src = fileLoc + currentButton + "_header.gif"; // Create new image and store _Header image inside
   newHeaderImage.id = currentButton + "_header"; //New id for new image is file + headerId
   imageHeader.src = newHeaderImage.src;
   imageHeader.height = newHeaderImage.height; // Assign header image id to currect location
   imageHeader.width = newHeaderImage.width;
   imageHeader.style.visibility = "visible";
   imageHeader.onmouseover = function() // Attach mouse event for header image
   {
    var imageText = document.getElementById("button_text");
    var newTextImage = new Image();
    newTextImage.src = fileLoc + currentButton + "_text.gif";
    imageText.src = newTextImage.src;
    imageText.height = newTextImage.height;
    imageText.width = newTextImage.width;
    imageText.style.visibility = "visible";

   }


  }
  //images[i].onmouseout = setTimeout(mouseOut(fileLoc, this.id),3000);
 }
    }

}

/*function mouseOut(fileLoc, curButton)

{

var titleImg = document.getElementById("current_title");
var imgButton = curButton;
this.src = fileLoc + imgButton + "_org.gif";

titleImg.style.visibility = "hidden";

}*/

+4  A: 

Okay, biting the bullet, let's see how this munges my rep :-).

This is not the answer you want but STOP.

Back up. Download a JS library (such as jQuery), then restart.

Your life will be easier, you'll have more time to spend with family and friends, and you'll be less grumpy whenever you have to ask more questions here (and believe me, that will be less often :-).

The very fact that you have to ask the advice of a JS expert should indicate to you that you're going about it the wrong way. Trust me, all the JS experts are already using a JS library because they've already faced all the nigglies like cross-browser compatibility and other such painful issues.

paxdiablo
Using a library is not necessarily going to help here. A library is just going to enable john to write his script in fewer lines. I can't see any JavaScript browser incompatibilities here. What I do see is a confused purpose. What exactly is the goal?
meouw
John, please post a simple version of your markup. This will help people see what you are trying to do and perhaps help you.
meouw
meouw, "code works ok except in Firefox" and "don't have this problem in IE" sure sounds like a cross-browser issue to me :-).
paxdiablo
A: 

Ok, here's a script that works (at least in ie and firefox) that doesn't use libraries.
Using a library would obviously make this code a lot more succinct.

window.onload = createRollover;

function createRollover() {
    var button;
    var imgPath = 'img/';
    var container = document.getElementById( 'ro_container' );
    var buttonContainer = document.getElementById( 'ro_buttons' );
    var headerContainer = document.getElementById( 'ro_header' );
    var textContainer = document.getElementById( 'ro_text' );
    var buttons = buttonContainer.getElementsByTagName( 'img' );

    container.onmouseout = rollOut;

    // set up the element hierarchy
    for( var i = 0; i < buttons.length; i++ ) {
        button = buttons[i];
        button.onmouseover = buttonRollover;
        button.up =  document.createElement( 'img' );
        button.up.src = imgPath+button.id+'.gif';
        button.over =  document.createElement( 'img' );
        button.over.src = imgPath+button.id+'_over.gif';
        button.header = document.createElement( 'img' );
        button.header.src = imgPath+button.id+'_header.gif';
        button.header.onmouseover = headerRollover;
        button.header.text =  document.createElement( 'img' );
        button.header.text.src = imgPath+button.id+'_text.gif';
    }

    function buttonRollover() {

        //do nothing if this button is already active
        if( this.src == this.over.src ) return;

        //reset all the buttons and set this one to over
        for( var i = 0; i < buttons.length; i++ ) {
            buttons[i].src = buttons[i].up.src;
        }
        this.src = this.over.src;

        //see what's in the header div and do the header thing
        var h = headerContainer.getElementsByTagName( 'img' );
        if( h.length > 0 ) {
            headerContainer.replaceChild( this.header, h[0] );
        } else {
            headerContainer.appendChild( this.header );
        }
        //clear the text div
        textContainer.innerHTML = '';
    }

    function headerRollover() {
        //see what's in the text div and do the thing
        var t = textContainer.getElementsByTagName( 'img' );
        if( t.length > 0 ) {
            textContainer.replaceChild( this.text, t[0] );
        } else {
            textContainer.appendChild( this.text );
        }
    }

    function rollOut( e ) {
        //mouseouts take a bit of work
        //that's one of the reasons why we like libraries
        e = e || window.event;
        var onto = e.relatedTarget || e.toElement;
        // we'll cancel this event if we've rolled on to an element
        // that is a child of this one.
        // traverse up the tree looking for 'this' or the document
        while( onto != this && onto != document ) {
            onto = onto.parentNode;
        }
        if( onto == this ) {
            //false alarm, it was a child of 'this'
            return; 
        }
        // reset
        for( var i = 0; i < buttons.length; i++ ) {
            buttons[i].src = buttons[i].up.src;
        }
        headerContainer.innerHTML = '';
        textContainer.innerHTML = '';
    }
}

And the markup

<div id="ro_container">
    <div id="ro_buttons">
        <img src="img/but1.gif" id="but1"/>
        <img src="img/but2.gif" id="but2"/>
        <img src="img/but3.gif" id="but3"/>
    </div>
    <div id="ro_header"></div>
    <div id="ro_text"></div>
</div>

I used the same image naming system you did (I think):

but1.gif, but1_over.gif, but1_header.gif, but1_text.gif  
but2.gif....

Hope this helps

meouw