How do you interact with js from dart? - dart

No, this isn't the same as the other question of the same name.
There are seemingly identical packages which seem to do this, but with different apis.
http://dart-lang.github.io/js-interop/docs/js.html
https://api.dartlang.org/docs/channels/stable/latest/dart_js.html
Why are there two?
Which one are we supposed to use?
The interop one looks newer and has a better api, but doesn't actually work. According to the documentation, you should be able to convert this javascript:
var stage = new PIXI.Stage(0xFFFFFF);;
renderer = PIXI.autoDetectRenderer(800, 600);
document.body.appendChild(renderer.view);
Into:
var pixi = new js.Proxy(js.context.PIXI.Stage, 0xffffff);
var renderer = js.context.PIXI.autoDetectRenderer(400, 400);
document.body.append(renderer.view);
But that errors when you try to compile it:
dart2js
Error occured:/Users/doug/megac/client/public/dart/index.dart:7:27:
Warning: No member named 'PIXI' in class 'Proxy'.
var pixi = new js.Proxy(js.context.PIXI.Stage, 0xffffff);
^^^^^^^^^^^^^^^
So... js:dart? Is that what you're supposed to use?
Edit: Incidentally, for anyone who stumbles into this, there is also an open bug http://code.google.com/p/dart/issues/detail?id=15795&thanks=15795&ts=1388068177 regarding how minified dart-js interop bridge operations don't currently work. The original issue was reported in May 2013, and there's been no action on it since then, so don't hold your breath.

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']);
}

Related

how can I use component only in dev?

I have some translation components that I would like to use only in the development environment. The idea is that the component does not get compiled when the project builds.
How can I achieve that in AngularDart 5?
Depending on how you'd like your component to be loaded/not loaded, there are different strategies you can take. My preferred one usually is to have two entry-points for your application, i.e. web/main.dart, and web/main.dev.dart, and have the latter be the only one that imports/uses/loads the component in question.
For example, you could have the following definition in lib/translation.dart:
void Function() loadTranslationComponent = () {};
And in web/main.dev.dart:
import 'package:name/translation.dart';
void main() {
loadTranslationComponent = () {
// Code to initialize and use only in development mode.
};
}

Using modal from semantic ui

I am planing to use semantic ui modal has anyone any idea, how to interoperate with dart?
Use the js package to interoperate. First, add the package as a dependency. Then, wrap the JavaScript that you want to use from Dart. Here's an example allowing you to use jQuery's $(...).addClass(...) in Dart:
#JS()
library jquery;
import 'package:js/js.dart';
// Calls invoke JavaScript `JSON.stringify(obj)`.
#JS("\$")
external ElementSet $(String selector);
#JS()
class ElementSet {
external addClass(String className);
}
If you import this file, you can now do:
$('#output').addClass("red");
That example is, of course, quite useless — Dart already allows you to modify HTML classes with better readability and flexibility (e.g. querySelector('#output').classes.add("red")).
But in your case, it starts to make sense. You would implement modal() and go from there.
(I would give you an example of how to implement modal, but I wasn't able to install semantic ui on my workstation for 10+ minutes and then I gave up. So I used the jQuery.addClass example instead.)
It's not that easy. There are two or three pub packages available but they are outdated and incomplete.
I did it this way in Dart 2 (AngularDart 5):
import 'dart:js';
// somewhere in the component:
context
.callMethod(r'$', [modalSelector])
.callMethod('modal', [new JsObject.jsify({
'onApprove': new JsFunction.withThis((element){
// do something on approve
})
})])
.callMethod('modal', ['show']);
This Dart code is equivalent to this Javascript code:
$(modalSelector).modal({
'onApprove': function(element){
// do something on approve
})
.modal('show');
As you may see, you have to call the jQuery framework through the JS module.

Export Dart classes and functions to javascript

If I want to use Dart to create a js library, how can I export Dart classes and functions for use in javascript?
Is there something similar to scala.js, like this?
#JSExport
class Hello{
num x = 0
Hello(this.x)
}
So that in javascript, users can instantiate it as var hi = new Hello(1)
In case this is still relevant: You can use the dart2js compiler, which will compile your dart code down to ES.

Caching streams in Functional Reactive Programming

I have an application which is written entirely using the FRP paradigm and I think I am having performance issues due to the way that I am creating the streams. It is written in Haxe but the problem is not language specific.
For example, I have this function which returns a stream that resolves every time a config file is updated for that specific section like the following:
function getConfigSection(section:String) : Stream<Map<String, String>> {
return configFileUpdated()
.then(filterForSectionChanged(section))
.then(readFile)
.then(parseYaml);
}
In the reactive programming library I am using called promhx each step of the chain should remember its last resolved value but I think every time I call this function I am recreating the stream and reprocessing each step. This is a problem with the way I am using it rather than the library.
Since this function is called everywhere parsing the YAML every time it is needed is killing the performance and is taking up over 50% of the CPU time according to profiling.
As a fix I have done something like the following using a Map stored as an instance variable that caches the streams:
function getConfigSection(section:String) : Stream<Map<String, String>> {
var cachedStream = this._streamCache.get(section);
if (cachedStream != null) {
return cachedStream;
}
var stream = configFileUpdated()
.filter(sectionFilter(section))
.then(readFile)
.then(parseYaml);
this._streamCache.set(section, stream);
return stream;
}
This might be a good solution to the problem but it doesn't feel right to me. I am wondering if anyone can think of a cleaner solution that maybe uses a more functional approach (closures etc.) or even an extension I can add to the stream like a cache function.
Another way I could do it is to create the streams before hand and store them in fields that can be accessed by consumers. I don't like this approach because I don't want to make a field for every config section, I like being able to call a function with a specific section and get a stream back.
I'd love any ideas that could give me a fresh perspective!
Well, I think one answer is to just abstract away the caching like so:
class Test {
static function main() {
var sideeffects = 0;
var cached = memoize(function (x) return x + sideeffects++);
cached(1);
trace(sideeffects);//1
cached(1);
trace(sideeffects);//1
cached(3);
trace(sideeffects);//2
cached(3);
trace(sideeffects);//2
}
#:generic static function memoize<In, Out>(f:In->Out):In->Out {
var m = new Map<In, Out>();
return
function (input:In)
return switch m[input] {
case null: m[input] = f(input);
case output: output;
}
}
}
You may be able to find a more "functional" implementation for memoize down the road. But the important thing is that it is a separate thing now and you can use it at will.
You may choose to memoize(parseYaml) so that toggling two states in the file actually becomes very cheap after both have been parsed once. You can also tweak memoize to manage the cache size according to whatever strategy proves the most valuable.

JS Object.create() in Dart

I'm constructing two JS object in Dart. In JS, they are constructed with Object.create():
var wavesurfer1 = Object.create(WaveSurfer);
var wavesurfer2 = Object.create(WaveSurfer);
This is what I think is Dart equivalent:
var wavesurfer1 = context['WaveSurfer'];
var wavesurfer1 = context['WaveSurfer'];
But, I found that the two objects in Dart appear to be the same. When I call a function in one object it gets triggered in both. This does not happen in the JS code. I suspect that Object.create() should not be written as context[''] in Dart. If this is true, I'm not able to find an example in dartlang.org or stackoverflow.com for how to correctly translate this expression to Dart. You can see the JS source code for WaveSurfer here.
With context['WaveSurfer'] you get a JsObject corresponding to the Js WaveSurfer and not to a new object.
To do the Dart equivalent of your pasted JS code :
import 'dart:js';
var wavesurfer = context['WaveSurfer'];
var wavesurfer1 = context['Object'].callMethod('create', [waveSurfer]);
var wavesurfer2 = context['Object'].callMethod('create', [waveSurfer]);
See Using JavaScript from Dart.
If you find the usage of dart:js to hard and verbose you can use package:js that provides a simplier API (but with a larger JS generated size) :
import 'package:js/js.dart';
var wavesurfer1 = context.Object.create(context.WaveSurfer);
var wavesurfer2 = context.Object.create(context.WaveSurfer);

Resources