using jint to call javascript using d3 from c# - javascript

I am currently working on a project where we need to generate some SVG based on some input data. Currently all this SVG generation is implemented in javascript using the d3 library. Note that my goal is to be able to reuse this logic and not implement it all over.
My problem is that I would like to be able to call this javascript from C#.
I have tried using PhantomJS and I am able to generate the SVG but I am not satisfied because
Each time I want to call the javascript it starts a new process and I
have noticed that it uses a lot of memory (In my case I saw 100 mb
which is too much in my case)
It seems a little unstable. I have
had some cases where the process just hangs
Development (On the javascript side) is pretty frustrating because it is hard to debug
Because I was not satisfied with PhantomJS I have also tried using jint and this seems really nice to work with. Unfortunately I haven't quite managed to get a working example up and running. Currently I am using AngleSharp to supply the DOM so that D3 has a place to write its data. This gives me the following example:
static void TestJint()
{
//We require a custom configuration with JavaScript and CSS
var config = Configuration.Default.WithJavaScript().WithCss();
//Let's create a new parser using this configuration
var parser = new HtmlParser(config);
//This is our sample source, we will do some DOM manipulation
var source = "<!doctype html> <html><head></head> <body> </body></html>";
var document = parser.Parse(source);
var jintEngine = new Engine();
jintEngine.SetValue("document", document.Implementation);
jintEngine = jintEngine.Execute(File.ReadAllText("d3.min.js"));
jintEngine = jintEngine.Execute("function testFunc() { d3.select(\"body\").append(\"span\").text(\"Hello, world!\"); return 42;}");
var res = jintEngine.Invoke("testFunc").ToObject();
}
The problem is that the line var res = jintEngine.Invoke("testFunc").ToObject(); throws an exception.
Exception screenshot
If I try replacing the line
jintEngine = jintEngine.Execute("function testFunc() { d3.select(\"body\").append(\"span\").text(\"Hello, world!\"); return 42;}");
with
jintEngine = jintEngine.Execute("function testFunc() { d3.select(\"body\"); return 42;}");
then the function is able to run without any exceptions. By playing a little with the logic I have concluded that it is the .append(\"span\") that causes the exception.
I am a little stuck so I was hoping that someone might have an idea that could point me in the right direction.

I have figured out the problems.
1) The document returned by parser.Parse(source); does not implement the function createElementNS which d3 uses. I solved this by using a wrapper that delegates the call.
2) d3 uses the variable ownerDocument which I havn't set. So I also had to add the following
jintEngine.SetValue("ownerDocument", new MyDocumentWrapper(document));
Note that this doesn't make the entire d3 library work. I have also noticed some problems with d3.geopath() but with these fixes I am able to execute my initial example.

Related

Getting Values out of Websocket Functions

I am working on a project which needs to get communication from C++ code to JavaScript on a webserver. Currently, I have data sending properly and it's being received but the issue is that I cant use the data outside of the inner(onmessage) function. This still works fine to overwrite elements of the webpage, but the charts I'm trying to build cant get the live data. If I put the code for the chart inside the inner function the entire program freezes and I can't get the variable out of the function for me to use it in the parent either. Right now, I just want to get the data out of the inner function so I can use it. So, is there any way for me to pull that data out of the inner function and use it in the parent function?
Here is my code:
{
var x;
var ws = new WebSocket('ws://localhost:10011/');
ws.onmessage = function(event)
{
x = event.data;
var testing = document.getElementById('InnerFunctionOutput');
testing.innerHTML = "Run Time: " + x;
}
var testing = document.getElementById('ParentFunctionOutput');
testing.innerHTML = "Run Time: " + x;
}
When I run this code the output from the inner function is the constant stream of data and the output from the parent is a constant 1. If anyone could help me find a solution, it would be greatly appreciated.
One alternative solution is to put the functions for the charts inside the websocket function. That way, I wouldn't have to get data out of the function. however, this solution has its own set of problems. I will put a link below to a thread where I ask about this alternate solution if you are interested in that part.
Plotly and Websockets
Any help would be greatly appreciated.
Thanks,
Luke
I found a solution to the problem. To get the data out of the websocket function I overwrote a text element on the page and simply made that element invisible. After that, just read the text element in order to get it into the rest of the code. However, there could be a better way of doing this so please let me knw if there is.
Also, there is one issue I ran into with this solution. When I originally tried this with normal formatting document.getElementById('some id').innerHTML = some data; it didn't work. But when with adding "window" to the beginning window.document.getElementById('some id').innerHTML = some data; it just worked.

How do I call a method inside component did update from a 3rd party library in react.js?

Ok so Im trying to call a method from another library called the xtk library I have tested the JavaScript code on its own and it works just fine. Now Im just trying to create a component react that will run it. Im a newbie when it comes to both js and react so I might not even be asking the right question here.
componentDidMount = function(){
this.v = X.renderer3D(this.refs.v);
this.v.container ='v';
this.v.init();
this.randF = X.mesh.randF(this.refs.randf);
this.file.randF = '../Assets/rgrid.vtk';
this.v.add(this.randF);
this.v.render();
}
Where Im essentially trying to execute this javascript code with that react.js code.
window.onload = function() {
// create and initialize a 3D renderer
var r = new X.renderer3D();
r.init();
// create a new X.mesh
var skull = new X.mesh();
// .. and associate the .vtk file to it
skull.file = 'http://x.babymri.org/?skull.vtk';
// .. make it transparent
skull.opacity = 0.7;
// .. add the mesh
r.add(skull);
// re-position the camera to face the skull
r.camera.position = [0, 400, 0];
r.render();
};
I keep constantly getting errors thrown at me saying that render3D is not a class, that X is not a constructor and so on. I have essentially spent the last few days trying to figure this out mostly on my own so any advice at all, even of where to look would be absolutely great.
thank you.
Ok this took me a long time to figure out so I want other people to not go through this.
You cannot simply install xtk, you have to eject from create-react-app, Delete your config.lock file and all of your modules, then run npm install on it and run the xtk install on it.
Then you will be able to use it.
This is just in general the way to use full robust 3rd party libraries without having to build everything from scratch.

How to generate blocks from code in blockly?

I have a blockly application which generates some output code. Now, is it possible to write some function which will take my output code and will put corresponding blocks on workspace.
For example, on this page, https://developers.google.com/blockly/
Blocks are connected to generate javascript code, But is there any way, I will give javascript code and blocks will appear on workspace.
You can only create javascript from blocks, not blocks from javascript. However, You can export blocks to xml, and import back the xml to blocks. So you can always save your blocks anywhere you wish in xml format, and load those from xml back to your blockly workspace.
function saveBlocks() {
var xmlDom = Blockly.Xml.workspaceToDom(Blockly.mainWorkspace);
var xmlText = Blockly.Xml.domToPrettyText(xmlDom);
// do whatever you want to this xml
}
function loadBlock(xml) { // xml is the same block xml you stored
if (typeof xml != "string" || xml.length < 5) {
return false;
}
try {
var dom = Blockly.Xml.textToDom(xml);
Blockly.mainWorkspace.clear();
Blockly.Xml.domToWorkspace(Blockly.mainWorkspace, dom);
return true;
} catch (e) {
return false;
}
}
We are working on a python-to-blocks system here
https://www.npmjs.com/package/#pi-top/blockly
it's a work in progress but pretty much deals with all of Python and is being built to work with the pi-top project website https://further.pi-top.com/ but you should be able to extract something useful, the main code->blocks functionality is in the
src/piBlocks folder. The code is based on this project https://github.com/blockpy-edu/BlockMirror I mainly converted it to typescript, reorganised the code and linted it, with a few additions and bugfixes.
It can be done - see https://makecode.microbit.org/. If you create a block then edit as Javascript, you can edit and (if it's valid code) then it will show the correct blocks when you switch back to the block view. The javascript is a bit odd that it's generates - so don't expect it to turn any javascript into blocks...
This isn't part of Blockly - and I'm not sure how this has been done - just that it exists - hope this helps.
I don't remember seeing this feature in blockly, but it is definitely possible. You will have to write custom parsers for your language code and then build the blocks accordingly.
This was somewhat explored in this answer.
Basically as and when you parse the code, you need to programatically create the blocks and attach them together to create the program in blockly.

Unity js script not working

I have recently taken an interest into unity, and as I guide a chose a playlist from youtube. I have installed the
Unity 5.6.4
16 Oct, 2017
version as well.
Now, I encounter an error when I try to add a script to an object.
In the tutorial:
here
, this happens from 11:40 to 13:40.
Basically, as a summary, he is writing a script in js and then attaches it to an object. Now, I have followed the exact steps as him, but it does not work for me.
I write the same script as him, in JS:
then add the script to the object. But then, on the object, I should get a target option, like he does:
However, I don't get this option on my object:
The error I get in the console is this:
Assets/Scripts/PickUp.js(1,386): BCE0044: unexpected char: 0xFEFF.
And this is the actual script:
var target : Transform;
function Update () { }
function OnMouseDown ()
{
this.transform.position = target.position;
this.transform.parent = GameObject.Find("FPSController").transform;
this.transform.parent = GameObject.Find("FirstPersonCharacter").transform;
}
function OnMouseUp ()
{
this.transform.parent = GameObject.Find ("FPSController").transform;
this.transform.parent = null;
}
Now, I've heard that it is not the most efficient, but at this point, I don't really care about that, I just want it to work.
Try to save your script using UTF8 - no BOM (ByteOrderMark). If that does not help, save as Ansi and try that - or read up what unity wants :)
Unity3d Issue Tracker: textassets-encoding-prefab-with-utf8-bom-encryption-is-corrupted it might be related.
This UTF-8 as default in Unity3D new script? was not solved unfortunately.

Minimalistic example of IPython kernel javascript bi-directional communication

My goal is to write an interactive variable viewer for IPython, i.e. which allows one to see, say nested dicts/lists as a tree, and drill down (a bit like the console.log in Javascript).
I spent a lot of time trying to extract minimalistic code out of the directview example in IPython but still can't get my head around how it all works. My Python's ok but my jQuery experience is quite limited.
So I got to stripping down directview.js to the following
container.show();
var widget = $('<div/>')
element.append(widget);
var output = $('<div></div>');
$(widget).append(output)
var output_area = new IPython.OutputArea(output, false);
var callbacks = { 'output': $.proxy(output_area.handle_output, output_area) };
var code = 'print 1+1'
var msg_id = IPython.notebook.kernel.execute(code, callbacks, {silent: false});
This works when I load the directview.ipynb. However I am still not clear how to make it completely standalone (i.e. not require the directview.py, and pass another callback than the standard handle_output of IPython.OutputArea). One of the issues is the container.show() which fails when called in a standalone way.
I am lost on several aspects:
Why is there an element.append(widget) and then $(widget).append(output)? Also why is there also a need to create an Ipython.OutputArea. Isn't there a way to just create a <div id=my_output_area>blah</div> and then have the output callback fill it with the relevant data?
What's the whole .proxy thing about? I would like to create my own callback for output but when I do that and console.log() the arguments passed to the callback, they're undefined or just useless.
I appreciate that the authors of the IPython notebook have done an incredible job creating such a beautiful front-end using jQuery/websockets, and that creating developer documentation that allows beginners like me to tweak with it is asking much, but if anyone can lend a hand that would be great!
I can answer to your second question. The fact is when JavaScript calls your callback, it makes it so without specifying the context, i.e. without setting this (Pythonistas call it self). But it's possible to bound a function to this via $.proxy, which you saw in:
var callbacks = { 'output': $.proxy(output_area.handle_output, output_area) };

Categories