I'm trying to communicate with a shared worker from Dart, but I haven't had any success and I've tried everything I can think of.
As a test, I'm just trying to get a basic worker which simply responds with whatever it is sent working.
Starting from the HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="scaffolded-by" content="https://github.com/google/stagehand">
<title>wtf</title>
<link rel="stylesheet" href="styles.css">
<script defer src="main.dart" type="application/dart"></script>
<script defer src="packages/browser/dart.js"></script>
<!-- <script defer src="test.js"></script> -->
</head>
<body>
<div id="output"></div>
</body>
</html>
JavaScript worker (worker.js):
onconnect = function(e) {
var port = e.ports[0];
port.onmessage = function(e) {
port.postMessage("Worker received message: " + e.data);
}
}
The Dart code (main.dart):
import 'dart:html';
import 'dart:async';
void main() async {
var myWorker = new SharedWorker("worker.js");
myWorker.port.onMessage.listen((msg) {
print("Worker says: " + msg);
});
new Timer.periodic(const Duration(seconds: 1), (timer) {
myWorker.port.postMessage("Hello, world");
});
}
The writer does get invoked every second, and I've verified that the shared worker does run (with chrome://inspect).
To narrow the problem down I threw together a JavaScript version of the Dart code (in test.js) which works as expected. If you comment out the contents of main() and uncomment the reference in the HTML to test.js it works. Contents of test.js:
var myWorker = new SharedWorker("worker.js");
myWorker.port.onmessage = function(e) {
console.log("Worker says: " + e.data);
}
setInterval(function() {
myWorker.port.postMessage("Hello, world");
}, 1000);
However, when using the Dart version nothing is written to the console. There are no errors at either compile-time or run-time. It just silently fails.
Any help would be greatly appreciated. I'm probably missing something stupid, but I've been stuck on this for longer than I care to admit…
Since the worker is a SharedWorker, you should call the method:
myWorker.port.start();
just after attach the onMessage listener, (documentation at MDN):
If the onmessage event is attached using addEventListener, the port is manually started using its start() method
Also, at the listener, the parameter msg is a MessageEvent and the text can be retrieved by accessing data property (same as your JS code):
print("Worker says: " + msg.data);
Follow the whole code with the changes:
import 'dart:html';
import 'dart:async';
void main() async {
var myWorker = new SharedWorker("worker.js");
myWorker.port.onMessage.listen((msg) {
print("Worker says: " + msg.data);
});
myWorker.port.start();
new Timer.periodic(const Duration(seconds: 1), (timer) {
myWorker.port.postMessage("Hello, world");
});
}
tested with Dart 1.19.1
Related
I have a .NET MVC project for Word online. The add-in starts up successfully but it does not load "Home.js" which calls Office.initialize to insert data into the body of word.
Here is _Layout.cshtml:
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
#Styles.Render("~/bundles/css")
#Scripts.Render("~/bundles/modernizr")
</head>
<body ng-app="">
<div class="container">
#RenderBody()
</div>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/Scripts/Office/1/office.js")
#Scripts.Render("~/Scripts/Home.js")
#Scripts.Render("~/bundles/bootstrap")
#Scripts.Render("~/Scripts/angular.min.js")
</body>
</html>
And Home.js:
(function () {
"use strict";
Office.initialize = function (reason) {
$(document).ready(function () {
if (!Office.context.requirements.isSetSupported('WordApi', '1.1')) {
return;
}
loadSampleData();
});
};
function loadSampleData() {
// Run a batch operation against the Word object model.
Word.run(function (context) {
// Create a proxy object for the document body.
var body = context.document.body;
// Queue a commmand to clear the contents of the body.
body.clear();
// Queue a command to insert text into the end of the Word document body.
body.insertText("This is a sample text inserted in the document",
Word.InsertLocation.end);
// Synchronize the document state by executing the queued commands, and return a promise to indicate task completion.
return context.sync();
})
.catch(errorHandler);
}
function errorHandler(error) {
console.log("Error: " + error);
if (error instanceof OfficeExtension.Error) {
console.log("Debug info: " + JSON.stringify(error.debugInfo));
}
}
})();
Thank you.
You're only executing if WordAPI v1.1 is available. This API is only supported in Word 2016 for Windows, Mac and iPad. If you're using Word Online or Word 2013 this code will exit (return) without executing anything.
One other note, you're referencing Office.js and Home.js at the bottom of the <body>. You only have 5 seconds to complete Office.initialize() and placing it at the bottom of the page will require everything load before the browser executes that function. While this is absolutely the proper thing to do for a web site, it will result in time-out errors with Add-ins. These references should always be placed within the <header>.
I'm trying to implement some scroll based animation in my Dart web application using Skrollr.js. So far I have the following in main():
main() {
ScriptElement script = new ScriptElement()
..type = 'application/javascript'
..src = 'skrollr.min.js';
document.body.children.add(script);
ScriptElement script2 = new ScriptElement()
..type = 'application/javascript'
..innerHtml = 'var s = skrollr.init({forceHeight: false});';
document.body.children.add(script2);
js.context.callMethod('skrollr', ['init({forceHeight: false})']);
}
For some reason I'm getting the following errors when run:
Uncaught ReferenceError: skrollr is not defined and
Exception: NoSuchMethodError: method not found: 'skrollr'
skroller.min.js has been placed in the app next to index.html so I'm looking for help on what is wrong here.
Also if the is a pure Dart alternative for scroll based animations I'd be happy to know of that as well.
Thanks in advance.
just use:
import 'dart:js';
void main() {
void keyframe(element, name, direction) {
}
context['skrollr'].callMethod('init', [{'keyframe': keyframe}]);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>skrollr</title>
<script type="text/javascript" src="skrollr.min.js"></script>
</head>
<body>
<script type="application/dart" src="main.dart"></script>
<script data-pub-inline src="packages/browser/dart.js"></script>
</body>
</html>
this works. no problem with it.
Since polymer-body has been removed, we need to use an auto-binded template to use polymer binding features outside of a PolymerElement:
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sample app</title>
<script src="packages/web_components/platform.js"></script>
<script src="packages/web_components/dart_support.js"></script>
<link rel="import" href="packages/polymer/polymer.html">
<script src="packages/browser/dart.js"></script>
</head>
<body>
<template is="auto-binding-dart">
<div>Say something: <input value="{{value}}"></div>
<div>You said: {{value}}</div>
<button id="mybutton" on-tap="{{buttonTap}}">Tap me!</button>
</template>
<script type="application/dart">
import 'dart:html';
import 'package:polymer/polymer.dart';
import 'package:template_binding/template_binding.dart';
main() {
initPolymer().run(() {
Polymer.onReady.then((_) {
var template = document.querySelector('template');
templateBind(template).model = new MyModel();
});
});
}
class MyModel extends Observable {
//$['mybutton'] wont works there
#observable String value = 'something';
buttonTap() => print('tap!');
}
</script>
</body>
</html>
Unfortunately, the whole model now extends Observable, every binding seems to work, but the PolymerElement array selector $['foo'] cant be used anymore...
Is there any easy way to implement this $['id'] selector into an Observable model?
I would suggest to use a normal Polymer element instead of auto-binding-dart.
Then you don't have to care about differences and you need no 'main'.
I always start a Polymer project with an <app-element> Polymer element that acts as main() and container for the entire app.
I also would suggest to not use inline code.
As far as I know it has some limitations especially debugging is not supported (might be fixed already, I don't know because I never use it).
To make $ work you need a small and simple workaround;
import 'dart:html';
import 'package:polymer/polymer.dart';
import 'package:template_binding/template_binding.dart';
Map<String, dynamic> $; // we define our own '$'
main() {
initPolymer().run(() {
Polymer.onReady.then((_) {
var template = document.querySelector('template') as Polymer;
$ = template.$; // we assign template.$ to our own '$' so we can omit the 'template' part
templateBind(template).model = new MyModel();
});
});
}
class MyModel extends Observable {
//$['mybutton'] wont work there - it can't because this is outside of a method
#observable String value = 'something';
buttonTap() {
print($['mybutton'].id); // here it works
print('tap!');
}
}
I started with the generating click-counter example. I made the click-counter into a library which I then imported into my main file. The click-counter component can be added manually by putting the appropriate HTML into the web page before running the program. However, I've been unable to find a way to dynamically add the click-counter web component to a div. My attempts have either ended in "Aw, snap!" errors or simply with nothing happening.
The click-counter (xclickcounter.dart):
library clickcounter;
import 'package:web_ui/web_ui.dart';
class CounterComponent extends WebComponent {
int count = 0;
void increment() {
count++;
}
}
The main HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Sample app</title>
<link rel="stylesheet" href="test1.css">
<!-- import the click-counter -->
<link rel="components" href="xclickcounter.html">
</head>
<body>
<h1>Test1</h1>
<p>Hello world from Dart!</p>
<div id="sample_container_id">
<div is="x-click-counter" id="click_counter" count="{{startingCount}}"></div>
</div>
<script type="application/dart" src="test1.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
main file:
import 'dart:html';
import 'package:web_ui/web_ui.dart';
import 'xclickcounter.dart';
// initial value for click-counter
int startingCount = 5;
void main() {
// no error for adding an empty button
var button = new ButtonElement();
query('#sample_container_id').append(button);
// doesn't work (gives "Aw, snap!" in Dartium)
query('#sample_container_id').append(new CounterComponent());
// Nothing happens with this code. Nothing appears.
// But I promise this same thing was giving Aw, Snap
// for a very similar program
final newComponentHtml = '<div is="x-click-counter"></div>';
query('#sample_container_id').appendHtml(newComponentHtml);
}
I tried added an empty constructor to click-counter but it still crashes.
I had the same issue.
See the example (not mine) at https://github.com/dart-lang/web-ui/blob/master/test/data/input/component_created_in_code_test.html and let me know if it works for you.
TL;DR:
void main() {
var element = query('#sample_container_id');
appendComponentToElement(element, new CounterComponent() );
}
void appendComponentToElement(Element element, WebComponent component) {
component.host = new DivElement();
var lifecycleCaller = new ComponentItem(component)..create();
element.append(component.host);
lifecycleCaller.insert();
}
There's more info at my web-ui#dartlang.org post: https://groups.google.com/a/dartlang.org/d/topic/web-ui/hACXh69UqG4/discussion
Hope that helps.
How do I dynamically load a snippet of HTML and insert it into my web page? I am using Dart.
Glad you asked! Using Dart for this task isn't much different than JavaScript, except you get typing, code completion, and a slick editing experience.
First, create the snippet.html:
<p>This is the snippet</p>
Next, create the application. Notice the use of XMLHttpRequest to request the snippet. Also, use new Element.html(string) to create a block of HTML from a string.
import 'dart:html';
void main() {
var div = querySelector('#insert-here');
HttpRequest.getString("snippet.html").then((resp) {
div.append(new Element.html(resp));
});
}
Finally, here's the host HTML page:
<!DOCTYPE html>
<html>
<head>
<title>dynamicdiv</title>
</head>
<body>
<h1>dynamicdiv</h1>
<div id="insert-here"></div>
<script type="application/dart" src="dynamicdiv.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
main.dart:
import 'dart:html';
DivElement div = querySelector('div');
main() async {
String template = await HttpRequest.getString("template.html");
div.setInnerHtml(template, treeSanitizer: NodeTreeSanitizer.trusted);
}
template.html:
<h1>Hello world.</h1>
Check my bird... <em>it flies</em> !
<img src="https://www.dartlang.org/logos/dart-bird.svg">
For the full example, that runs out of the box, see:
https://gist.github.com/kasperpeulen/536b021ac1cf397d4e6d
Note that you need 1.12 to get NodeTreeSanitizer.trusted working.
You can try this example.
https://jsfiddle.net/kofwe39d/ (JS compiled from Dart source code.)
web/main.dart
import 'dart:async';
import 'dart:html';
import 'package:virtual_dom/components/component.dart';
import 'package:virtual_dom/features/state.dart';
import 'package:virtual_dom/helpers/h.dart';
import 'package:virtual_dom/helpers/mount.dart';
import 'package:virtual_dom/helpers/styles.dart';
import 'package:virtual_dom/helpers/vhtml.dart';
void main() {
final app = document.getElementById('app')!;
mount(app, _App());
}
class _App extends Component {
#override
Object render() {
final timer = State.get('timer', () => 3);
final setTimer = State.set<int>('timer');
if (timer > 0) {
Timer(Duration(seconds: 1), () {
setTimer(timer - 1);
});
}
final html = timer > 0
? ''
: '''
Hello, <strong>World!</strong>
''';
final style = styles({'padding': '6px'});
return h('div', {
'style': style
}, [
if (timer > 0) '$timer sec',
h('p', 'Your html:'),
vHtml('div', html),
]);
}
}
web/index.html
<!DOCTYPE html>
<html style="height: 100%;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Example application</title>
<link rel="stylesheet" href="normalize.css">
<link rel="stylesheet" href="styles.css">
<script defer src="main.dart.js"></script>
</head>
<body style="height: 100%; font-family: Verdana,sans-serif; font-size:15px; line-height:1.5">
<div id="app" style="height: 100%;"></div>
</body>
</html>