Commit 79ec609d authored by Mathieu Lorber's avatar Mathieu Lorber Committed by Sindre Sorhus

Add Dart lang app. Closes #295

parent ebdead12
......@@ -262,6 +262,9 @@
<li>
<a href="labs/architecture-examples/canjs/yui-widget/" data-source="http://canjs.us" data-content="CanJS with YUI (includes a YUI widget binding example). CanJS is a client-side, JavaScript framework that makes building rich web applications easy. It provides can.Model (for connecting to RESTful JSON interfaces), can.View (for template loading and caching), can.Observe (for key-value binding), can.EJS (live binding templates), can.Control (declarative event bindings) and can.route (routing support).">CanJS (YUI Widget)</a>
</li>
<li>
<a href="labs/architecture-examples/dart/" data-source="http://dartlang.org" data-content="Dart firstly targets the development of modern and large scale browser-side web apps. It's an object oriented language with a C-style syntax. It has two run modes : it can be compiled to JS, and will later run in native VM in compliant browsers (just in a dedicated Chromium provided with Dart SDK for the moment).">Dart</a>
</li>
</ul>
</div>
</div>
......
name: todomvc-dart
description: TodoMVC built with Dart
version: 0.0.1
# Dart • [TodoMVC](http://todomvc.com)
A TodoMVC sample built with Dart. It does not use a MVC framework - it's a Vanilla Dart sample.
Dart firstly targets the development of modern and large scale browser-side web apps. It's an object oriented language with a C-style syntax.
## Run
Dart compiles to JavaScript and thus runs across modern browsers. Dart also can run in its own virtual machine.
To edit and debug Dart, you can use Dart Editor. The editor ships with the [SDK](http://dartlang.org) and [Dartium](http://www.dartlang.org/dartium/), our version of Chromium with an embedded Dart VM.
For testing purpose, dart/app.dart will run on any browser thanks to sdk/dart.js. First run will take time to process dart files.
## Credit
Made by [Mathieu Lorber](http://mlorber.net)
html,
body {
margin: 0;
padding: 0;
}
button {
margin: 0;
padding: 0;
border: 0;
background: none;
font-size: 100%;
vertical-align: baseline;
font-family: inherit;
color: inherit;
-webkit-appearance: none;
/*-moz-appearance: none;*/
-ms-appearance: none;
-o-appearance: none;
appearance: none;
}
body {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #eaeaea url('bg.png');
color: #4d4d4d;
width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
#todoapp {
background: #fff;
background: rgba(255, 255, 255, 0.9);
margin: 130px 0 40px 0;
border: 1px solid #ccc;
position: relative;
border-top-left-radius: 2px;
border-top-right-radius: 2px;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
#todoapp:before {
content: '';
border-left: 1px solid #f5d6d6;
border-right: 1px solid #f5d6d6;
width: 2px;
position: absolute;
top: 0;
left: 40px;
height: 100%;
}
#todoapp input::-webkit-input-placeholder {
font-style: italic;
}
#todoapp input:-moz-placeholder {
font-style: italic;
color: #a9a9a9;
}
#todoapp h1 {
position: absolute;
top: -120px;
width: 100%;
font-size: 70px;
font-weight: bold;
text-align: center;
color: #b3b3b3;
color: rgba(255, 255, 255, 0.3);
text-shadow: -1px -1px rgba(0, 0, 0, 0.2);
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
-ms-text-rendering: optimizeLegibility;
-o-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;
}
#header {
padding-top: 15px;
border-radius: inherit;
}
#header:before {
content: '';
position: absolute;
top: 0;
right: 0;
left: 0;
height: 15px;
z-index: 2;
border-bottom: 1px solid #6c615c;
background: #8d7d77;
background: -webkit-gradient(linear, left top, left bottom, from(rgba(132, 110, 100, 0.8)),to(rgba(101, 84, 76, 0.8)));
background: -webkit-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: -moz-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: -o-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: -ms-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');
border-top-left-radius: 1px;
border-top-right-radius: 1px;
}
#new-todo,
.edit {
position: relative;
margin: 0;
width: 100%;
font-size: 24px;
font-family: inherit;
line-height: 1.4em;
border: 0;
outline: none;
color: inherit;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
#new-todo {
padding: 16px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.02);
z-index: 2;
box-shadow: none;
}
#main {
position: relative;
z-index: 2;
border-top: 1px dotted #adadad;
}
label[for='toggle-all'] {
display: none;
}
#toggle-all {
position: absolute;
top: -56px;
left: -15px;
width: 65px;
height: 41px;
text-align: center;
border: none; /* Mobile Safari */
-webkit-appearance: none;
/*-moz-appearance: none;*/
-ms-appearance: none;
-o-appearance: none;
appearance: none;
-webkit-transform: rotate(90deg);
/*-moz-transform: rotate(90deg);*/
-ms-transform: rotate(90deg);
/*-o-transform: rotate(90deg);*/
transform: rotate(90deg);
}
#toggle-all:before {
content: '»';
font-size: 28px;
color: #d9d9d9;
padding: 0 25px 7px;
}
#toggle-all:checked:before {
color: #737373;
}
#todo-list {
margin: 0;
padding: 0;
list-style: none;
}
#todo-list li {
position: relative;
font-size: 24px;
border-bottom: 1px dotted #ccc;
}
#todo-list li:last-child {
border-bottom: none;
}
#todo-list li.editing {
border-bottom: none;
padding: 0;
}
#todo-list li.editing .edit {
display: block;
width: 506px;
padding: 13px 17px 12px 17px;
margin: 0 0 0 43px;
}
#todo-list li.editing .view {
display: none;
}
#todo-list li .toggle {
text-align: center;
width: 40px;
height: 40px;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
border: none; /* Mobile Safari */
-webkit-appearance: none;
/*-moz-appearance: none;*/
-ms-appearance: none;
-o-appearance: none;
appearance: none;
}
#todo-list li .toggle:after {
font-size: 18px;
content: '✔';
line-height: 43px; /* 40 + a couple of pixels visual adjustment */
font-size: 20px;
color: #d9d9d9;
text-shadow: 0 -1px 0 #bfbfbf;
}
#todo-list li .toggle:checked:after {
color: #85ada7;
text-shadow: 0 1px 0 #669991;
bottom: 1px;
position: relative;
}
#todo-list li label {
word-break: break-word;
padding: 15px;
margin-left: 45px;
display: block;
line-height: 1.2;
-webkit-transition: color 0.4s;
-moz-transition: color 0.4s;
-ms-transition: color 0.4s;
-o-transition: color 0.4s;
transition: color 0.4s;
}
#todo-list li.completed label {
color: #a9a9a9;
text-decoration: line-through;
}
#todo-list li .destroy {
display: none;
position: absolute;
top: 0;
right: 10px;
bottom: 0;
width: 40px;
height: 40px;
margin: auto 0;
font-size: 22px;
color: #a88a8a;
-webkit-transition: all 0.2s;
-moz-transition: all 0.2s;
-ms-transition: all 0.2s;
-o-transition: all 0.2s;
transition: all 0.2s;
}
#todo-list li .destroy:hover {
text-shadow: 0 0 1px #000,
0 0 10px rgba(199, 107, 107, 0.8);
-webkit-transform: scale(1.3);
-moz-transform: scale(1.3);
-ms-transform: scale(1.3);
-o-transform: scale(1.3);
transform: scale(1.3);
}
#todo-list li .destroy:after {
content: '✖';
}
#todo-list li:hover .destroy {
display: block;
}
#todo-list li .edit {
display: none;
}
#todo-list li.editing:last-child {
margin-bottom: -1px;
}
#footer {
color: #777;
padding: 0 15px;
position: absolute;
right: 0;
bottom: -31px;
left: 0;
height: 20px;
z-index: 1;
text-align: center;
}
#footer:before {
content: '';
position: absolute;
right: 0;
bottom: 31px;
left: 0;
height: 50px;
z-index: -1;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3),
0 6px 0 -3px rgba(255, 255, 255, 0.8),
0 7px 1px -3px rgba(0, 0, 0, 0.3),
0 43px 0 -6px rgba(255, 255, 255, 0.8),
0 44px 2px -6px rgba(0, 0, 0, 0.2);
}
#todo-count {
float: left;
text-align: left;
}
#filters {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
right: 0;
left: 0;
}
#filters li {
display: inline;
}
#filters li a {
color: #83756f;
margin: 2px;
text-decoration: none;
}
#filters li a.selected {
font-weight: bold;
}
#clear-completed {
float: right;
position: relative;
line-height: 20px;
text-decoration: none;
background: rgba(0, 0, 0, 0.1);
font-size: 11px;
padding: 0 10px;
border-radius: 3px;
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2);
}
#clear-completed:hover {
background: rgba(0, 0, 0, 0.15);
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);
}
#info {
margin: 65px auto 0;
color: #a6a6a6;
font-size: 12px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7);
text-align: center;
}
#info a {
color: inherit;
}
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox and Opera
*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
#toggle-all,
#todo-list li .toggle {
background: none;
}
}
.hidden{
display:none;
}
\ No newline at end of file
(function( window ) {
'use strict';
if ( location.hostname === 'todomvc.com' ) {
var _gaq=[['_setAccount','UA-31081062-1'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script'));
}
})( window );
This diff is collapsed.
part of todomvc;
class TodoApp {
List<TodoWidget> todoWidgets = new List<TodoWidget>();
Element todoListElement = query('#todo-list');
Element mainElement = query('#main');
InputElement checkAllCheckboxElement = query('#toggle-all');
Element footerElement = query('#footer');
Element countElement = query('#todo-count');
Element clearCompletedElement = query('#clear-completed');
Element showAllElement = query('#filters a[href="#/"]');
Element showActiveElement = query('#filters a[href="#/active"]');
Element showCompletedElement = query('#filters a[href="#/completed"]');
TodoApp() {
initLocalStorage();
initElementEventListeners();
window.on.hashChange.add((e) => updateFilter());
updateFooterDisplay();
}
void initLocalStorage() {
var jsonList = window.localStorage["todos-vanilladart"];
if (jsonList != null) {
try {
var todos = JSON.parse(jsonList);
for (Map todo in todos) {
addTodo(new Todo.fromJson(todo));
}
} catch (e) {
window.console.log("Could not load todos form local storage.");
}
}
}
void initElementEventListeners() {
InputElement newTodoElement = query('#new-todo');
newTodoElement.on.keyPress.add((KeyboardEvent e) {
if (e.keyIdentifier == KeyName.ENTER) {
var title = newTodoElement.value.trim();
if (title != '') {
addTodo(new Todo(UUID.createUuid(), title));
newTodoElement.value = '';
updateFooterDisplay();
save();
}
}
});
checkAllCheckboxElement.on.click.add((Event e) {
InputElement target = e.srcElement;
for (TodoWidget todoWidget in todoWidgets) {
if (todoWidget.todo.completed != target.checked) {
todoWidget.toggle();
}
}
updateCounts();
save();
});
clearCompletedElement.on.click.add((MouseEvent e) {
var newList = new List<TodoWidget>();
for (TodoWidget todoWidget in todoWidgets) {
if (todoWidget.todo.completed) {
todoWidget.element.remove();
} else {
newList.add(todoWidget);
}
}
todoWidgets = newList;
updateFooterDisplay();
save();
});
}
void addTodo(Todo todo) {
var todoWidget = new TodoWidget(this, todo);
todoWidgets.add(todoWidget);
todoListElement.nodes.add(todoWidget.createElement());
}
void updateFooterDisplay() {
if (todoWidgets.length == 0) {
checkAllCheckboxElement.style.display = 'none';
mainElement.style.display = 'none';
footerElement.style.display = 'none';
} else {
checkAllCheckboxElement.style.display = 'block';
mainElement.style.display = 'block';
footerElement.style.display = 'block';
}
updateCounts();
}
void updateCounts() {
var complete = 0;
for (TodoWidget todoWidget in todoWidgets) {
if (todoWidget.todo.completed) {
complete++;
}
}
checkAllCheckboxElement.checked = (complete == todoWidgets.length);
var left = todoWidgets.length - complete;
countElement.innerHTML = '<b>${left}</b> item${left != 1 ? 's' : ''} left';
if (complete == 0) {
clearCompletedElement.style.display = 'none';
} else {
clearCompletedElement.style.display = 'block';
clearCompletedElement.text = 'Clear completed (${complete})';
}
updateFilter();
}
void removeTodo(TodoWidget todoWidget) {
todoWidgets.removeAt(todoWidgets.indexOf(todoWidget));
}
void updateFilter() {
switch(window.location.hash) {
case '#/active':
showActive();
break;
case '#/completed':
showCompleted();
break;
default:
showAll();
}
}
void showAll() {
setSelectedFilter(showAllElement);
for (TodoWidget todoWidget in todoWidgets) {
todoWidget.visible = true;
}
}
void showActive() {
setSelectedFilter(showActiveElement);
for (TodoWidget todoWidget in todoWidgets) {
todoWidget.visible = !todoWidget.todo.completed;
}
}
void showCompleted() {
setSelectedFilter(showCompletedElement);
for (TodoWidget todoWidget in todoWidgets) {
todoWidget.visible = todoWidget.todo.completed;
}
}
void setSelectedFilter(Element e) {
showAllElement.classes.remove('selected');
showActiveElement.classes.remove('selected');
showCompletedElement.classes.remove('selected');
e.classes.add('selected');
}
void save() {
var todos = new List<Todo>();
for (TodoWidget todoWidget in todoWidgets) {
todos.add(todoWidget.todo);
}
window.localStorage["todos-vanilladart"] = JSON.stringify(todos);
}
}
part of todomvc;
class TodoWidget {
TodoApp todoApp;
Todo todo;
Element element;
InputElement toggleElement;
TodoWidget(this.todoApp, this.todo);
Element createElement() {
element = new Element.html('''
<li ${todo.completed ? 'class="completed"' : ''}>
<div class='view'>
<input class='toggle' type='checkbox' ${todo.completed ? 'checked' : ''}>
<label class='todo-content'>${todo.title}</label>
<button class='destroy'></button>
</div>
<input class='edit' value='${todo.title}'>
</li>
''');
Element contentElement = element.query('.todo-content');
InputElement editElement = element.query('.edit');
toggleElement = element.query('.toggle');
toggleElement.on.click.add((MouseEvent e) {
toggle();
todoApp.updateCounts();
todoApp.save();
});
contentElement.on.doubleClick.add((MouseEvent e) {
element.classes.add('editing');
editElement.selectionStart = todo.title.length;
editElement.focus();
});
void removeTodo() {
element.remove();
todoApp.removeTodo(this);
todoApp.updateFooterDisplay();
}
element.query('.destroy').on.click.add((MouseEvent e) {
removeTodo();
todoApp.save();
});
void doneEditing(event) {
todo.title = editElement.value.trim();
if (todo.title != '') {
contentElement.text = todo.title;
element.classes.remove('editing');
} else {
removeTodo();
}
todoApp.save();
}
editElement.on
..keyPress.add((KeyboardEvent e) {
if (e.keyIdentifier == KeyName.ENTER) {
doneEditing(e);
}
})
..blur.add(doneEditing);
return element;
}
void set visible(bool visible) {
if(visible) {
element.style.display = 'block';
} else {
element.style.display = 'none';
}
}
void toggle() {
todo.completed = !todo.completed;
toggleElement.checked = todo.completed;
if (todo.completed) {
element.classes.add('completed');
} else {
element.classes.remove('completed');
}
}
}
library todomvc;
import 'dart:html';
import 'dart:math';
import 'dart:json';
part 'TodoWidget.dart';
part 'TodoApp.dart';
void main() {
new TodoApp();
}
class Todo {
String id;
String title;
bool completed;
Todo(String this.id, String this.title, {bool this.completed : false});
Todo.fromJson(Map json) {
id = json['id'];
title = json['title'];
completed = json['completed'];
}
Map toJson() {
return {'id': id, 'title': title, 'completed': completed};
}
}
class UUID {
static Random random = new Random();
static String createUuid() {
return "${S4()}${S4()}-${S4()}-${S4()}-${S4()}-${S4()}${S4()}${S4()}";
}
static String S4() {
return random.nextInt(65536).toRadixString(16);
}
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Dart • TodoMVC</title>
<link rel="stylesheet" href="assets/base.css">
<!--[if IE]>
<script src="assets/ie.js"></script>
<![endif]-->
</head>
<body>
<section id="todoapp">
<header id="header">
<h1>todos</h1>
<input id="new-todo" placeholder="What needs to be done?" autofocus>
</header>
<section id="main">
<input id="toggle-all" type="checkbox">
<label for="toggle-all">Mark all as complete</label>
<ul id="todo-list"></ul>
</section>
<footer id="footer">
<span id="todo-count"><strong>1</strong> item left</span>
<ul id="filters">
<li>
<a class="selected" href="#/">All</a>
</li>
<li>
<a href="#/active">Active</a>
</li>
<li>
<a href="#/completed">Completed</a>
</li>
</ul>
<button id="clear-completed">Clear completed (1)</button>
</footer>
</section>
<footer id="info">
<p>Double-click to edit a todo</p>
<p>Created by <a href="http://mlorber.net">Mathieu Lorber</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
<script src="assets/base.js"></script>
<script type="application/dart" src="dart/app.dart"></script>
<script src="sdk/dart.js"></script>
</body>
</html>
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Bootstrap support for Dart scripts on the page as this script.
if (navigator.webkitStartDart) {
if (!navigator.webkitStartDart()) {
document.body.innerHTML = 'This build has expired. Please download a new Dartium at http://www.dartlang.org/dartium/index.html';
}
} else {
// TODO:
// - Support in-browser compilation.
// - Handle inline Dart scripts.
window.addEventListener("DOMContentLoaded", function (e) {
// Fall back to compiled JS. Run through all the scripts and
// replace them if they have a type that indicate that they source
// in Dart code.
//
// <script type="application/dart" src="..."></script>
//
var scripts = document.getElementsByTagName("script");
var length = scripts.length;
for (var i = 0; i < length; ++i) {
if (scripts[i].type == "application/dart") {
// Remap foo.dart to foo.dart.js.
if (scripts[i].src && scripts[i].src != '') {
var script = document.createElement('script');
script.src = scripts[i].src + '.js';
var parent = scripts[i].parentNode;
parent.replaceChild(script, scripts[i]);
}
}
}
}, false);
}
// ---------------------------------------------------------------------------
// Experimental support for JS interoperability
// ---------------------------------------------------------------------------
function SendPortSync() {
}
function ReceivePortSync() {
this.id = ReceivePortSync.id++;
ReceivePortSync.map[this.id] = this;
}
(function() {
// Serialize the following types as follows:
// - primitives / null: unchanged
// - lists: [ 'list', internal id, list of recursively serialized elements ]
// - maps: [ 'map', internal id, map of keys and recursively serialized values ]
// - send ports: [ 'sendport', type, isolate id, port id ]
//
// Note, internal id's are for cycle detection.
function serialize(message) {
var visited = [];
function checkedSerialization(obj, serializer) {
// Implementation detail: for now use linear search.
// Another option is expando, but it may prohibit
// VM optimizations (like putting object into slow mode
// on property deletion.)
var id = visited.indexOf(obj);
if (id != -1) return [ 'ref', id ];
var id = visited.length;
visited.push(obj);
return serializer(id);
}
function doSerialize(message) {
if (message == null) {
return null; // Convert undefined to null.
} else if (typeof(message) == 'string' ||
typeof(message) == 'number' ||
typeof(message) == 'boolean') {
return message;
} else if (message instanceof Array) {
return checkedSerialization(message, function(id) {
var values = new Array(message.length);
for (var i = 0; i < message.length; i++) {
values[i] = doSerialize(message[i]);
}
return [ 'list', id, values ];
});
} else if (message instanceof LocalSendPortSync) {
return [ 'sendport', 'nativejs', message.receivePort.id ];
} else if (message instanceof DartSendPortSync) {
return [ 'sendport', 'dart', message.isolateId, message.portId ];
} else {
return checkedSerialization(message, function(id) {
var keys = Object.getOwnPropertyNames(message);
var values = new Array(keys.length);
for (var i = 0; i < keys.length; i++) {
values[i] = doSerialize(message[keys[i]]);
}
return [ 'map', id, keys, values ];
});
}
}
return doSerialize(message);
}
function deserialize(message) {
return deserializeHelper(message);
}
function deserializeHelper(message) {
if (message == null ||
typeof(message) == 'string' ||
typeof(message) == 'number' ||
typeof(message) == 'boolean') {
return message;
}
switch (message[0]) {
case 'map': return deserializeMap(message);
case 'sendport': return deserializeSendPort(message);
case 'list': return deserializeList(message);
default: throw 'unimplemented';
}
}
function deserializeMap(message) {
var result = { };
var id = message[1];
var keys = message[2];
var values = message[3];
for (var i = 0, length = keys.length; i < length; i++) {
var key = deserializeHelper(keys[i]);
var value = deserializeHelper(values[i]);
result[key] = value;
}
return result;
}
function deserializeSendPort(message) {
var tag = message[1];
switch (tag) {
case 'nativejs':
var id = message[2];
return new LocalSendPortSync(ReceivePortSync.map[id]);
case 'dart':
var isolateId = message[2];
var portId = message[3];
return new DartSendPortSync(isolateId, portId);
default:
throw 'Illegal SendPortSync type: $tag';
}
}
function deserializeList(message) {
var values = message[2];
var length = values.length;
var result = new Array(length);
for (var i = 0; i < length; i++) {
result[i] = deserializeHelper(values[i]);
}
return result;
}
window.registerPort = function(name, port) {
var stringified = JSON.stringify(serialize(port));
window.localStorage['dart-port:' + name] = stringified;
};
window.lookupPort = function(name) {
var stringified = window.localStorage['dart-port:' + name];
return deserialize(JSON.parse(stringified));
};
ReceivePortSync.id = 0;
ReceivePortSync.map = {};
ReceivePortSync.dispatchCall = function(id, message) {
// TODO(vsm): Handle and propagate exceptions.
var deserialized = deserialize(message);
var result = ReceivePortSync.map[id].callback(deserialized);
return serialize(result);
};
ReceivePortSync.prototype.receive = function(callback) {
this.callback = callback;
};
ReceivePortSync.prototype.toSendPort = function() {
return new LocalSendPortSync(this);
};
ReceivePortSync.prototype.close = function() {
delete ReceivePortSync.map[this.id];
};
if (navigator.webkitStartDart) {
window.addEventListener('js-sync-message', function(event) {
var data = JSON.parse(getPortSyncEventData(event));
var deserialized = deserialize(data.message);
var result = ReceivePortSync.map[data.id].callback(deserialized);
// TODO(vsm): Handle and propagate exceptions.
dispatchEvent('js-result', serialize(result));
}, false);
}
function LocalSendPortSync(receivePort) {
this.receivePort = receivePort;
}
LocalSendPortSync.prototype = new SendPortSync();
LocalSendPortSync.prototype.callSync = function(message) {
// TODO(vsm): Do a direct deepcopy.
message = deserialize(serialize(message));
return this.receivePort.callback(message);
}
function DartSendPortSync(isolateId, portId) {
this.isolateId = isolateId;
this.portId = portId;
}
DartSendPortSync.prototype = new SendPortSync();
function dispatchEvent(receiver, message) {
var string = JSON.stringify(message);
var event = document.createEvent('CustomEvent');
event.initCustomEvent(receiver, false, false, string);
window.dispatchEvent(event);
}
function getPortSyncEventData(event) {
return event.detail;
}
DartSendPortSync.prototype.callSync = function(message) {
var serialized = serialize(message);
var target = 'dart-port-' + this.isolateId + '-' + this.portId;
// TODO(vsm): Make this re-entrant.
// TODO(vsm): Set this up set once, on the first call.
var source = target + '-result';
var result = null;
var listener = function (e) {
result = JSON.parse(getPortSyncEventData(e));
};
window.addEventListener(source, listener, false);
dispatchEvent(target, [source, serialized]);
window.removeEventListener(source, listener, false);
return deserialize(result);
}
})();
......@@ -66,6 +66,7 @@ We also have a number of in-progress applications in Labs:
- [AngularJS](http://angularjs.org) + [RequireJS](http://requirejs.org) (using AMD)
- [AngularJS](http://angularjs.org) (optimized)
- [Backbone.xmpp](https://github.com/ggozad/Backbone.xmpp)
- [Dart](http://dartlang.org)
## Live demos
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment