Question

I looks like when I run a page through jsdom, the $(document).ready block in the page script isn't being executed.

Here is the html:

<html>
<body>
  If everything works, you should see a message here:  <h2 id="msg"></h2>

  <script>
    var checkpoint1 = true
    var checkpoint2 = false
    $(document).ready(function(){
      checkpoint2 = true
      $('#msg').html("It works, it works, it works!")
    })
  </script>
</body>
</html>

and the codez:

fs = require('fs');
htmlSource = fs.readFileSync("public/examples/test_js_dom.html", "utf8");

global.jsdom = require("jsdom");

jsdom.defaultDocumentFeatures = {
  FetchExternalResources   : ['script'],
  ProcessExternalResources : ['script'],
  MutationEvents           : '2.0',
  QuerySelector            : false
};

doc = jsdom.jsdom(htmlSource)
window = doc.createWindow()
jsdom.jQueryify(window, "http://code.jquery.com/jquery-1.8.3.min.js", function(){
  console.log(window.checkpoint1);
  console.log(window.checkpoint2);
  console.log(window.$().jquery)
  console.log("body:");
  console.log(window.$('body').html());
});

and the output:

Bee@cleanroom:~/projects/notjs$ test/jsdom.js
true
false   
1.8.3
body:

      If everything works, you should see a message here:  <h2 id="msg"></h2>

      <script>
        var checkpoint1 = true
        var checkpoint2 = false
        $(document).ready(function(){
          checkpoint2 = true
          $('#msg').html("It works, it works, it works!")
        })
      </script>
    <script class="jsdom" src="http://code.jquery.com/jquery-1.8.3.min.js"></script>

What am I doing wrong?

adding detail to satisfied absurd stackoverflow ratio.

Bee@cleanroom:~/projects/notjs$ npm ls jsdom
notjs@1.0.0 /Users/Bee/projects/notjs
├─┬ jquery@1.8.3
│ └── jsdom@0.2.19
└── jsdom@0.3.3
Bee@cleanroom:~/projects/notjs$ node -v
v0.8.15
Bee@cleanroom:~/projects/notjs$ npm -v
1.1.66

[SOLUTION]:

Thank you Dave for leading me to the right answer.

I think the complete jsdom answer goes like this; don't use jsdom.jQuerify, add the script tag to load jQuery in the page above the in page script (as it would need to in order to load the page in a browser).

html:

    ...
    If everything works, you should see a message here:  <h2 id="msg"></h2>

    <script src="http://notjs.org/vendor/jquery-1.8.3.min.js"></script>
    <script>
      var checkpoint1 = true
      var checkpoint2 = false
      $(document).ready(function(){
        var checkpoint2 = true
    ...       

code:

    ...
    doc = jsdom.jsdom(htmlSource)
    window = doc.createWindow()
    window.addEventListener('load',  function(){
      console.log(window.checkpoint1);
      console.log(window.checkpoint2);
      console.log(window.$().jquery)
      console.log("body:");
      console.log(window.$('body').html());
    });
    ...
Was it helpful?

Solution

jQuery hasn't loaded when your script is parsed for the first time, so $ isn't defined. This means that $(document).ready isn't defined, so your function isn't set. You should have seen a warning about this in the console. The solution is to make sure jQuery has loaded before creating your document.ready function. I'm not familiar with jsdom, but there are 2 ways to go about this:

  1. Move the generated <script> tag above your inline script. This may or may not be possible with jsdom.
  2. Move your inline script inside the jsdom callback, where you have all the console.log functions. Because by this point jQuery has been loaded. Edit: actually I think jsdom is like a preprocessor? In which case this one won't work, and you need to do (1).
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top