Below is the HTML code:
Try moving the script tag and putting it at the very end of the body. They way it is now, the script is trying to run before the elements on the page are loaded. Moving the script tag to the bottom of the body will ensure that all the html elements above it have loaded properly.
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.
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
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.
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.onDomReady
: This is same as DOMContentLoaded
or ready
of jquery, here also the code is wrappedNo 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.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