jsdom can't load local html and javascript - jsdom

Thanks for any help.
Using jsdom, I'm trying to load a local HTML file, which itself loads a local JS file.
import jsdom from 'jsdom-no-contextify'
var fs = require('fs');
var path = require("path");
var html = fs.readFileSync(path.join(__dirname, '../src/', 'launcher.html'));
global.document = jsdom.jsdom(html, {
FetchExternalResources: ['script'],
ProcessExternalResources: ['script'],
created: function (error, window) {
console.log("created: " + error);
},
url: "file://mydir/src/js/helloworld.js"
});
global.window = document.parentWindow;
window.addEventListener('load', function () {
});
launcher.html itself sources helloworld.js i.e.
<script type="text/javascript" src="js/helloworld.js"></script>
However I can't access or read any variables inside helloworld.js
Regards, Sam

you need to add the runsScripts and resources properties as below
global.document = jsdom.jsdom(html, {
FetchExternalResources: ['script'],
ProcessExternalResources: ['script'],
created: function (error, window) {
console.log("created: " + error);
},
url: "file://mydir/src/js/helloworld.js",
runScripts: "dangerously",
resources:'usable'
});

Related

Is there a way to get a callback from

I am downloading files to the client using Iron Router.
Router.route('zipfile', {
where: 'server',
path: '/zipfile/:name/:targetName',
action: function() {
var name = this.params.name;
var targetName = this.params.targetName;
var filename = `${ZIP_DIR}/${name}`;
var file = fs.readFileSync(filename);
var headers = {
'Content-type': 'application/zip',
'Content-disposition' : `attachment; filename=${targetName}.zip`,
};
this.response.writeHead(200, headers);
return this.response.end(file);
}
});
I wanted to know when the download has completed so I can then delete the source file on the server. Is there an easy way of doing that?
You could use the onAfterAction hook
Router.onAfterAction(function(req, res, next) {
// in here next() is equivalent to this.next();
}, {
only: ['zipfile'],
where: 'server
});

Casper JS Ajax request is not returning any response

I am working on casper JS, to scrap data from a website. For now I am just getting the title of a website. When I scrap the title of that page I want to send that title to my php script through Casper JS ajax method, but for some reasons its not working for me :
Below is the Casper JS code :
var casper = require('casper').create();
casper.start("https://www.google.com/", function() {});
casper.then(function() {
var d = this.evaluate(function() {
var links = document.getElementsByTagName('title')[0].textContent;
return links;
})
console.log(d);
casper.thenOpen("modal_scripts.php?scraped=true", {
method: "post",
data: {
data: d
}
},
function(response) {
console.log(response.data);
});
})
casper.run();
And this is the php scripts, where I want to collect the data sent by casper POST method.
if (isset($_POST["scraped"])) {
$d = $_POST["data"];
echo "Response : "." ".$d;
}
I just want to send the scrapped data to my php script, where I can save it in a Database.
The Simpler Solution :
var casper = require('casper').create();
casper.start("https://www.google.com/");
casper.then(function() {
var data = this.evaluate(function() {
var title = document.getElementsByTagName('title')[0].textContent;
return title;
})
console.log(data);
casper.thenOpen("http://localhost/fiverr/Crawl%20The%20Jobs/modal_scripts.php", {
method: "POST",
data: data + "&crawled_jobs=true"
}).then(function(res) {
console.log(res.status);
})
})
casper.run();

Get image url in Meteor method

I cannot seem to find any documentation that will explain how I can get the filename and filepath of an uploaded collectionFS image into my meteor method.
I am able to get the image URL on the client side no problem using helpers, but I cannot seem to figure out how I can send the filename and filepath of the attached image to my method.
Method JS
Meteor.methods({
addQuote: function(data) {
check(data, Object);
var attachments = [];
var html = html;
// need to get the filename and filepath from collectionFS
// I would then have the data go here
attachments.push({filename: , filePath: });
this.unblock();
var email = {
from: data.contactEmail,
to: Meteor.settings.contactForm.emailTo,
subject: Meteor.settings.contactForm.quoteSubject,
html: html,
attachmentOptions: attachments
};
EmailAtt.send(email);
}
});
Controller JS
function ($scope, $reactive, $meteor) {
$reactive(this).attach($scope);
this.user = {};
this.helpers({
images: () => {
return Images.find({});
}
});
this.subscribe('images');
this.addNewSubscriber = function() {
// Uploads the Image to Collection
if(File.length > 0) {
Images.insert(this.user.contactAttachment);
console.log(this.user.contactAttachment);
}
// This is the variable I use to push to my method
// I image I need to push the filename and filepath also
// I am unsure how to access that information in the controller.
var data = ({
contactEmail: this.user.contactEmail,
contactName: this.user.contactName,
contactPhone: this.user.contactPhone,
contactMessage: this.user.contactMessage
});
// This will push the data to my meteor method "addQuote"
$meteor.call('addQuote', data).then(
function(data){
// Show Success
},
function(err) {
// Show Error
}
);
};
You can use the insert callback to get this informations:
Images.insert(fsFile, function (error, fileObj)
{
if (error) console.log(error);
else
{
console.log(fileObj);
//Use fileObj.url({brokenIsFine: true}); to get the url
}
});

Server side route to download file

I've got a server side route I'm using to download a file. This is called from a client side button click and everything is working fine. However, once the button has been clicked once it will not work again until another route is loaded and you go back. How can I code it so that the button can be clicked multiple times and the server side route be fired each time?
My button code looks like this...
'click #view_document_download': function (event, tmpl) {
Router.go('/download_document/' + this._id);
}
And my server side route looks like this...
Router.route('/download_document/:_id', function () {
//Get the file record to download
var file = files.findOne({_id: this.params._id});
//Function to take a cfs file and return a base64 string
var getBase64Data = function(file2, callback) {
var readStream = file2.createReadStream();
var buffer = [];
readStream.on('data', function(chunk) {
buffer.push(chunk);
});
readStream.on('error', function(err) {
callback(err, null);
});
readStream.on('end', function() {
callback(null, buffer.concat()[0].toString('base64'));
});
};
//Wrap it to make it sync
var getBase64DataSync = Meteor.wrapAsync(getBase64Data);
//Get the base64 string
var base64str = getBase64DataSync(file);
//Get the buffer from the string
var buffer = new Buffer(base64str, 'base64');
//Create the headers
var headers = {
'Content-type': file.original.type,
'Content-Disposition': 'attachment; filename=' + file.original.name
};
this.response.writeHead(200, headers);
this.response.end(buffer, 'binary');
}, { where: 'server' });
use a element instead of js 'click' event
page html
page js in server
Router.route("/download_document/:fileId", function(){
var file = files.findOne({_id: this.params.fileId});
var contentFile = //file text
let headers = {
'Content-Type': 'text/plain',
'Content-Disposition': "attachment; filename=file.txt"
};
this.response.writeHead(200, headers);
this.response.end(contentFile);
},
{where: "server", name: "download"}
);
Maybe you should just return an Object from your Server via a method and form it to a file on the client side? if possible..
To create a file on the client side is really simple, and you don't have to deal with Routers at this point.
function outputFile(filename, data) {
var blob = new Blob([data], {type: 'text/plain'}); // !note file type..
if(window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, filename);
}
else{
var elem = window.document.createElement('a');
elem.href = window.URL.createObjectURL(blob);
elem.download = filename;
document.body.appendChild(elem)
elem.click();
document.body.removeChild(elem);
}
}
function getContentAndOutputFile() {
var content = document.getElementById('content').value;
outputFile('file.txt', content);
}
<input id="content" value="test content"/>
<button onClick="getContentAndOutputFile()">Create File</button>

grunt is not defined default not found

I want to create yoeman generator for html template project
when i try to launch grunt i ha this error Task 'default not found
grunt build give grunt is not defined
$> grunt
Loading "Gruntfile.js" tasks...ERROR
>> ReferenceError: grunt is not defined
Warning: Task "default" not found. Use --force to continue.
Aborted due to warnings.
Here is my code
var fs = require('fs');
var path = require('path');
var showdown = require('showdown');
var EJS = require('ejs');
var TemplateRender = function(file, destination, source, template) {
this.file = file;
this.destination = destination;
this.source = source;
this.template = template;
this.grunt = grunt;
};
TemplateRender.prototype = {
render: function() {
var file = this._read();
var html = this._convert(file);
var content = this._template(html);
this._write(content);
},
_read: function() {
var filepath = path.join(this.source,this.file);
grunt.file.read(filepath);
},
_convert: function(file) {
return new showdown.convertor().makeHtml(file);
},
_template: function(html) {
var template = this.grunt.file.read(this.template);
return EJS.render(template,{content:html});
},
_write: function() {
this.grunt.file.write(
path.join(this.destination, this.file),
page
);
}
};
'use strict';
module.exports = function(grunt) {
grunt.registerTask('build', function() {
var template = "app/index.ejs",
destination = path.join(process.cwd(),"dist"),
source = path.join(process.cwd(),"posts"),
files = fs.readdirSync(source);
files.forEach(function(file) {
new TemplateRender(file, destination, source, template, grunt).render();
read();
convert();
template();
write();
});
});
};
I need to know how to detect error in grunt and yeoman
At the top of your code, in the TemplateRender function, you have this line: this.grunt = grunt; But you don't actually have an argument by that name. Try this:
// ... (everything the same above here)
// *** Notice the new argument to this constructor function
var TemplateRender = function(file, destination, source, template, grunt) {
this.file = file;
this.destination = destination;
this.source = source;
this.template = template;
this.grunt = grunt;
};
TemplateRender.prototype = {
// ...
_read: function() {
var filepath = path.join(this.source,this.file);
// *** probably needs to be `this.grunt` ?
this.grunt.file.read(filepath);
},
// ...
};
module.exports = function(grunt) {
grunt.registerTask('build', function() {
// ... (mostly the same)
files.forEach(function(file) {
new TemplateRender(file, destination, source, template, grunt).render();
// *** where are these defined? Should they be: this._read(), etc?
this._read();
this._convert();
this._template();
this._write();
});
});
};

Resources