Search code examples
javascriptrollovers

Javascript help rollover is a rollover


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

}*/


Solution

  • 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