3

Alright I'll try to make this as clear as possible. Be kind, I'm very new to JavaScript.

I have a div container called nav, that holds five navigation buttons and they're all floated side by side. Under that container I have a div container called underbar, which is just a solid color bar under each nav element. When someone hovers on a navigation div, the color of the underbar for that element changes. Right now, I have what you see below, and it is working correctly.

<div id="container">
<div id="nav">
<div id="one" onmouseover="document.getElementById('ubone').style.background='gray'" onmouseout="document.getElementById('ubone').style.background='white';"><a href="one.html">One</a>    </div><!-- end of first nav -->
<div id="two" onmouseover="document.getElementById('ubtwo').style.background='gray'" onmouseout="document.getElementById('ubtwo').style.background='white';"><a href="two.html">Two</div><!-- end of second nav -->
<div id="three" onmouseover="document.getElementById('ubthree').style.background='gray'" onmouseout="document.getElementById('ubthree').style.background='white';"><a href="three.html">Three</div><!-- end of third nav -->
<div id="four" onmouseover="document.getElementById('ubfour').style.background='gray'" onmouseout="document.getElementById('ubfour').style.background='white';"><a href="four.html">Four</div><!-- end of fourth nav -->
<div id="five" onmouseover="document.getElementById('ubfive').style.background='gray'" onmouseout="document.getElementById('ubfive').style.background='white';"><a href="five.html">Five</div><!-- end of fifth nav -->
</div><!-- end of nav div -->

<div id="underbar">
<div id="ubone"></div><!-- end of first nav -->
<div id="ubtwo"></div><!-- end of second nav -->
<div id="ubthree"></div><!-- end of third nav -->
<div id="ubfour"></div><!-- end of fourth nav -->
<div id="ubfive"></div><!-- end of fifth nav -->
</div><!-- end of underbar div -->

</div><!-- end of container div-->

This works fine, yes. However, I absolutely hate the thought of having to go in and edit these one by one, by one. What's the easiest way to simplify this using a javascript function / jquery (preferably) while being able to do it for multiple div ids? Thoughts / opinions? Thanks!

Sparky
  • 98,165
  • 25
  • 199
  • 285
user1504591
  • 95
  • 2
  • 13

6 Answers6

4

This targets the div's that are a direct child of your #nav element.

$(document).ready(function(){
    $('#nav > div').mouseover(function(){

        $('#ub' + this.id).css('backgroundColor', 'grey');

    }).mouseout(function(){

        $('#ub' + this.id).css('backgroundColor', 'white');

    });
});

If you want a pure Javascript solution then try this:

window.onload = function(){

    var elements = document.querySelectorAll('#nav > div');

    for(var i=0; i<elements.length; i++)
    {
        elements[i].onmouseover = function(){
            document.querySelector('#ub' + this.id).style.backgroundColor = 'grey';
        };
        elements[i].onmouseout = function(){
            document.querySelector('#ub' + this.id).style.backgroundColor = 'white';
        };
    }
}
MrCode
  • 63,975
  • 10
  • 90
  • 112
  • 1
    jQuery `.mouseenter()` and `.mouseleave()` would work better. Or `.hover()` which combines them. – Sparky Dec 03 '12 at 17:36
  • How do I go about applying this code to the divs? I linked the jquery hosted by google. I also created a mouse-events.js javascript page with the code above and linked it to my html page. I'm just not sure what else needs to be done? TYVM! Very clean reply, and exactly what I was looking for. – user1504591 Dec 03 '12 at 17:42
  • 1
    You don't _apply_ to the `div`'s... this code already _targets_ the `div`'s. – Sparky Dec 03 '12 at 17:43
  • 1
    @user1504591 I edited the answer with a pure javascript solution as well. Have a look how I have used document.ready and window.onload. Using those, the code will execute when the page loads. For the jQuery, include the library and throw my code anywhere on the page. For the pure Javascript, just throw the code anywhere on the page (within – MrCode Dec 03 '12 at 17:47
  • Gotcha... in that case. Not working? lol Or atleast for me. Again, I linked the jquery, linked the js page I made from the above code, and I remove the onmouseover / mouseout settings from the html page, stripping it to just the div id and the text inside that div. Wonder what I'm doing wrong.. herm. Will keep checking into this. Perhaps I need to alter a CSS element? Thanks – user1504591 Dec 03 '12 at 17:49
  • Try to get it working with the code on the same page (to rule out the include). Post your full code to the question and I'll take a look. Also keep an eye on the error console for messsages to indicate what's wrong. – MrCode Dec 03 '12 at 17:51
  • @user1504591 you need to add the document.ready(function(.. wrapper that I added to my code. Your code won't work because the elements don't exist at the time that it executes. If you add the document.ready wrapper, it executes on load instead. – MrCode Dec 03 '12 at 18:04
  • @user1504591, if you can't get this working, glance at the jsFiddle demo in my answer to see it in action. – Sparky Dec 03 '12 at 18:10
  • @MrCode Working perfectly now, TYVM! Exactly what I was looking for. – user1504591 Dec 03 '12 at 18:11
2
$(".myClass").mouseover(function() {
    $('#ub' + this.id).css('background-color', 'gray');
  }).mouseout(function(){
     $('#ub' + this.id).css('background-color', 'white');
  });
Gutenberg
  • 992
  • 1
  • 7
  • 17
2

Here's an answer with a working DEMO:

http://jsfiddle.net/AVk6k/1/

And using jQuery .hover() instead. .hover() is like a shorthand that combines .mouseenter() and .mouseleave() into one handler.

IMHO, mouseenter and mouseleave are much more reliable than mouseover and mouseout, which tend to flicker.

jQuery:

$(document).ready(function() {
    $('#nav div').hover(
    function() {
        $('#ub' + this.id).css('background-color', 'grey');
    }, function() {
        $('#ub' + this.id).css('background-color', 'white');
    });
});​

You also had some missing </a> tags.

HTML:

<div id="container">
    <div id="nav">
        <div id="one"><a href="one.html">One</a></div><!-- end of first nav -->
        <div id="two"><a href="two.html">Two</a></div><!-- end of second nav -->
        <div id="three"><a href="three.html">Three</a></div><!-- end of third nav -->
        <div id="four"><a href="four.html">Four</a></div><!-- end of fourth nav -->
        <div id="five"><a href="five.html">Five</a></div><!-- end of fifth nav -->
    </div><!-- end of nav div -->
    <div id="underbar"> 
        <div id="ubone"></div><!-- end of first nav -->
        <div id="ubtwo"></div><!-- end of second nav -->
        <div id="ubthree"></div><!-- end of third nav -->
        <div id="ubfour"></div><!-- end of fourth nav -->
        <div id="ubfive"></div><!-- end of fifth nav -->   
    </div><!-- end of underbar div -->   
</div><!-- end of container div-->​
Sparky
  • 98,165
  • 25
  • 199
  • 285
  • Although I have a working example now using MrCodes script. I'm interested in trying yours because of the .hover vs the mouseover and mouseout. I'm pretty much pulling my hair out because for some reason something that should be so easy to recreate from your JS fiddle is not yielding the same results. My process? Link to jquery with google in the head i.e then copy the html and save as "test.html". create Test.css and link your css from the test.html page. Create a page and save as test.js, and copy / paste js. – user1504591 Dec 03 '12 at 18:49
  • @user1504591, I'm not understanding where you could be going wrong. The HTML is exactly yours except I added the missing `` tags and removed the inline JS. Ignore my CSS; I added that because yours was missing. You can see the jsFiddle is working... so just look at the JavaScript section and apply the minor changes to your code. Then use your browser's developer console to see if you get any errors. – Sparky Dec 03 '12 at 20:12
  • Working now. I'm unable to tell you why or what I did, as I just came back to it today. Why couldn't I have just been a welder... THX! – user1504591 Dec 04 '12 at 14:30
1

All solutions provided uses jQuery to achieve what you want. Using plain Javascript (which is much faster), use this approach:

<script type="text/javascript">
function hoverMenu(elem)
{
    document.getElementById('ub' + elem.id).style.background='gray';
}

function blurMenu(elem)
{
    document.getElementById('ub' + elem.id).style.background='white';
}
</script>

<div id="container">
    <div id="nav">
        <div id="one" onmouseover="hoverMenu(this);" onmouseout="blurMenu(this);"><a href="one.html">One</a>    </div><!-- end of first nav -->
        <div id="two" onmouseover="hoverMenu(this);" onmouseout="blurMenu(this);"><a href="two.html">Two</div><!-- end of second nav -->
        <div id="three" onmouseover="hoverMenu(this);" onmouseout="blurMenu(this);"><a href="three.html">Three</div><!-- end of third nav -->
        <div id="four" onmouseover="hoverMenu(this);" onmouseout="blurMenu(this);"><a href="four.html">Four</div><!-- end of fourth nav -->
        <div id="five" onmouseover="hoverMenu(this);" onmouseout="blurMenu(this);"><a href="five.html">Five</div><!-- end of fifth nav -->
    </div><!-- end of nav div -->

    <div id="underbar">
        <div id="ubone"></div><!-- end of first nav -->
        <div id="ubtwo"></div><!-- end of second nav -->
        <div id="ubthree"></div><!-- end of third nav -->
        <div id="ubfour"></div><!-- end of fourth nav -->
        <div id="ubfive"></div><!-- end of fifth nav -->
    </div><!-- end of underbar div -->
</div><!-- end of container div-->
Matheus Azevedo
  • 878
  • 7
  • 18
  • Working perfectly. My only question is document.getElementById('ub' <-- So I don't have to use the entire name of the id? – user1504591 Dec 03 '12 at 17:35
  • 1
    Quote Matheus: _"plain Javascript (which is much faster)"_ ~ If you're going to make a statement like that, please quantify. How much faster and will it make any practical difference for the user experience? – Sparky Dec 03 '12 at 17:42
  • 2
    This isn't much cleaner than the original. Pure JS doesn't mean you have to be obtrusive with your event handlers. – MrCode Dec 03 '12 at 17:53
  • @user1504591 No. The functions will automate that for you. – Matheus Azevedo Dec 03 '12 at 17:54
  • @Sparky672 I just can't see a point of including a library in the project just to do a simple task, since he was already using Vanilla JS. And of course plain Javascript will be faster. Not only in the processing, but also in bandwidth. Want numbers? http://vanilla-js.com/ – Matheus Azevedo Dec 03 '12 at 17:58
  • You can't see the point, yet the OP specifically stated that he preferred a jQuery solution.... for learning, or maybe his project is more complex, etc? And I don't dispute that it's faster... I dispute that the difference will be noticeable in an average practical application. – Sparky Dec 03 '12 at 18:01
  • I didn't saw that part that he wanted a jQuery solution (an edit maybe)... Anyway. You're right. – Matheus Azevedo Dec 03 '12 at 18:06
0
$("#nav").on("mouseover", "div", function() {
    $('#ub' + this.id).css('backgroundColor', 'gray');
}).on("mouseout", "div", function() {
    $('#ub' + this.id).css('backgroundColor', 'white');
});
Samuel Caillerie
  • 8,259
  • 1
  • 27
  • 33
0

Edit: Misread the question. Here is my amended answer.

I would suggest a more semantically correct markup. As your navigation is effectively a list of links, it is generally standard practice to style it as such:

<ul id="nav">
  <li rel="#ubone"><a href="mypage1.html">One</a><li>
  <li rel="#ubtwo"><a href="mypage2.html">Two</a><li>
  <li rel="#ubthree"><a href="mypage3.html">Three</a><li>
  <li rel="#ubfour"><a href="mypage4.html">Four</a><li>
</ul>

This does require a little extra styling to remove the default list styles, but results in a navigation that makes more sense to Google web crawlers, and follows good coding practices. If in doubt, here is a start on the css:

#nav {margin:0; padding:0;}
#nav li {list-style:none; float:left; padding:5px 10px; background:#FFF;}
#nav a {color:#000; text-decoration:none;}

To answer your original question you can add the behaviour using jQuery like this:

$(document).ready(function(){
  // The document ready waits for the document to load before adding JS to the elements
  // We use the css selector for our element to select it, then use the hover function to apply a behaviour
  $('#nav li').hover(function(){
    // This function executes when the mouse hovers over the li
    var target = $(this).attr('rel');
    $(target).css({
      'background' : '#ccc'
    });
  }, function(){
    // This function executes when the mouse leaves the li
    var target = $(this).attr('rel');
    $(target).css({
      'background' : '#fff'
    });        
  });
});

If you need more help with jQuery, head over to http://api.jquery.com/ where they have some excellent in depth documentation.

N.B. - Without seeing the actual styles you're applying I can't be sure, but it sounds like your underbar could also be accomplished by adding a bottom border and then changing the colour on hover using the ":hover" css pseudo-class.

Maloric
  • 5,525
  • 3
  • 31
  • 46
  • Pure CSS can't modify another element, only the hovering element. – MrCode Dec 03 '12 at 17:31
  • 1
    Use the delete/undelete link when your answer is hidden. – Sparky Dec 03 '12 at 17:34
  • My apologies, like I said I misread the question. Thanks for the tip Sparky672, I'm still getting the hang of Stackoverflow so will remember that for next time. – Maloric Dec 03 '12 at 17:38