Search code examples
javascripthtmlcsstoggleparent

Toggle class of parent element onrollover


I have a navigation bar, and I want the background image of the parent element to change when the user rolls over a link in the navigation bar. I know there's a way to do this with some simple javascript, but I am less than amateur at JS.

Here is the html:

<div class="image">
<ul>
<li><a onmouseover="toggleElementOne()" href="#">Roll over to Change Parent Div class</a></li>
<li>Second Link</li>
<li>etc</li>
</ul>
</div>

Here is the css:

<style>
.image {
    background:url(image1.png);
    height:500px;
    width:1000px;
    display:block;
}

.image-two {
    background:url(image2.png);
    height:500px;
    width:1000px;
    display:block;
}
</style>

Ideally, I would like to have a different background image for each link in the navigation bar, but I figure I could just make different functions for each button. Once I know how to get one function to work, the rest should be easy.

The javascript I have right now is this:

<script>
function toggleElementOne() {

    document.getElementsByClassName("image").className = "image-two";

}
</script>

The idea is that this function (which is activated by an onmouseover event in the link) will find the parent element with the class "image" and change it to the class "image-two." What I'm also afraid will happen is that once the user rolls off the link, the image will stay, so I will also need a onmouseout event to return the background image to it's original state.

How do I do it???


Solution

  • CSS could do this quite easily if you only want to change the background of the actual image you are hovering. But if I understand your question correctly, you would like a general background image to change depending on which child element the user hovers over.

    You can in fact do this with not-so-complex Javascript. You can even do this using only two functions, for all the menu items; but there's a few things you'll have to change first.

    The way you are now using getElementsByClassName is not correct. You can use the class image to use it in CSS as .image, but to simply select just one item in Javascript, you'll have to use id="image" and then use document.getElementById. You can still use the class for CSS, that's fine. I'll call it "imageDefault" later on, to distinguish it from the id.

    Ok, now the Javascript. You do indeed need a onmouseover and an onmouseout on your menu items. But every menu item can use the same functions for those, only passing different arguments. These arguments could refer to the className you want to change the parent element to in order to change the image.

    Example:

    <div id="image" class="imageDefault">
    <ul>
    <li><a onmouseover="mOver('imageA')" onmouseout="mOut()" href="#">Roll over to Change Parent Div class</a></li>
    <li><a onmouseover="mOver('imageB')" onmouseout="mOut()" href="#">Second Link</a></li>
    <li><a onmouseover="mOver('imageC')" onmouseout="mOut()" href="#">etc</a></li>
    </ul>
    </div>
    

    In this case, all the tags are calling mOver and mOut when the mouseover and mouseout events are triggered, but they pass a different string to mOver (I'm using short function names in this example for readability in the long HTML lines; feel free to rename, of course).

    Javascript can pick up these arguments and directly set them as className like this:

    function mOver(newName)
    {
        document.getElementById("image").className = newName
    }
    function mOut()
    {
        document.getElementById("image").className = "imageDefault"
    }
    

    Notice how mOut doesn't need the newName argument as it will always default back to "imageDefault".

    And finally, the CSS would look something like this:

    <style>
    .defaultImage {
        background:url(image1.png);
        height:500px;
        width:1000px;
        display:block;
    }
    
    .imageA {
        background:url(image2.png);
        height:500px;
        width:1000px;
        display:block;
    }
    
    .imageB {
        background:url(image3.png);
        height:500px;
        width:1000px;
        display:block;
    }
    
    .imageC {
        background:url(image4.png);
        height:500px;
        width:1000px;
        display:block;
    }
    </style>
    

    Which of course can be simplified to:

    <style>
    .defaultImage, .imageA, .imageB, .imageC {
        height:500px;
        width:1000px;
        display:block;
    }
    
    .defaultImage { background:url(image1.png); }
    .imageA { background:url(image2.png); }
    .imageB { background:url(image3.png); }
    .imageC { background:url(image4.png); }
    </style>
    

    There are many ways to do these kind of things. This method basically just builds on what you had already. I hope it helps!