Mais conteúdo relacionado Mais de Eelco Visser (20) mobl1. Slides from keynote at MOSE 2010, Malaga, June 29, 2010
Zef Hemel Eelco Visser
@mobllang @zef @eelcovisser
5. 1.5 million 1.2 million
G1 Droid
outsells iPhone in US
12. 3.3.1 – Applications may only use Documented
APIs in the manner prescribed by Apple and
must not use or call any private APIs.
Applications must be originally written in
Objective-C, C, C++, or JavaScript as executed
by the iPhone OS WebKit engine, and only code
written in C, C++, and Objective-C may compile
and directly link against the Documented APIs
(e.g., Applications that link to Documented APIs
through an intermediary translation or
compatibility layer or tool are prohibited).
20. WebDatabases
Full-screen support
Location information
(GPS)
Offline support
Canvas
Multi-touch Threading
22. “ We believe the web has won and over the next
several years, the browser [..] will become the
platform that matters and certainly that’s where
Google is investing.
”
Vic Gundotra, Google VP of Engineering
26. data model
user interface
script
web service access
28. entity Task {
name : String (searchable)
done : Bool
dueDate : DateTime
}
29. entity Task {
name : String (searchable)
done : Bool
dueDate : DateTime
categories : Collection<Category>
}
entity Category {
name : String
tasks : Collection<Task> (inverse: categories)
}
31. screen root() {
header("Todo")
group {
list(t in Task.all()) {
item {
checkbox(t.done)
" "
label(t.name)
}
}
}
}
32. screen root() {
header("Todo")
topButton("Add", onclick={
addTask();
})
group {
list(t in Task.all()) {
item {
checkbox(t.done)
" "
label(t.name)
}
}
}
}
33. screen addTask() {
var newTask = Task {
done = false,
dueDate = now()
}
header("Add")
backButton("Back", onclick={
screen return;
})
group {
item { textField(newTask.name) }
item { datePicker(newTask.dueDate) }
}
button("Add", onclick={
add(newTask);
screen return;
})
}
34. screen root() {
header("Todo")
topButton("Add", onclick={
addTask();
})
group {
list(t in Task.all()) {
item {
checkbox(t.done)
" "
label(t.name)
}
}
}
}
35. screen root() {
var query = ""
header("Todo")
topButton("Add", onclick={
addTask();
})
searchBox(query)
group {
list(t in Task.search(query)) {
item {
checkbox(t.done)
" "
label(t.name)
}
}
}
}
37. function cleanDoneTasks() : Num {
var removed = 0;
for(t in Task.all()) {
if(t.done) {
remove(t);
removed = removed + 1;
}
}
return removed;
}
43. var amount = 10
var percentage = 10
var total <- amount *
(1 + percentage/100)
inputNum(amount)
inputNum(percentage)
label(total)
47. http://api.stackoverflow.com/0.8/questions?answers=true&body=true
{
"total": 746646,
"page": 1,
"pagesize": 30,
"questions": [
{
"tags": ["string", "assembly", "arm"],
"answers": [],
"question_id": 3092029,
"owner": {
"user_id": 320124,
"user_type": "registered",
"display_name": "SoulBeaver",
"reputation": 195
},
"creation_date": 1277200629,
"score": 0,
"title": "ARM - Infinite Loop While Searching String",
"body": "...",
...
},
...
]
}
48. {
"total": 746646,
"page": 1,
"pagesize": 30,
"questions": [
{
"tags": ["string", "assembly", "arm"],
"answers": [],
"question_id": 3092029,
"owner": {
"user_id": 320124,
"user_type": "registered",
"display_name": "SoulBeaver",
"reputation": 195
},
"creation_date": 1277200629,
"score": 0,
"title": "ARM - Infinite Loop While Searching String",
"body": "...",
...
},
...
]
}
external type QuestionsResultSet {
total : Num
page : Num
pagesize : Num
questions : Array<QuestionResult>
}
49. {
"tags": ["string", "assembly", "arm"],
"answers": [],
"question_id": 3092029,
"owner": {
"user_id": 320124,
"user_type": "registered",
"display_name": "SoulBeaver",
"reputation": 195
},
"creation_date": 1277200629,
"score": 0,
"title": "ARM - Infinite Loop While Searching String",
"body": "...",
...
}
external type QuestionResult {
tags : Array<String>
answers : Array<AnswerResult>
owner : OwnerResult
creation_date : Num
...
}
50. service StackOverflow {
root = "http://api.stackoverflow.com/0.8"
resource questions(answers : Bool, body : Bool) : QuestionsResultSet {
uri = "/questions"
method = "GET"
encoding = "json"
}
...
}
51. function fetchQuestions() {
var res = StackOverflow.questions(answers=true, body=true);
for(question : QuestionResult in res.questions) {
mapQuestion(question);
}
}
52. entity Question {
questionId : Num
title : String
body : Text
answers : Collection<Answer> (inverse: question)
creationDate : DateTime
owner : User
}
entity Answer {
question : Question
answerId : Num
owner : User
body : Text
}
entity User {
userId : Num
name : String
reputation : Num
}
53. function mapQuestion(qr : QuestionResult) : Question {
var q : Question = cachedQuestion(remote.question_id);
if(q == null) {
q = Question {
questionId = qr.question_id,
title = qr.title,
body = qr.body,
answers = mapAnswers(qr.answers),
creationDate = DateTime.fromTimestamp(qr.creation_date),
owner = mapUser(qr.owner)
};
add(q);
}
return q;
}
56. mobl code
parse
check
desugar
generate
code
HTML/Javascript
57. entity Task {
name : String (searchable)
done : Bool
dueDate : DateTime
}
Javascript using
persistence.js
HTML5 ORM
tasks.Task = persistence.define('tasks__Task', {
'name': 'TEXT',
'done': 'BOOL',
'dueDate': 'DATE'
});
tasks.Task.textIndex('name');
58. screen root() {
header("Todo")
...
}
Javascript functions
building DOM
tasks.root = function(callback, screenCallback) {
var root1018 = $("<div>");
mobl.header(ref("Todo"), function(node) {
root1018.append(node);
...
});
};
59. function cleanDoneTasks() : Num {
var removed = 0;
for(t in Task.all()) {
if(t.done) {
remove(t);
removed = removed + 1;
}
}
return removed;
}
tasks.cleanDoneTasks = function() {
var removed = 0;
var results = Task.all();
for(var i = 0; i < results.length; i++) {
var t = results[i];
if(t.done) {
remove(t);
removed = removed + 1;
}
}
return removed;
}
60. function cleanDoneTasks() : Num {
var removed = 0;
for(t in Task.all()) {
if(t.done) {
remove(t);
removed = removed + 1;
}
}
return removed;
}
tasks.cleanDoneTasks = function() {
var removed = 0;
var results = Task.all();
for(var i = 0; i < results.length; i++) {
var t = results[i];
if(t.done) {
remove(t);
removed = removed + 1;
}
}
return removed;
};
61. tasks.cleanDoneTasks = function() {
var removed = 0;
var results = Task.all();
for(var i = 0; i < results.length; i++) {
var t = results[i];
if(t.done) {
remove(t);
removed = removed + 1;
}
}
return removed;
};
continuation-passing
style transform
tasks.cleanDoneTasks = function(callback) {
var removed = 0;
Task.all(function(results) {
for(var i = 0; i < results.length; i++) {
var t = results[i];
if(t.done) {
remove(t);
removed = removed + 1;
}
}
callback(removed);
});
};
63. screen root() {
var n = 8
label(n * n)
button("Inc", onclick={
n = n + 1;
})
}
64. var n = 8
var n = ref(8);
Observable
- set(value)
- get()
- addEventListener(eventType, callback)
65. label(n * n)
var node565 = $("<span>");
node565.text(n.get() * n.get());
n.addEventListener("change", function() {
node565.text(n.get() * n.get());
});
root.append(node565);
66. button("Inc", onclick={
n = n + 1;
})
var nodes566 = $("<span class='button'>");
node566.text("Inc");
node566.click(function() {
n.set(n.get() + 1);
});
root.append(node566);
67. screen root() {
var n = 8
label(n * n)
button("Inc", onclick={
n = n + 1;
})
}