2

I'm trying to learn how to program in JavaScript, coming from a pretty solid knowledge of Java, HTML, and CSS. I've styled a website using bootstrap to play around with but I'm already stuck. My goal is the change the background color of the navbar elements using plain JavaScript

What I'm working with I can do this using jQuery, but I need to know how to program in JavaScript as its helpful to have as a skill. After researching this, The implementations I can see are the mouseover attribute of HTML elements and getElementsByClassName/getElementsById.

When I implement them myself I can't seem the have any luck at all. I'd like to keep my JavaScript inside an external file which is another difficulty. I can't seem to select all the elements at once, let alone style them.

Here's my html (using Bootstrap 4 and some custom stylings):

<!DOCTYPE = html>
<html lang = "en">
  <head>
    <title>Testing Styles</title>
    <link rel="stylesheet" type="text/css" href="css/bootstrap.css">
    <link rel="stylesheet" type="text/css" href="css/bootstrap-grid.css">
    <link rel="stylesheet" type="text/css" href="css/styles.css">
    <link href="https://fonts.googleapis.com/css?family=Julius+Sans+One|Quicksand|Rubik" rel="stylesheet">
  </head>
  <body>
    <heading>
      <div class = "Jumbotron">
        <h1 class = "display-2">The Header</h1>
        <p class = "lead subtext"> And Subtext about the header</p>
      </div>
    </heading>
    <nav class = "mx-auto bg-dark">
      <div class = "container-fluid">
        <ul class = "nav justify-content-center">
          <li class = "nav-item active" id = "temp">
            <a class = "nav-link text-light" href="#">Homepage</a>
          </li>
          <li class = "nav-item active" id = "temp">
            <a class = "nav-link text-light" href="#">Posts</a>
          </li>
          <li class = "nav-item active" id = "temp">
            <a class = "nav-link text-light" href="#">Report A Problem</a>
          </li>
        </ul>
      </div>
    </nav>
    <script src= "JS/scripts.js"></script>

  </body>
</html>

JavaScript:

document.getElementsByClassName("nav-link").style.color = "blue";

Setting the color to blue is only testing if the selection worked, not my final goal. When I refresh the page nothing happens. I've confirmed I linked my JS file correctly as alert() works.

4
  • 1
    getElementsByClassName returns a list, not a single element. You need to iterate the elements and add a mouseover event listener. Commented Jan 23, 2018 at 0:39
  • JS file link is not posted. Commented Jan 23, 2018 at 0:39
  • 1
    Element.getElementsByClassName() gives you an Array Like Object. It would be like document.getElementsByClassName('nav-link')[0].style.color = 'blue'; for the first Array Like Object Element. Commented Jan 23, 2018 at 0:40
  • 1
    The id attribute should be unique. You should not set the same id value for different elements. And you don't really need javascript for this, it can be easily done with css. Commented Jan 23, 2018 at 0:46

4 Answers 4

3

You're almost there... what you've got is a collection to loop through...

var N=document.getElementsByClassName("nav-link");

for(var i=0; i<N.length; i++){ N[i].style.color = "blue"; }
Sign up to request clarification or add additional context in comments.

Comments

2

Cleaning up @user4723924 solution and providing a way to change the color back when the mouse leaves the control.

// Get all the nav-link elements.
var navButtons = document.getElementsByClassName("nav-link");

for (var i=0; i < navButtons.length; i++) { 
    // On mouse over.
    navButtons[i].addEventListener("mouseover", function () {
        // Change color to red.
        this.style.color = "red";
    });
    // On mouse out.
    navButtons[i].addEventListener("mouseout", function () {
      // Change back to original color.
      this.style.color = "";
    });
}
<nav class = "mx-auto bg-dark">
      <div class = "container-fluid">
        <ul class = "nav justify-content-center">
          <li class = "nav-item active" id = "temp">
            <a class = "nav-link text-light" href="#">Homepage</a>
          </li>
          <li class = "nav-item active" id = "temp">
            <a class = "nav-link text-light" href="#">Posts</a>
          </li>
          <li class = "nav-item active" id = "temp">
            <a class = "nav-link text-light" href="#">Report A Problem</a>
          </li>
        </ul>
      </div>
    </nav>

2 Comments

Great answer, thanks! Hadn't considered it being a collection. I'd upvote if I could but not high enough rep atm.
One small problem with this approach, if the link is coloured using an inline style, which it REALLY shouldn't be, the inline style will be lost on mouse out. You could use data attributes to store the original color: jsfiddle.net/ofkbe7et
2

You need to loop over an array of elements.

var links = document.getElementsByClassName('nav-link');
for (var i = 0; i < links.length; i++) {
  links[i].addEventListener('mouseover', function() {
    this.style.color = "blue";
  });

  links[i].addEventListener("mouseout", function () {       
      this.style.color = "";
  });
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/grid.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<heading>
  <div class="Jumbotron">
    <h1 class="display-2">The Header</h1>
    <p class="lead subtext"> And Subtext about the header</p>
  </div>
</heading>
<nav class="mx-auto bg-dark">
  <div class="container-fluid">
    <ul class="nav justify-content-center">
      <li class="nav-item active" id="temp">
        <a class="nav-link text-light" href="#">Homepage</a>
      </li>
      <li class="nav-item active" id="temp">
        <a class="nav-link text-light" href="#">Posts</a>
      </li>
      <li class="nav-item active" id="temp">
        <a class="nav-link text-light" href="#">Report A Problem</a>
      </li>
    </ul>
  </div>
</nav>

Comments

1

I personally prefer .querySelectorAll('selector') as it allows more flexibility for selecting elements.
The method (of choice) to loop through them is [].map.call(collection, function).

It's flexible, not too verbose and highly readable, hence maintainable. I'm not really sure how far it goes in terms of backwards browser compatibility, but it does cover modern IE, which the recommended method, NodeList.forEach() does not, yet.

[].map.call(document.querySelectorAll('.nav-link'), function(el){
  el.addEventListener('mouseover', function(){
    el.setAttribute('data-color',el.style.color);
    el.style.color='red'
  });
  el.addEventListener('mouseout', function(){
    el.style.color=el.getAttribute('data-color');
    el.removeAttribute('data-color')
  });
})
<ul>
  <li><a href class="nav-link">a link</a></li>
  <li><a href class="nav-link" style="color:blue">a link</a></li>
  <li><a href class="nav-link" style="color:orange">a link</a></li>
</ul>

7 Comments

The method to loop through querySelectorAll's NodeList is NodeList.forEach().
@AuxTaco Internet Explorer: no compatibility.
That's what transpilers and polyfills are for.
@AuxTaco, I'm not a JavaScript expert. I learned it by practice, out of necessity. Could you please update me on the pitfalls/downsides of using [].map.call()? Point me a useful link, if you have any. Thank you.
We're moving into opinion now, so I'll leave it, but I do want to note for others that polyfill.io doesn't actually include this particular polyfill at the moment.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.