PhantomJS: how to type text to a textbox? - node.js

The only solution I can think of is to do it with JS, but I can't pass any variables from the phantom script to the JS I'm trying to execute.

You should take a look at CasperJS. It's a very nice PhantomJS script that allows you to easily perform this kind of web behavior.
As far as communicating with your PhantomJS script, as stands today, you have a few reliable options:
Pass your data in via command line args.
Exchange data via reading/writing of files.
Have your PhantomJS script call your Node.js script via GETS/POSTS.

Yes, there are issue in the QtWebKit bridge between C++ and JS to pass stuff up and down.
It works, but better from JS to C++ than the opposite.
We have a number of issues to address, but this is one of the highest in number one in terms of demand.
In the meanwhile, I usually "decorate" the page object like this:
var page = require("webpage").create();
page.evaluateWithParams = function(func) {
var args = [].slice.call(arguments, 1),
str = 'function() { return (' + func.toString() + ')(',
i, ilen, arg;
for (i = 0, ilen = args.length; i < ilen; ++i) {
arg = args[i];
if (/object|string/.test(typeof arg)) {
str += 'JSON.parse(' + JSON.stringify(JSON.stringify(arg)) + '),';
} else {
str += arg + ',';
}
}
str = str.replace(/,$/, '); }');
return this.evaluate(str);
}
And then you can call a function within the scope of the page like this:
var a = 1, b = 2;
page.evaluateWithParams(function(arg1, args) {
// your code that uses arg1 and arg2
}, a, b);
Hope this helps.
Ivan

Related

Barcode wasn't printed as many as the Request

I was able to print raw ZPL commands from PHP directly to the printer, except that I can't print more than 1 label at once after windows update to windows-10 on the TLP 2844-Z printer and my first time when installing WebClientPrint Processor (WCPP) in windows-10. When I was trying to emulate ZPL printer in the ZPL Printer app it also happened. The only exception was when I try this on the mac Safari browser, it's doing fine.
Working request script (still working in Safari, and previously in all other browser):
for(var i=0; i<rows.length; i++){
javascript:jsWebClientPrint.print('useDefaultPrinter=' + $('#useDefaultPrinter').attr('checked') + '&printerName=' + $('#installedPrinterName').val() + '&param=' + rows[i].value);
}
What's preventing me was the permission asking:
on Chrome weren't generated as many time as the request were (which aren't the problem on Safari).
Example when request were 2:
it only ask for permission once, resulting (only 1 label printed):
when it supposed to be (2 labels printed):
I was able to reproduce the above by using the following script:
for (var i = 0; i < rows.length; i++) {
var url = ('useDefaultPrinter=' + $('#useDefaultPrinter').attr('checked') + '&printerName=' + $('#installedPrinterName').val() + '&param=' + rows[i].value);
window.open('webclientprint:' + domain + url);
}
Which aren't ideal since many tabs would be generated only to print, where previously you don't need any new tab to do the same.
Any idea how to solve this? So that it would print as many as the request ask?
What I did to solve this was to make each request on a separate tab and closed the tab once it's executed. To make it simple I make it into a separate function.
Request script changed into:
for (var i = 0; i < rows.length; i++) {
if (i > 0)
delayPrint(rows[i], i); // separate function
else
javascript: jsWebClientPrint.print('useDefaultPrinter=' + $('#useDefaultPrinter').attr('checked') + '&printerName=' + $('#installedPrinterName').val() + '&param=' + rows[i].value);
}
separate function used for delaying request and to make each request on a separate tab and closed the tab once it's executed:
function delayPrint(data, interval) {
setTimeout(function() {
var wnd = window.open('webclientprint:' + domain + ('useDefaultPrinter=' + $('#useDefaultPrinter').attr('checked') + '&printerName=' + $('#installedPrinterName').val() + '&param=' + rows[i].value));
setTimeout(function() {
wnd.close(); // close once it's done
}, 1000);
}, interval * 3000);
}

npm wait.for not working as expected

tried the code below as provided in the official site - https://www.npmjs.com/package/wait.for. But not working as expected.
Output:
*before calling test
after calling test
reverse for 216.58.196.142: ["syd15s04-in-f14.1e100.net"]*
Expected output:
*before calling test
reverse for 216.58.196.142: ["syd15s04-in-f14.1e100.net"]
after calling test*
What is that I can do to make it work?
var dns = require("dns"), wait=require('wait.for');
function test(){
var addresses = wait.for(dns.resolve4,"google.com");
for (var i = 0; i < addresses.length; i++) {
var a = addresses[i];
console.log("reverse for " + a + ": " + JSON.stringify(wait.for(dns.reverse,a)));
}
}
console.log("before calling test");
wait.launchFiber(test);
console.log("after calling test");
wait.launchFiber(test);
Means launch and forget. launchFiber starts a concurrent execution fiber. Inside the fiber you can use wait for, but the fiber is concurrent with the main execution thread.

NODEJS: Uncork() method on writable stream doesn't really flush the data

I am writing quite simple application to transform data - read one file and write to another. Files are relatively large - 2 gb. However, what I found is that flush to the file system is not happening, on cork-uncork cycle, it only happens on end(), so the end() basically hangs the system until it's fully flashed.
I simplified the example so it just writes a line to the stream a lot of times.
var PREFIX = 'E:\\TEST\\';
var line = 'AA 11 999999999 20160101 123456 20160101 AAA 00 00 00 0 0 0 2 2 0 0 20160101 0 00';
var fileSystem = require('fs');
function writeStrings() {
var stringsCount = 0;
var stream = fileSystem.createWriteStream(PREFIX +'output.txt');
stream.once('drain', function () {
console.log("drained");
});
stream.once('open', function (fileDescriptor) {
var started = false;
console.log('writing file ');
stream.cork();
for (i = 0; i < 2000000; i++) {
stream.write(line + i);
if (i % 10000 == 0) {
// console.log('passed ',i);
}
if (i % 100000 == 0) {
console.log('uncorcked ',i,stream._writableState.writing);
stream.uncork();
stream.cork();
}
}
stream.end();
});
stream.once('finish', function () {
console.log("done");
});
}
writeStrings();
going inside the node _stream_writable.js, I found that it flushes the buffer only on this condition:
if (!state.writing &&
!state.corked &&
!state.finished &&
!state.bufferProcessing &&
state.buffer.length)
clearBuffer(this, state);
and, as you can see from example, the writing flag doesn't set back after first uncork(), which prevents the uncork to flush.
Also, I don't see drain events evoking at all. Playing with highWaterMark doesn't help (actually doesn't seems to have effect on anything). Manually setting the writing to false (+ some other flags) indeed helped but this is surely wrong.
Am I am misunderstanding the concept of this?
From the node.js documentation I found that number of uncork() should match the number of cork() call, I am not seeing matching stream.uncork() call for stream.cork(), which is called before the for loop. That might be the issue.
Looking at a guide on nodejs.org, you aren't supposed to call stream.uncork() twice in the same event loop. Here is an excerpt:
// Using .uncork() twice here makes two calls on the C++ layer, rendering the
// cork/uncork technique useless.
ws.cork();
ws.write('hello ');
ws.write('world ');
ws.uncork();
ws.cork();
ws.write('from ');
ws.write('Matteo');
ws.uncork();
// The correct way to write this is to utilize process.nextTick(), which fires
// on the next event loop.
ws.cork();
ws.write('hello ');
ws.write('world ');
process.nextTick(doUncork, ws);
ws.cork();
ws.write('from ');
ws.write('Matteo');
process.nextTick(doUncork, ws);
// as a global function
function doUncork(stream) {
stream.uncork();
}
.cork() can be called as many times we want, we just need to be careful to call .uncork() the same amount of times to make it flow again.

What's the optimal way to execute a nodejs script from golang, that returns a string, and then communicate that string back to a golang variable?

I'm currently doing it with os/exec and Stdout on golang's side, and console.log("string") on nodejs's side.
Basically I need to generate a string but can only do so within nodejs but the majority of my code is in golang, so I'm trying to make this little blip in my code as seamless, secure, and reliable as possible and I'm a little uneasy about resting such an important part of my program on "console.log" and reading from shell output.
In short: I'm wondering if there exists a better and more standard communication line between my node and go code then console.log + shell output, or is that perhaps optimal enough?
Oh and the function of this particular part of my program is to take a markdown text file and convert it to HTML using markdown-it.
Some ideas:
Communicate through HTTP (send the data/string to a golang http listener)
Communicate through the filesystem (write the string to a temporary file and read it with golang)
Communicate through "something similiar to HTTP but specific to local application data sharing"
P.S.
I can't use otto, since markdown-it doesn't run there.
Actual code:
parser.go
package main
import (
"os"
"os/exec"
"fmt"
"bytes"
)
func main() {
cmd := "node"
args := []string{"parser.js", "/home/user1/dev/current/wikis/Bob's Pain/markup/index.md"}
process := exec.Command(cmd, args...)
stdin, err := process.StdinPipe()
if err != nil {
fmt.Println(err)
}
defer stdin.Close()
buf := new(bytes.Buffer) // THIS STORES THE NODEJS OUTPUT
process.Stdout = buf
process.Stderr = os.Stderr
if err = process.Start(); err != nil {
fmt.Println("An error occured: ", err)
}
process.Wait()
fmt.Println("Generated string:", buf)
}
parser.js
var md = require('markdown-it')();
var yaml = require('js-yaml');
var fs = require('fs');
if (process.argv.length < 3) {
console.log('Usage: node ' + process.argv[1] + ' FILENAME');
process.exit(1);
}
var filename = process.argv[2];
fs.readFile(filename, 'utf8', function(err, data) {
if (err) {
throw err;
}
parse(data)
});
function parse(data) {
data = data.split("---")
yamlData = data[1];
markData = data[2];
y = yamlProcess(yamlData);
markData = "# "+y.title+"\n\n"+markData
html = markdownToHTML(markData);
console.log(html) // SEND THE DATA BACK TO GOLANG
}
function yamlProcess(data) {
try {
var doc = yaml.safeLoad(data);
return doc;
} catch (e) {
console.log(e);
return {};
}
}
function markdownToHTML(data) {
return md.render(data);
}
The easiest way to do this with os/exec:
command := "node parser.js /path/to/some/file.md"
parts := strings.Fields(command)
data, err := exec.Command(parts[0], parts[1:]...).Output()
if err != nil {
panic(err)
}
output := string(data)
"output" is the data that is printed from your NodeJS script. "command" is any command as a string.
I've approached similar requirement both ways.
For a build pipeline extension, I'd write a Python script that takes arguments from command line and outputs results to stdout. It's a simple interface, for a "run once", "everything succeeds otherwise fail fast" usage. If that's the same in your case, I'd keep the implementation as-is.
For a web application, I had Java service for just a specific function (in my case, Natty date recognition from a natural language string). This has the benefit that the application is already "warmed up" at the time of the call, and will definitely respond faster rather than booting up each time the request comes in. Going with a rest interface will probably reveal more benefits over time - e.g. simpler client implementation, monitoring, deployment options, switch implementation without changing clients, etc. It's just more conventional this way.

Execute script in current scope with native v8 code

I need to execute a script that runs in the scope where it's called. Is it possible with native code?
var a = 5;
function test () {
var b = 7;
somenativelib(); // I want to use 'a' and 'b' variables in native code
}

Resources