1

I've been trying to implement basic Javascript with Webpack but have found a lot of trouble trying to get basic methods to work. I know it is probably a problem with my js loading before the DOM but all my fixes to this issue have been futile.

For instance, I'm trying to just run let taskinput = document.getElementById('new-task'); and when I search the taskinput variable in the console I get a return of Uncaught ReferenceError: taskinput is not defined(…).

I've tried quite a few different solutions to make this code operate after the DOM has loaded but nothing seems to work.

I tried the basic attempt of just putting my javascript file at the bottom of the DOM.

I've tried a basic js method like so:

  document.onreadystatechange = function() {
  if (document.readyState === "complete") {
    initApplication();
  }

function initApplication() {(... placed code in here ...)}

I've tried using jqueries

$( document ).ready(function() { });

I've tried injecting my javascript file into my HTML with the html-webpack-plugin

Is there something I'm missing with Webpack?

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Sample Site</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
  </head>
  <body>
    <button id="new-task">click</button>
    <script src="/assets/app.bundle.js"></script>
  </body>
</html>

app.js

'use strict';

document.onreadystatechange = function() {
  if (document.readyState === "complete") {
    initApplication();
  }
}

function initApplication() {
  onButtonClick();
}

let onButtonClick = function() {
  let taskInput = document.getElementById('new-task');
  taskInput.onclick = alert('hey');
}
Jleibham
  • 480
  • 2
  • 9
  • 26

2 Answers2

2

Using the browser console you can only access variables which are declared globally, and if you define a JavaScript variable inside a function, it doesn't become a global variable. Also, variables declared using let never become global variables.

If you want to declare a variable globally, you can make it a property of window, for example:

window.taskinput = document.getElementById('new-task');

This might be useful for debugging, but avoid doing it in production code, as using global variables is considered a bad practice.

Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
  • cool thanks! I'll try this out now but I was also having trouble with launching things with the onclick command. Though I imagine this is probably rooted in the same issue. – Jleibham Nov 05 '16 at 19:35
2

For instance, I'm trying to just run let taskinput = document.getElementById('new-task'); and when I search the taskinput variable in the console I get a return of Uncaught ReferenceError: taskinput is not defined(…).

First of all, module code in webpack bundles is run in its own scope, effectively in a closure, and not in the global scope (which you can access with window). Secondly, even if you go to your console and declare a variable with let, for example let a = 1, even though your console operates in the global (window) scope, if you try to do window.a you will get undefined because let variables do not get attached to the window scope. See this

Is there something I'm missing with Webpack?

Probably the fact that the code in your bundles, generated by webpack, does not run in the global scope, as explained above.

If you want to expose a variable to the global scope in order to be able to use it, for debugging purposes, in the console, declare it as window.variableName. Or you can add a breakpoint in your code, by adding debugger, after the variable you want to check out, without exposing it to the global scope.

Community
  • 1
  • 1
Dimitris Karagiannis
  • 8,942
  • 8
  • 38
  • 63
  • Ok but then how am I supposed to communicate effectively with the DOM? Is it imperative to use a HTML templating language or generate all page HTML with javascript while using webpack? – Jleibham Nov 05 '16 at 19:53
  • "Ok but then how am I supposed to communicate effectively with the DOM?" In general you want to put vendor code, such as `jQuery` in the head of the page, because it is most likely not dependent on the DOM state, and your own code, which may be interacting with the DOM at the bottom of the body tag, after everything else. Maybe I am not understanding what you are asking exactly, in which case can you provide an example? – Dimitris Karagiannis Nov 05 '16 at 19:57
  • I mean I'm honestly just trying to a simple alert box on click with only javascript. I'm trying to learn more about the language of javascript without any bells and whistles of other libraries. But let me throw up some sample code to show you what I'm trying to do. – Jleibham Nov 05 '16 at 20:02
  • Ok, ping me when you do – Dimitris Karagiannis Nov 05 '16 at 20:10
  • Ok, so I added some code, which I just typed up to demonstrate a thing I'm trying to do. This is particular launched an alert on load but then never when the button is clicked. – Jleibham Nov 05 '16 at 20:17
  • To be honest I think this question is deviating from the original question which I believe you both answered. I just am finding a lot of odd things happening within webpack and it's probably due to my lack of understanding how it works. – Jleibham Nov 05 '16 at 20:19
  • Ok. Initial observation: since you are loading your script at the end of the `body` tag, it is implied that the parts of the DOM that interest you are ready, so you don't really need to run your scripts inside of `onreadystatechange` (It may be a little more complicated than that in some cases (see this answer [here](http://stackoverflow.com/questions/1438883/jquery-why-use-document-ready-if-external-js-at-bottom-of-page) but in your case you don't really need to check if the document is ready). – Dimitris Karagiannis Nov 05 '16 at 20:24
  • 1
    Apart from that, your **actual** problem, is that when you do `taskInput.onclick = alert('hey');` you are immediately invoking the `alert` function on the right hand part of the assignment. Thus, `alert` is executed *once*, it returns `undefined` in the assignment and that's it. You end up with `taskInput.onclick === undefined`. Make the assignment like this instead: `taskInput.onclick = function() { alert('hey'); }`. This way you are assigning a reference to a function on the `onclick` property and you are not immediately executing it. – Dimitris Karagiannis Nov 05 '16 at 20:27
  • As a general advice, if you are just starting to learn the language, maybe you should start with something simpler, without using webpack altogether :) – Dimitris Karagiannis Nov 05 '16 at 20:29
  • Yeah, it looks like it was actually a combination of not being able to trigger the variables globally in the console, as well as my own miswritten code. – Jleibham Nov 05 '16 at 20:32
  • And yes now understanding that I can't check on my variables easily while using webkit it is probably wise to stick to the basics :p – Jleibham Nov 05 '16 at 20:33
  • 1
    Well, you can check your variables, if that's your problem. You don't have to expose them to `window` in order to be able to check them. As I told you, you can add breakpoints to your code, either by adding a [`debugger`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/debugger) statement after the part of code that you want to check, or add a breakpoint in your browser's console. See [here](https://developers.google.com/web/tools/chrome-devtools/javascript/add-breakpoints) for instructions on how to do it – Dimitris Karagiannis Nov 05 '16 at 20:36