How to call a Dart program from Javascript? - dart

Given that Dart will need to inter-operate with other javascript frameworks. In the client-web environment what are the current or intended best-practices to communicate with a Dart program from javascript?

Currently you need to use window.postMessage to communicate with Dart however a interorp layer is planned and should arrive in dart2js any day now (although I believe that its initial incarnation will focus more Dart->JavaScript than JavaScript->Dart).

Sample code:
import 'package:js/js.dart' as js;
js.context.jQuery();
var context = js.context;
var param = js.map({ 'modal': true, "width":1000, "height":600});
js.context.jQuery("#dialog").dialog(param);
in html
<script src="packages/browser/interop.js"></script>
The above code open a div as dialog using jQuery.

Related

How can I interop with existing JS objects?

I'm trying to write Dart code that will generate a rough equivalent of this:
var disposable = vscode['commands'].registerCommand(
'extension.sayHello',
function () {
vscode['window'].showInformationMessage('Hello World!');
}
);
context.subscriptions.push(disposable);
The variables vscode and context are both globals available in the JavaScript which is executing my Dart (which is being compiled to JS with the Dart Dev Compiler).
I'm happy for context/vscode to be completely untyped for now, but I'm struggling to bend the JS package to output code like this (eg. if I put #JS() on a stub vscode, I get dart.global.vscode).
You can use the base dart:js features
Note that context happens to be dart's name for the javascript context.
var disposable = context['vscode']['commands'].callMethod('registerCommand', [
'extension.sayHello',
() {
context['vscode']['window'].callMethod('showInformationMessage', ['Hello World!']);
}]);
);
context['context']['subscriptions'].callMethod('push', [disposable]);
Let me put together a quick example on github with package:js.
Edit: OK, here you go:
https://github.com/matanlurey/js-interop-examples
It took me a couple tries to the package:js syntax correct (we probably need more documentation here and examples), but I ended up creating a "fake" visual studio code API (vscode.js), and interoping with it fine.
Watch out that you need to wrap your functions with allowInterop if you expect your examples to work in Dartium.

What is the equivalent to Platform.flush() in Dart?

I was trying to migrate one library from polymer.js to polymer.dart and I found this line:
Platform.flush()
And I was wondering what is the equivalent in dart.
this line appears on line 32 in next library:
https://github.com/Polymer/designer/blob/master/elements/design-state/design-state.html
There isn't and you shouldn't need it in Polymer.dart but you might for interop with Polymer.js.
A workaround is to use JS-interop:
import 'dart:js' as js show context;
...
js.context['Platform'].callMethod('flush')
When you call async(...) or asyncTimer(...) of your Polymer element Platform.flush() is called from Polymer.dart code.

Using thirdparty libraries from dart language

How can import and use any third party javascript libraries in dart..? I want to use snapsvg in my dart application to render svg. But not sure how to add dependencies to add and import it.
I added js: any to my pubspec.yaml and imported packages/browser/interop.js into my html. Where do I place downloaded snapsvg.js and import it to my dart source file to use it.
I am trying to use following javascript code using snapsvg framework from dart.
s = Snap(800, 600);
s.rect(0, 0, 100, 100).attr({
fill: 'white',
stroke: 'black'
});
I tried this code from in dart:
import 'package:js/js.dart' as js;
void main() {
var s = js.context.Snap(800, 600);
s.rect(0, 0, 100, 100);
}
This works fine in dartium, but when I Run as Javascript after build, I got javascript error "method zm not found in object"
I believe this is not right way and I should use be using callMethod on proxy. So I changed code like this
import 'dart:js' show context, JsObject;
void main() {
var snap = context['Snap'];
snap.callMethod('rect', 0,0,100,100);
}
This is not working in Dartium as itself. I would appreciate if someone can provide example of how to call constructor Snap(800, 600) from dart and also rect and attr methods in my example code.
You add them to the HTML file using <script> tags.
You can call JavaScript functions from Dart using dart-js-interop.
There are many examples here on Stackoverflow under this tag - just click on the tag below your question.
When you provide a more concrete example it is easier to help.
You can call into JavaScript with the built-in dart:js library. Please try to avoid using /package/ js, which is what you install by adding js: any to your pubspec. The js package is likely to cause the dart2js output to be bloated and we're probably going to deprecate it at some point.
You can reference JavaScript files like you would in any HTML page, via script tags. You don't actually import them into Dart source, you use dart:js to access JavaScript via its top-level context property.

What is a difference between dart:js and js package?

Everywhere in Dart documentation it is recommended to use js package for javascript interoperability.
However, I have recently found that dart:js package exists in SDK that seems to have similar (but not same) interface.
Are there any differences between these packages? Are they feature equivalent? Which one is recommended?
Js interop started with package:js. It was built with with window.postMessage.
Later dart:js has been added to provide better performance and reduce the size of the compiled js file. Basically the goal were :
removing scopes and lifecycle manual handling
avoiding noSuchMethod to keep compilation size as low as possible
renaming objects to make the api more understandable
Once dart:js has been ready, package:js has been rewrite to use dart:js under the cover.
package:js provides a simpler Api that comes at the cost of an increase of the js size (because package:js uses dart:mirrors and noSuchMethod).
Here is the same thing done with package:js and dart:js :
import 'package:js/js.dart' as js;
main() {
var pixi = new js.Proxy(js.context.PIXI.Stage, 0xffffff);
var renderer = js.context.PIXI.autoDetectRenderer(400, 400);
document.body.append(renderer.view);
}
import 'dart:js' as js;
main() {
var pixi = new js.JsObject(js.context['PIXI']['Stage'], [0xffffff]);
var renderer = js.context['PIXI'].callMethod('autoDetectRenderer', [400, 400]);
document.body.append(renderer['view']);
}
I've received response regardless this on GitHub:
That stack overflow comment is way out of date. Prefer package:js - we're working on updating docs to explicitly recommend that. It's no longer implemented over window.postMessage (that was a Dartium-based solution) - it's handled directly in the compilers and should be more efficient than dart:js.
Source: https://github.com/flutter/flutter/issues/35588#issuecomment-522097151

Rhino and envjs: share Javascript objects with Java application

I'm using rhino and envjs embedded in my java application as described in the envjs guide
Java code:
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.tools.shell.Global;
import org.mozilla.javascript.tools.shell.Main;
...
Context cx = ContextFactory.getGlobal().enterContext();
cx.setOptimizationLevel(-1);
cx.setLanguageVersion(Context.VERSION_1_5);
Global global = Main.getGlobal();
global.init(cx);
Main.processSource(cx, "path/to/your/JSfile");
This is working and my test javascript file correctly loads a remote site and does some manipulation with the HTML elements using jQuery.
What I can't figure out is how to send data from the JavaScript back to my Java application.
Here's my .js file:
load('env.rhino.js');
load('jquery.js');
Envjs.scriptTypes['text/javascript'] = true;
window.location = 'http://[mytestpage].html'
var body = $("body");
print("The body is: "+ $.trim(body));//this prints in the Java console!
//I'd like to call a function in my Java code from the Javascript and pass the bodyText as a parameter to it. How can i do this?
myJavaFunction(bodytext);
So this Rhino tutorial was very useful in learning how to connect your Java to JS.
https://developer.mozilla.org/en-US/docs/Scripting_Java

Resources