I'm using jsdom with jquery, and it's working just fine. However, I'm trying to modularize my code a bit so I don't repeat myself, so I made a basic function out of some jsdom code that takes in some html (DOM), tweaks it with jquery, and spits it back out. However, I'm unable to return my result and thus assign it to a calling var. I'm probably not returning in the right place, but I'm just not seeing the obvious if so. Could use a little help.
Here's the code:
function tweakIt(html_in){
var jsdom = require('jsdom');
jsdom.env({
html: html_in,
scripts: [
'../public/javascripts/jquery-1.7.1.min.js',
],
done: function(errors, window) {
var $ = window.$;
// do some jquery magic and manipulate the dom
$('body').append('<div>foo</div>');
console.log('Freshly Manipulated HTML: '+ $('body').html()); // it logs perfectly
return $('body').html(); // this isn't returned to where I called tweakIt() from, why not?
}
});
}
var oldhtml = '<html><body><div>some text</div></body></html>';
var newhtml = tweakIt(oldhtml); // never gets set because nothing gets returned, why?
EDIT:
It was indeed an async issue, so here's how it should be done using a callback instead of a return:
function tweakIt(html_in, callback){
var jsdom = require('jsdom');
jsdom.env({
html: html_in,
scripts: [
'../public/javascripts/jquery-1.7.1.min.js',
],
done: function(errors, window) {
var $ = window.$;
// do some jquery magic and manipulate the dom
$('body').append('<div>foo</div>');
console.log('Freshly Manipulated HTML: '+ $('body').html()); // it logs perfectly
callback($('body').html()); // instead of a return, pass the results to the callback
}
});
}
var oldhtml = '<html><body><div>some text</div></body></html>';
var newhtml = tweakIt(oldhtml, function(newstuff){
console.log(newstuff); // woohoo! it works!
});
I don't think you can do this using a return value, because done: is an async function. Try adding a callback to your tweakIt and get the new html by sending it as a parameter, e.g.
tweakIt(oldHtml, function(newHtml) {/*use the result here*/})
The new version of the JSDOM API no longer includes the 'done' callback option.
So I wrote a 'poor man's callback' to access a DOM variable only after it has been set.
function getSomeDOMVar(callback) {
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const dom = new JSDOM(`
<!DOCTYPE html>
<html>
<body>
<script>
var result; // globally scoped, undefined var, accessible in the node scope as dom.window.result
function doSomething() {
// your code goes here
}
// then assign the data you want back to your the globally scoped var
result = doSomething();
</script>
</body>
</html>
`, {
runScripts: "dangerously",
resources: "usable"
});
// poor man's callback
function waitForVar() {
if (typeof dom.window.result !== 'undefined') {
cb(dom.window.result);
}
}
setTimeout(waitForVar, 1000);
}
getSomeDOMVar(function(result) {
console.log(result)
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With