Is there a way to use d3.js in swt composite - javascript

I am working on an eclipse plug-in where in I need some kind of data visualization. I find d3's visualization to be very useful. Since d3 is a javascript library, the charts can be displayed in browser. But I want the charts to display on swt composite.
Is there any way to do this...

You can use the SWT browser widget. By default it is linked to IE DLL on windows and XULrunner DLL on linux.

You can use javafx-d3
to interact with d3.js in a JavaFx WebView (which should be able to be integrated in SWT).
How I got a minimal example to run:
First, install javafx-d3 as explained on the github page:
Get the source code
You can use the main folder as an Eclipse workspace including two projects:
Import the two Eclipse Maven projects javafx-d3 and javafx-d3-demo
Build the maven projects
Run the demo suite com.github.javafxd3.d3.JavaFxD3DemoSuite
If you do not get javafx-d3 up and running please create an issue ticket.
(Working in Eclipse I had to solve the problem of a missing 'src/test/java' folder on the way.)
Next I followed this tutorial to integrate the browser from the JavaFxSingleDemo into an SWT shell.
(I had to manually import the javafx.embed.swt package - see this thread)
public class SwtIntegrationDemo {
private static Scene scene;
private static JavaFxD3Browser browser;
public static void main(final String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("JavaFX / SWT Integration");
shell.setLayout(new FillLayout());
final FXCanvas canvas = new FXCanvas(shell, SWT.NONE);
//define d3 content as post loading hook
final Runnable postLoadingHook = () -> {
System.out.println("Initial loading of browser is finished");
//do some d3 stuff
createD3Example(); };
//create browser
browser = new JavaFxD3Browser(postLoadingHook, true);
//create the scene
scene = new Scene(browser, 750, 500, Color.web("#666970"));
canvas.setScene(scene);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
private static void createD3Example() {
// code from JavaFxD3SingleDemo.java
}
}

Related

Minify JavaScript using the Google Closure Compiler and Gradle

I have a small Java web application being built with Gradle that includes some custom vanilla JavaScript. I'd like to minify the custom JS code using Google Closure Compiler.
All of the documentation for the Closure Compiler seems to be around using the CLI or the JSON API for minifying JS. I'd much prefer to call the Java API directly from Gradle in e.g. a Copy task.
I'd like to avoid
Node solutions
Calling out to the CLI and using java -jar
HTTP calls to the JSON API
This example is out-of-date and does not reflect the most recent Java API. This question is several years old, though most of the API calls seem similar to the current Java API.
Has anyone else minified JavaScript from Gradle using the Google Closure Compiler Java API directly?
I have a working solution:
task processWebapp(type: Copy) {
from('src/main/webapp') {
include "**/*"
}
eachFile {
if (it.sourceName.endsWith('.js') && !it.sourceName.endsWith('.min.js')) {
it.exclude()
Reader reader = it.file.newReader()
String source = ""
try {
source = reader.readLines().join("\r\n")
} finally {
reader.close()
}
com.google.javascript.jscomp.Compiler compiler = new com.google.javascript.jscomp.Compiler(System.err)
CompilerOptions options = new CompilerOptions()
CompilationLevel.SIMPLE_OPTIMIZATIONS.setOptionsForCompilationLevel(
options)
SourceFile extern = SourceFile.fromCode("externs.js", "")
SourceFile input = SourceFile.fromCode(it.sourceName, source)
compiler.compile(extern, input, options)
String transpiled = compiler.toSource()
def directoryPath = it.relativePath - it.sourceName
File theDir = new File("build/resources/main/${directoryPath}")
if (!theDir.exists()) {
theDir.mkdirs()
}
PrintWriter writer = new PrintWriter("build/resources/main/${it.relativeSourcePath}", "UTF-8")
try {
writer.println(transpiled)
} finally {
writer.close()
}
}
}
destinationDir = file('build/resources/main')
}
This task copies everything from src/main/webapp to build/resources/main while transpiling (minifying) all files ending in .js (but not ending in .min.js) en-route. Gradle then packages and embeds those resources in the resulting jar.
Hope this helps someone else out there using Google Closure Compiler and Gradle.

template node local library import

I have to setup a, most of the time, offline installation of Node-RED and need to use the "Chart.js" Library in a template node. Currently my working approach is to copy the Chart.js dictory to node-red-dashboard/dist/js and import it with <script src= "js/chart.js/dist/Chart.min.js"></script>. But when I want to update the dashboard I need to copy everything again. So it would be nice to have a permanent Solution for this.
I tryed two other approaches until now. For both I installed Chart.js to the .node-red dictory.
First I tryed it like this:
var canvas = document.getElementById('myChart').getContext('2d');
var ChartJs = require('Chart.js');
var chart = new ChartJs(canvas, {... }
in a script tag (... stands for the working chart code that is not edited), but it didn't work aswell as to put
functionGlobalContext: {chartjs:require('Chart.js')} into settings.js and change require('Chart.js') to global.get('chartjs')
Does anyone here has an Idea to solve this properly? Unfortunately the node throws no Error to the console so I don't get an idea whats wrong here.
Thanks in advance for every hint or solution,
manni
When I want to use any 3rd party charting library in my node-red dashboard, I put 2 ui_template nodes into my flow:
under "Template Type" select the "Added to site <head> section" and add the link to the library's url:
<script src="url/to/library.js"></script>
(which in your offline case would be a local url)
use the library's exported objects directly within the template, without using require, such as:
<div id="myChart"></div>
<script>
var canvas = document.getElementById('myChart').getContext('2d');
var chart = new ChartJs(canvas, { ... }
</script>
The trick is to have your local node-red instance serve the ChartJS library through a local url. For that, first add this require path line to the settings.js file, before the exports section:
// The `https` setting requires the `fs` module. Uncomment the following
// to make it available:
var fs = require("fs");
var path = require ("path");
then, uncomment the httpStatic section below that, within the exports:
// When httpAdminRoot is used to move the UI to a different root path, the
// following property can be used to identify a directory of static content
// that should be served at http://localhost:1880/.
httpStatic: path.join(__dirname, 'public'),
(you can use any directory name, in place of public) The __dirname references the node-red server's working directory, usually .node-red under your home directory.
Create this new public directory, copy the ChartJS files under it, and restart node-red. At startup, you should see a line in the console log showing the path to your new static file location:
5 Feb 12:12:23 - [info] Settings file : C:\NODE\node_red_ui\settings.js
5 Feb 12:12:23 - [info] HTTP Static : C:\NODE\node_red_ui\public
5 Feb 12:12:23 - [info] User directory : C:\NODE\node_red_ui
Now you can serve the local file public\scripts\abc.js using the local url
http://localhost:1880/scripts/abc.js
This way, npm updates to the dashboard code will not overwrite your static files.

Using a NodeJS Library from Java using Rhino and Rhinodo

I'm trying to use the Javascript library multilang-extract-comments from within a Java application, so I decided to use Rhino as the Javascript engine and Rhinodo to interface between Rhino and NodeJS. However, I cannot figure out how to actually use Rhinodo. I've looked at the code for the projects that use Rhinodo (maven plugins for brunch, jshint, and recess), but I find the code to be pretty arcane. I've tried implementing code like the following (with some editing for my application):
rhinodoBuilder
.destDir(rhinodoDestDir)
.moduleFactory(nodeModuleProvider)
.consoleFactory(wrappingConsoleFactory)
.env(env)
.build(new BaseFunction() {
#Override
public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
Scriptable brunch = (Scriptable) ScriptableObject.callMethod(cx, scope, "require",
new Object[]{Context.javaToJS("brunch", scope)});
Scriptable options = cx.newObject(scope);
ScriptableObject.putProperty(options, "minify", minify);
System.setProperty("user.dir", userDir.getAbsolutePath());
ScriptRuntime.doTopCall(ScriptableObject.getTypedProperty(brunch, "build", Function.class),
cx, scope, thisObj, new Object[]{
options,
new BaseFunction() {
#Override
public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
return Undefined.instance;
}
}
});
return Undefined.instance;
}
});
(from the brunch maven plugin)
However, this code doesn't work for me. I either get an error in trying to find my Javascript library or, when I use a library it should be able to find (I used fs as an example), I get a NullPointerException. Could someone please tell me what I'm missing here?
Note: both Rhinodo and the maven plugins that use it can be found in MuleSoft's GitHub Repositories
I didn't find a way for this to work out. However, if anyone else is determined to use Rhinodo in this way, part of the problem was that I wasn't actually using a NodeModuleProvider. In order to try and load my required Node modules, I used code similar to the following:
// create a module provider for all the node modules in META-INF
String prefix = "META-INF/node_modules/";
String[] moduleNames = {"amodule","anothermodule","modulethethird"};
ArrayList<NodeModuleImpl> moduleList = new ArrayList<NodeModuleImpl>();
for (String module: moduleNames) {
moduleList.add(NodeModuleImplBuilder.fromFolder(prefix+module));
}
NodeModuleProviderImpl nmp = new NodeModuleProviderImpl(moduleList);
I then used the NodeModuleProvider in the RhinodoBuilder.moduleFactory() method (which you can see used in my code snippet in the question). However, be warned that you may have to solve the problem which I couldn't: using imported modules later from Rhino.
In the end I decided that it made much more sense to call my javascript as a command using exec, so I recommend that anyone else who undertakes something similar just use that solution.

cordova plugin x509store

I have to develop an app with cordova targeting mainly Windows platform.
In this app, I have to manipulate the certification store. Long story short answer, I have to do a cordova plugin (or maybe an activeX trick).
I made a windows runtime component in C#, as explained here, to use X509Store (as I need Windows).
I used visual studio 2015 to make a windows runtime component project (I tried universal windows and 8.1). It works, I can call C# methods in my .js.
But the problem is: a windows runtime component project doesn't have the namespace System.Security.Cryptography.X509Certificates. So I can't access to X509Store.
As a workaround, I made a Class library (.NetCore, .dll) which call X509Store and return strings, at least to show the certificate (json stringify). A classic class library can also access to x509store but it makes target error when I reference it in this windows runtime component project. (a portable/universal dll project doesn't have X509Store neither). My .netcore dll works, I tried it in a Console Application (.NetCore) project and it showed all my certificates. But when I call it from the cordova app (cordova app -> plugin -> runtime -> .netcore dll) it's empty (no certificate found, and the current user is undefined). I think it's because the execution context is not the same (webapp vs console app). And i don't think it's a good solution (which doesn't even work).
So, how can I access to the certification store (of the windows user) in a windows runtime component ? As I don't think it's possible with javascript.
Thanks
P.S: I can provide some source code if needed
EDIT:
I forgot that there is an assembly conflict in the runtime project with the .netcore dll which I solved by referencing the right dll in plugin.xml file (System.Runtime.dll etc ..) as I didn't manage to solve it in visual studio
//script inside cordova, called after device ready
signatureplugin.getAllCertNames(function(a) { }, function(a) { }, 0);
//signatureplugin.js
var exec = require('cordova/exec');
module.exports = {
getAllCertNames: function(successCallback, errorCallback, args) {
exec(successCallback, errorCallback, "SignaturePlugin", "getAllCertNames", [args]);
}
};
//signaturepluginProxy.js
module.exports = {
getAllCertNames: function(successCallback, errorCallback, args) {
var res = SignerVerifier.PluginRT.getAllCertNames();
for (var i = 0, len = res.length; i < len; i++) {
alert(res[i]);
}
}
};
require("cordova/exec/proxy").add("SignaturePlugin", module.exports);
//windows runtime component
using CertStore;
namespace SignerVerifier
{
public sealed class PluginRT
{
public static string[] getAllCertNames()
{
var certStore = new StoreManager();
var res = certStore.getAllCertificates();
return res;
}
}
}
//.NetCore dll
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using Newtonsoft.Json;
using System;
namespace CertStore
{
public class StoreManager
{
private X509Store store;
public StoreManager()
{
store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
}
public string[] getAllCertificates()
{
List<string> res = new List<string>();
store.Open(OpenFlags.ReadOnly);
var certificates = store.Certificates;
foreach (var cert in certificates)
{
res.Add(JsonConvert.SerializeObject(cert));
}
store.Dispose();
return res.ToArray();
}
}
}
If i do a javascript blank app project + Windows Runtime Component project (projects from "universal", I don't have "Windows Store" and I use windows 10) then add the .netcore dll i got the conflict which lead to an exception:
System.IO.FileLoadException: Could not load file or assembly 'System.Runtime, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
(in cordova I prevent this exception by referencing System.Runtime.dll, etc ..., from the nuget package NETStandard.Library.1.6.0 used in .netcore)
I must miss something. .NetCore dll doesn't seem compatible, but the windows runtime project target .NetCore
EDIT 2: (solved)
vcsjones's answer = workaround useless (and no problem from the previous edit).
BUT in anycase there is a security issue, and I have to check "Shared User Certificates" in Capabilities in the appxmanifest
WinRT does certificate management different from the Desktop and Core framework. For WinRT, you would use the Windows.Security namespace.
You can open and manage the certificate store using the Windows.Security.Cryptography.Certificates.CertificateStore class.

Using Google Closure's "compiler.jar" in Google App Engine

I am trying to use Google Closure Compiler API from my Java code. Function compile() receives the original source code, and returns the compiled source code in a String.
This code will run in Google App Engine, but when I deploy and run it I get an "server error". Without calling function below, I don't get any errors. At time of compilation I get warning "compiler.jar will not be available on server's classpath". Compiler.jar is the library I downloaded from Closure Compiler project website.
Any ideas of how to go around this?
Thanks a million,
import com.google.javascript.jscomp.*;
public static String compile(String code)
{
com.google.javascript.jscomp.Compiler.setLoggingLevel(Level.INFO);
com.google.javascript.jscomp.Compiler compiler = new com.google.javascript.jscomp.Compiler();
CompilerOptions options = new CompilerOptions();
CompilationLevel.SIMPLE_OPTIMIZATIONS.setOptionsForCompilationLevel(options);
JSSourceFile js = JSSourceFile.fromCode("input.js", code);
WarningLevel.QUIET.setOptionsForWarningLevel(options);
compiler.compile(null, js, options);
return compiler.toSource();
}
try this:
import com.google.javascript.jscomp.*;
public static String compile(String code)
{
com.google.javascript.jscomp.Compiler.setLoggingLevel(Level.INFO);
com.google.javascript.jscomp.Compiler compiler = new
com.google.javascript.jscomp.Compiler();
CompilerOptions options = new CompilerOptions();
CompilationLevel.SIMPLE_OPTIMIZATIONS.setOptionsForCompilationLevel(options);
JSSourceFile js = JSSourceFile.fromCode("input.js", code);
List<SourceFile> list = new ArrayList<SourceFile>();
list.add(js);
WarningLevel.QUIET.setOptionsForWarningLevel(options);
compiler.compile(new ArrayList<SourceFile>(), list, options);
return compiler.toSource();
}
At time of compilation I get warning "compiler.jar will not be available on server's classpath".
You might have to move the compiler.jar to your WEB-INF/lib.
this is likely the cause for the 500: if you don't deploy the compiler.jar as part of your webapp, your servlet (or whatever) will fail with a NoClassDefFoundError.
If you haven't done so you need to disable threading in the compiler to run on app engine: see "disableThreads" in Compiler.java
http://code.google.com/p/closure-compiler/source/search?q=Compiler.java&origq=Compiler.java&btnG=Search+Trunk
Normally, the compiler spawns a new thread to be sure that it has a larger than standard stack.

Categories