Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Below is the HTML code:

<!DOCTYPE html>
<html>

<head>
    <link rel="stylesheet" type="text/css" href="style.css">
    <script type="text/javascript">
    var list = document.querySelector('ul');
    list.addEventListener('click', function(ev) {
        if (ev.target.tagName === 'LI') {
            ev.target.classList.toggle('done');
        }
    }, false);
    </script>
</head>

<body>
    <ul>
        <li>Buy milk</li>
        <li>Take the dog for a walk</li>
        <li>Exercise</li>
        <li>Write code</li>
        <li>Play music</li>
        <li>Relax</li>
    </ul>
</body>

</html>

below is the CSS code:

li {
  list-style-type: none;
  position: relative;
  margin: 2px;
  padding: 0.5em 0.5em 0.5em 2em;
  background: lightgrey;
  font-family: sans-serif;
}

li.done {
  background: #CCFF99;
}

li.done::before {
  content: '';
  position: absolute;
  border-color: #009933;
  border-style: solid;
  border-width: 0 0.3em 0.25em 0;
  height: 1em;
  top: 1.3em;
  left: 0.6em;
  margin-top: -1em;
  transform: rotate(45deg);
  width: 0.5em;
}

Above HTML code does not create class="done" on click action, when launched on browser.

On fiddle the same code works fine.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
110 views
Welcome To Ask or Share your Answers For Others

1 Answer

As the code is included in <head> it is executed before the content of the <body> is loaded. So, the elements are not found in the DOM when binding events and event is not bound.

There are two ways to solve this problem.

  1. Wrap the code in DOMContentLoaded event callback.

    document.addEventListener('DOMContentLoaded', function () {
        var list = document.querySelector('ul');
        list.addEventListener('click', function (ev) {
            if (ev.target.tagName === 'LI') {
                ev.target.classList.toggle('done');
            }
        }, false);
    });
    

    Updated fiddle: https://jsfiddle.net/tusharj/pr2hw6c1/

    Read More about DOMContentLoaded: https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded

  2. Move the code to the end of <body>, so that when the script is executed, all the DOM elements are loaded.

Note: You can also use load event to execute the script code after DOM is completely loaded, but this will wait for all the resources(image, frames, etc.) on the page to load which is not necessary to bind the event on the elements. For reference read Difference between DOMContentLoaded and Load events


Why does the same code in jsfiddle works?

jsfiddle provides four options for where the script should be included. You can set this option from the left panel, below the libraries list.

  1. onLoad: This is same as load event of window. The code is wrapped in the callback of the load event so, the functions/variables cannot be accessed from outside of it. Ex. From HTML inline handlers.
  2. onDomReady: This is same as DOMContentLoaded or ready of jquery, here also the code is wrapped
  3. No wrap - in Head: This means the JS code will be added in the head. No wrap means the code is not wrapped in any function like in load and DOMContentLoaded. So the functions/variables defined are global.
  4. No wrap - in Body: The script is loaded at the end of <body> element.

Now that we know how the script behaves for each of the option, in the fiddle, the option for script location is set to onLoad, so the code works. The code will work for all options except No wrap - in Head.

Read more about this on jsfiddle docs http://doc.jsfiddle.net/basic/introduction.html#fiddle-settings-sidebar


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...