PhantomJS onPrompt callback - javascript

I am trying to get the onPrompt callback working with PhantomJS.
Just for testing I have a basic angular application that prompts the user on initialization and displays that data on the page.
It works fine when I enter the information into the prompt manually, but it will not work when using the PhantomJS onPrompt callback.
Here's the angular app:
angular
.module('app')
.controller('test', TestController)
function TestController() {
var vm = this;
vm.$onInit = onInit;
vm.testData = '';
function onInit() {
vm.testData = prompt('Name?');
}
}
This is the code I running with PhantomJS
var page = require('webpage').create();
page.open('http://localhost:3000', function() {
console.log('test')
page.onPrompt = function(msg, defaultVal) {
console.log("MESSAGE", msg)
return "Dog";
};
page.render('test.pdf');
phantom.exit();
});
I would expect to get a console.log that says "MESSAGE" and the text from the prompt and also a screenshot of my page with "Dog" displayed.
I get a screenshot of a blank page and no console log.
I would ideally like to use this callback with node webshot as an option. webshot phantom callbacks
Thanks for the help.

There is a context in which interaction with the actual interaction with the page takes place - usually within the page.evaluate(..) function. The onPrompt callback will execute within that context and will not print to the console as you expect - I think you need to marshal the output back to the console by setting the onConsoleMessage callback first:
page.onConsoleMessage = function (msg) {
console.log(msg);
};
And then it should print to the console as you expect :)

Related

Outlook AddIn GetAsync successful but returns nothing

I've got an Outlook Add In that was developed using the Office Javascript API.
It looks at the new email being composed & does things based on who it's going to: https://learn.microsoft.com/en-us/office/dev/add-ins/reference/objectmodel/requirement-set-1.3/office.context.mailbox.item
The code correctly returns the TO email when you 'select' the email from the suggested email list... screenshots shown # bottom of this thread
To debug the Javascript, I use C:\Windows\SysWOW64\F12\IEChooser.exe
It was working fine until last week. Is it possible a Windows update broke functionality?
I'm the only person with access to the code. It hadn't been modified for months.
When debugger is running, getAsync correctly returns the 'TO' value. I needed to write the response to a global variable to prove the values were 'undefined' while not in debug.
var resultObjects;
var resultObjects2;
var strMessages = '';
var strTo = '';
var mailbox;
var mailitem;
(function () {
"use strict";
// The Office initialize function must be run each time a new page is loaded.
Office.initialize = function (reason) {
$(document).ready(function () {
mailbox = Office.context.mailbox;
mailitem = mailbox.item;
mailitem.to.getAsync(function (result) {
if (result.status === 'failed') {
strMessages = 'FAILED';
} else {
strMessages = 'SUCCESS';
strTo = result.value[0];
resultObjects = result;
resultObjects2 = result.value;
}
});
loadApp();
});
};
})();
Here are the values of the variables, when the app is loaded & debugger is not running
EDIT
If you 'select' the TO email so that it is bolded... the code works correctly. If you leave the typed-in-text field without selecting the suggested email, it does not work. The same behavior is true for both the Outlook Web Application (# https://outlook.office.com) and the desktop outlook application.
Does not work
Does Work
The Office.context.mailbox.item.to.getAsync API will only return resolved recipients. If the TO email address is not resolved (as in the first screenshot titled "Does not Work"), then API will not return the email address until it is resolved (in both desktop and OWA).
You can use the RecipientsChanged Event, to get newly resolved recipients after you have queried for to.getAsync. This event would fire when a recipient is newly resolved.

Make NodeJS/JSDom wait for full rendering before scraping

I'm trying to scrape data from a website that I need to log into. Unfortunately, I'm getting different results using JSDom/NodeJS than I would if I were to use a web browser, such as FF. In particular, I'm not getting the log in form with the username, password and submit button.
I understand much of Javascript, at least, is asynchronous. However, I thought the "done" function of JSDom waits synchronously for the full rendering of the page. I guess what I'd like to do is simulate an HTTPS get and wait for the full document.ready to be done.
var jsdom = require("jsdom");
var jsdom_global = require("jsdom-global");
var fs = require("fs");
var jquery = fs.readFileSync("./jquery-3.1.1.min.js", "utf-8");
jsdom.env({
url: "https://wemc.smarthub.coop/Login.html#login:",
src: [jquery],
done: function (err, window) {
var $ = window.$;
if($("button#LoginSubmitButton").length) {
console.log('Click button found');
} else {
console.log('Click button not found');
}
// The following text boxes are not coming back:
// $("input#LoginUsernameTextBox")
// $("input#LoginPasswordTextBox")
// If I enable the line below, I see a lot less than I would if I
// do a view source in any reasonable browser.
//console.log($("body").html());
}
});
Usually, this will happen because JSDOM doesn't execute the JS when it hits the page. In that case, the only elements returned will be the server rendered HTML.
You could try a headless browser module such as PhantomJS etc and see how that goes for you. There's a section about the distinction between the two at the bottom of the JSDOM github page.

Grab JavaScript console output with PhantomJS and evaluate it

I'm trying to parse the status page of my router to get the number of wlan devices. The page uses some JavaScript to get the status, so I tried to use PhantomJS, but had no luck.
This is the html source of the status page (status.html and status.js): http://pastebin.com/dmvptBqv
The developer tools of my browser show me this output on the console (anonymized):
([
{"vartype":"value","varid":"device_name","varvalue":"Speedport W 921V"},
{"vartype":"value","varid":"factorydefault","varvalue":"1"},
{"vartype":"value","varid":"rebooting","varvalue":"0"},
{"vartype":"value","varid":"router_state","varvalue":"OK"},
{"vartype":"value","varid":"bngscrat","varvalue":"0"},
{"vartype":"value","varid":"acsreach","varvalue":"0"},
Full reference
How can I get this evaluated output out of PhantomJS? Maybe it is very simple and I just missed the part in the documentation.
I think that i have to use the evluate function, but have no idea what is the correct function for the document object to return the complete evaluation.
var webPage = require('webpage');
var page = webPage.create();
page.open('blubb', function (status) {
var js= page.evaluate(function() {
return document.???;
});
console.log(js);
phantom.exit();
});
The main problem that you have is to get the console messages from the page into a single structure that you can do further processing on. This is easily done with the following code which waits indefinitely until the first console message appears and stops waiting as soon as no further messages appeared during 1 second.
var logs = []
timeoutID;
page.onConsoleMessage = function(msg){
if (timeoutID) clearTimeout(timeoutID);
logs.push(msg); // possibly also further processing
timeoutID = setTimeout(function(){
page.onConsoleMessage = function(msg){
console.log("CONSOLE: " + msg);
};
// TODO: further processing
console.log(JSON.stringify(logs, undefined, 4));
phantom.exit();
}, 1000);
};
page.open(url); // wait indefinitely
If each msg is valid JSON, then you can parse it immediately to get JavaScript objects. Change
logs.push(msg);
to
logs.push(JSON.parse(msg));

Cannot put phantom.exit() inside page.evaluate() in phantomjs

I have 2 code samples as following:
var page = require('webpage').create();
page.open('https://www.youtube.com', function(s) {
console.log(s);
page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
var t = page.evaluate(function() {
console.log('here');
phantom.exit(); // case 1: inside page.evaluate()
});
});
});
-> In this case, phantom.exit() is put inside page.evaluate(), and error appears: "ReferenceError: Can't find variable: phantom"
var page = require('webpage').create();
page.open('https://www.youtube.com', function(s) {
console.log(s);
page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
var t = page.evaluate(function() {
console.log('here');
});
phantom.exit(); // case 2: outside page.evaluate()
});
});
-> In case 2: phantom.exit() is put outside page.evaluate(). There is no error, but 'here' is not printed out.
=> Neither of 2 above ways can print out 'here'. Is there any effective way to print 'here' without error?
You can't use any of the phantom method inside of the page, in the same way the page itself can't use them.
The phantom object is a special host object provided by the runtime to the script it initially launches. Once a page has been loaded, the page runs in its own context with the usual browser variables, which do not include phantom.
You need to wait for the page.evaluate to call back to the phantom script, then call exit from there. The Phantom docs show this exact case, with exit being called after evaluate has returned. They don't seem to cover whether evaluate is blocking or not, but the example suggests that it may be.
To capture the log messages from the page, you need to subscribe to its onConsoleMessage event. The Phantom console only picks up messages from the script it is running, not any pages that it may load. All you need to do is route page messages to the phantom console:
page.onConsoleMessage = function(msg) {
console.log('PAGE: ' + msg);
};
Try returning required data back and do console.log() after evaluation
Example
var page = require('webpage').create();
page.open('https://www.youtube.com', function(s) {
console.log(s);
page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
var t = page.evaluate(function() {
return "here";
});
console.log(t);
phantom.exit(); // case 2: outside page.evaluate()
});
});

Fire Elfinder Error Dialog from Command

I am working on making my own command (view commands) for elFinder, and it works pretty good.
The only thing that I have a problem with is when I do my custom ajax call to the connector, the error doesn't popup. It is valid JSON error output.
I was thinking if it somehow was possible to fire the error dialog myself from the command file?
I'm trying to do this from inside the this.exec = function(data) { ... } function in my command.
Your error call should be like this within that function. this.fm.error() or fm.error() in this case is used to fire the error dialog.
this.exec = function(data) {
var fm = this.fm,
dfrd = $.Deferred()
.fail(function(error) {
fm.error(error);
})
return dfrd;
}

Categories

Resources