0

I want to change body color, font color and link color with functions in JS.

function bodyBackgroundColor(color){
    var target = document.querySelector('body')
    target.style.backgroundColor=color
}

function bodyColor(color){
    var target = document.querySelector('body')
    target.style.color=color
}

function linkColor(color){
    var link = document.querySelectorAll('a')
    var i = 0
    while (i<link.length) {
        link[i].style.color=color
        i = i+1
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Night MOde Final</title>
    <link rel="stylesheet" href="final_night.css">
    <script src="final_night.js"></script>
</head>
<body>
    <h1>
        <a href="qwer">
            WEB
        </a>
    </h1>
    <ol>
        <li>
            <a href="asdf">
                HTML
            </a>
        </li>
        <li>
            <a href="zxcv">
                CSS
            </a>
        </li>
        <li>
            <a href="uiop">
                JavaScript
            </a>
        </li>
    </ol>
    <h2>
        Nightmode
    </h2>
    <p>
        Night mode making again...
    </p>

    <input type="button" value="NIGHT" onclick="
    if (this.value === 'NIGHT') {
    bodyBackgroundColor('black')
    bodyColor('powderblue')
    linkColor('powderblue')
    this.value='DAY'
    }
    else {
    bodyBackgroundColor('white')
    bodyColor('navy')
    linkColor('navy')
    this.value ='NIGHT'
    }
    ">
</body>
</html>

But I found that function linkColor is not working and details of error is that "linkColor is not a function".

I tried to check linkColor function with chrome console, and checked that just writing linkColor('red') or ('blue') is working well.

So I think error occurs when fuction linkColor is in if conditional statement in html document, but still I can't figure out what's wrong.

Does anyone know how to fix this?

  • 1
    `onClick` needs to be passed a function. You're just assigning it a string which is what the error is telling you. – Andy Sep 23 '21 at 15:39
  • 1
    @Andy Are you talking about the `onclick` attribute on the ``? No, the string is correct here. The error is about something different: `onclick` attributes create two implicit `with` scopes around the JS code inside them — one of which is scoped to `document` (the other one to the element itself). By calling `linkColor`, actually [`document.linkColor`](//developer.mozilla.org/docs/Web/API/Document/linkColor) (a deprecated getter that returns an empty string) is “called” (which isn’t possible because strings aren’t functions). – Sebastian Simon Sep 23 '21 at 15:48
  • 1
    Inline event handlers like `onclick` are [not recommended](/q/11737873/4642212). They are an [obsolete, hard-to-maintain and unintuitive](/a/43459991/4642212) way of registering events. Always [use `addEventListener`](//developer.mozilla.org/docs/Learn/JavaScript/Building_blocks/Events#inline_event_handlers_%E2%80%94_dont_use_these) instead. **This is one of the many reasons why `onclick` should be avoided.** – Sebastian Simon Sep 23 '21 at 15:48
  • It's weird. In an my time (25 years) of working with JS I've never seen anything like that. And you're right, but I'm leaving my comment up :). I've seen things like `` obviously, and try to steer my junior devs away from inline JS and use modern methods, but that really _really_ caught me off-guard. @SebastianSimon. Sometimes the more knowledge you gain the more you lose. – Andy Sep 23 '21 at 16:00

1 Answers1

3

It is not recommended to inline JS. You should use addEventListener to add listener on HTML element.

But you can also get the button reference using querySelector and addEventListener to it

function bodyBackgroundColor(color) {
  var target = document.querySelector('body')
  target.style.backgroundColor = color
}

function bodyColor(color) {
  var target = document.querySelector('body')
  target.style.color = color
}

function linkColor(color) {
  var link = document.querySelectorAll('a')
  var i = 0
  while (i < link.length) {
    link[i].style.color = color
    i = i + 1
  }
}


const button = document.querySelector("button");
button.addEventListener("click", function() {
  if (this.value === 'NIGHT') {
    bodyBackgroundColor('black')
    bodyColor('powderblue')
    linkColor('powderblue')
    this.value = 'DAY'
  } else {
    bodyBackgroundColor('white')
    bodyColor('navy')
    linkColor('navy')
    this.value = 'NIGHT'
  }

})
<div class="wrapper">
  <h1>
    <a href="qwer">
          WEB
        </a>
  </h1>
  <ol>
    <li>
      <a href="asdf">
            HTML
          </a>
    </li>
    <li>
      <a href="zxcv">
            CSS
          </a>
    </li>
    <li>
      <a href="uiop">
            JavaScript
          </a>
    </li>
  </ol>
  <h2>
    Nightmode
  </h2>
  <p>
    Night mode making again...
  </p>

  <button type="button" value="NIGHT"> change theme</button>
DecPK
  • 24,537
  • 6
  • 26
  • 42
  • `addEventListener` is definitely recommended and works, but the reason is wrong. The `onclick` attribute _does_ accept a string of JS code, _not_ a function. – Sebastian Simon Sep 23 '21 at 15:49
  • @SebastianSimon If you write a JS functiona as a string then It will produce `Uncaught SyntaxError: Function statements require a function name` – DecPK Sep 23 '21 at 15:54
  • Function name should be passed to `onclick`. – DecPK Sep 23 '21 at 15:54
  • There is no syntax error in the code as shown by the OP. I have no idea what you’re trying, but `onclick="if(){`…`} else{`…`}"` or `onclick="someFunction();"` are both definitely correct. You make it sound as if `onclick="someFunction"` was correct. Note that I’m talking about the _attribute_ (i.e. as in ``), not about the property (i.e. as in `someInput.onclick = someFunction;`); attribute values are always strings anyway. The reason for OP’s error message is explained in my comment under the question, and in more detail by the duplicate target. – Sebastian Simon Sep 23 '21 at 15:58
  • @SebastianSimon You are right we can pass function as a string and pass the function name also. I apologize. Corrected mistake and learned something that I didn't know. Thanks ✌ – DecPK Sep 23 '21 at 16:11