Merge branch 'web-world'
Conflicts: scribblings/cs19.scrbl
This commit is contained in:
commit
efc8dcdf9f
|
@ -174,7 +174,7 @@
|
||||||
(first sources))]
|
(first sources))]
|
||||||
[(ast stmts)
|
[(ast stmts)
|
||||||
(get-ast-and-statements this-source)])
|
(get-ast-and-statements this-source)])
|
||||||
(log-debug "visiting")
|
(log-debug (format "visiting ~a\n" (source-name this-source)))
|
||||||
(on-module-statements this-source ast stmts)
|
(on-module-statements this-source ast stmts)
|
||||||
(loop (append (map wrap-source (collect-new-dependencies this-source ast))
|
(loop (append (map wrap-source (collect-new-dependencies this-source ast))
|
||||||
(rest sources)))
|
(rest sources)))
|
||||||
|
|
|
@ -216,3 +216,4 @@ For example,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,7 @@ will be:
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
Example 3
|
Example 3 "field"
|
||||||
|
|
||||||
|
|
||||||
We want to make it easy to query from the view. That's why each
|
We want to make it easy to query from the view. That's why each
|
||||||
|
|
|
@ -1,8 +1,107 @@
|
||||||
<!DOCTYPE html>
|
<html>
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
<head><title>Animation</title>
|
||||||
<head>
|
<link rel="stylesheet" href="style.css"/>
|
||||||
<meta name="viewport" content="initial-scale=1.0, width=device-width, height=device-height, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
</head>
|
||||||
<meta charset="utf-8"/>
|
<body>
|
||||||
<title></title>
|
<p>
|
||||||
</head>
|
This should be animating:
|
||||||
<script>
|
<hr/>
|
||||||
|
<div>
|
||||||
|
<div class="selectedBlock" id="0"></div>
|
||||||
|
<div class="block" id="1"></div>
|
||||||
|
<div class="block" id="2"></div>
|
||||||
|
<div class="block" id="3"></div>
|
||||||
|
<div class="block" id="4"></div>
|
||||||
|
<div class="block" id="5"></div>
|
||||||
|
<div class="block" id="6"></div>
|
||||||
|
<div class="block" id="7"></div>
|
||||||
|
<div class="block" id="8"></div>
|
||||||
|
<div class="block" id="9"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
The program for this is:
|
||||||
|
<blockquote>
|
||||||
|
<pre>
|
||||||
|
#lang planet dyoo/whalesong
|
||||||
|
|
||||||
|
(require (planet dyoo/whalesong/resource)
|
||||||
|
(planet dyoo/whalesong/web-world))
|
||||||
|
|
||||||
|
(define-resource index.html)
|
||||||
|
(define-resource style.css)
|
||||||
|
|
||||||
|
(define (tick w v)
|
||||||
|
(modulo (add1 w) 10))
|
||||||
|
|
||||||
|
|
||||||
|
;; pick-block: world view -> view
|
||||||
|
;; Focus the view on block i.
|
||||||
|
(define (pick-block v i)
|
||||||
|
(view-focus v (format "#~a" i)))
|
||||||
|
|
||||||
|
|
||||||
|
(define (draw w v)
|
||||||
|
(define v1 (update-view-attr
|
||||||
|
(pick-block v w)
|
||||||
|
"class"
|
||||||
|
"selectedBlock"))
|
||||||
|
(define v2 (update-view-attr
|
||||||
|
(pick-block v1 (modulo (sub1 w) 10))
|
||||||
|
"class"
|
||||||
|
"offsetBlock"))
|
||||||
|
(define v3 (update-view-attr
|
||||||
|
(pick-block v2 (modulo (add1 w) 10))
|
||||||
|
"class"
|
||||||
|
"offsetBlock"))
|
||||||
|
(define v4 (update-view-attr
|
||||||
|
(pick-block v3 (modulo (- w 2) 10))
|
||||||
|
"class"
|
||||||
|
"block"))
|
||||||
|
(define v5 (update-view-attr
|
||||||
|
(pick-block v4 (modulo (+ w 2) 10))
|
||||||
|
"class"
|
||||||
|
"block"))
|
||||||
|
v5)
|
||||||
|
|
||||||
|
|
||||||
|
(big-bang 0
|
||||||
|
(initial-view index.html)
|
||||||
|
(on-tick tick)
|
||||||
|
(to-draw draw))
|
||||||
|
</pre>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
|
||||||
|
with <tt>style.css</tt>:
|
||||||
|
<blockquote>
|
||||||
|
<pre>
|
||||||
|
.block {
|
||||||
|
width : 80px;
|
||||||
|
height : 10px;
|
||||||
|
background-color : blue;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectedBlock {
|
||||||
|
width : 80px;
|
||||||
|
height : 10px;
|
||||||
|
background-color: navy;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.offsetBlock {
|
||||||
|
width : 80px;
|
||||||
|
height : 10px;
|
||||||
|
background-color: teal;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
53
web-world/examples/dwarves/dwarves.rkt
Normal file
53
web-world/examples/dwarves/dwarves.rkt
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
#lang planet dyoo/whalesong
|
||||||
|
(require (planet dyoo/whalesong/web-world)
|
||||||
|
(planet dyoo/whalesong/resource))
|
||||||
|
(define-resource index.html)
|
||||||
|
|
||||||
|
;; The world is the set of dwarfs.
|
||||||
|
|
||||||
|
|
||||||
|
;; make-item: string -> view
|
||||||
|
(define (make-item name)
|
||||||
|
(view-bind (->view `(li ,name))
|
||||||
|
"click"
|
||||||
|
hide-on-click))
|
||||||
|
|
||||||
|
|
||||||
|
;; When a dwarf clicks, it hides!
|
||||||
|
(define (hide-on-click w v)
|
||||||
|
(remove (view-id v) w))
|
||||||
|
|
||||||
|
|
||||||
|
(define dwarf-names
|
||||||
|
'("Doc" "Grumpy" "Happy" "Sleepy" "Bashful" "Sneezy" "Dopey"))
|
||||||
|
|
||||||
|
|
||||||
|
;; Update the view so it shows the next dwarf on the scene,
|
||||||
|
;; until we're all done.
|
||||||
|
(define (draw w dom-view)
|
||||||
|
(foldl (lambda (name view)
|
||||||
|
(define focused (view-focus view (format "#~a" name)))
|
||||||
|
(cond
|
||||||
|
[(member name w)
|
||||||
|
(view-show focused)]
|
||||||
|
[else
|
||||||
|
(view-hide focused)]))
|
||||||
|
dom-view
|
||||||
|
dwarf-names))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;; The first view consists of index.html. We attach event handlers
|
||||||
|
;; to each name here.
|
||||||
|
(define my-view
|
||||||
|
(foldl (lambda (name view)
|
||||||
|
(view-bind (view-focus view (format "#~a" name))
|
||||||
|
"click"
|
||||||
|
hide-on-click))
|
||||||
|
(->view index.html)
|
||||||
|
dwarf-names))
|
||||||
|
|
||||||
|
|
||||||
|
(big-bang dwarf-names
|
||||||
|
(initial-view my-view)
|
||||||
|
(to-draw draw))
|
16
web-world/examples/dwarves/index.html
Normal file
16
web-world/examples/dwarves/index.html
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<html>
|
||||||
|
<head><title>Dwarves</title></head>
|
||||||
|
<body>
|
||||||
|
<h1>Dwarfs from Snow White</h1>
|
||||||
|
<p>Click on a dwarf to make them hide.</p>
|
||||||
|
<ul id="list">
|
||||||
|
<li id="Doc">Doc</li>
|
||||||
|
<li id="Grumpy">Grumpy</li>
|
||||||
|
<li id="Happy">Happy</li>
|
||||||
|
<li id="Sleepy">Sleepy</li>
|
||||||
|
<li id="Bashful">Bashful</li>
|
||||||
|
<li id="Sneezy">Sneezy</li>
|
||||||
|
<li id="Dopey">Dopey</li>
|
||||||
|
</ul>
|
||||||
|
</body>
|
||||||
|
</html>
|
31
web-world/examples/field/field.rkt
Normal file
31
web-world/examples/field/field.rkt
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#lang planet dyoo/whalesong
|
||||||
|
(require (planet dyoo/whalesong/web-world)
|
||||||
|
(planet dyoo/whalesong/resource))
|
||||||
|
|
||||||
|
(define-resource index.html)
|
||||||
|
|
||||||
|
;; The world is a string which represents the name of the user.
|
||||||
|
|
||||||
|
|
||||||
|
;; on-click: world view -> world
|
||||||
|
;; When the user clicks on the button, grab at the text of the
|
||||||
|
;; text-field.
|
||||||
|
(define (on-click w button-view)
|
||||||
|
(view-form-value (view-focus button-view "#text-field")))
|
||||||
|
|
||||||
|
|
||||||
|
;; draw: world view -> view
|
||||||
|
;; Take the view, and replace the template with the world value.
|
||||||
|
(define (draw w dom)
|
||||||
|
(update-view-text (view-focus dom "#template")
|
||||||
|
w))
|
||||||
|
|
||||||
|
|
||||||
|
(define my-view (view-bind (view-focus (->view index.html)
|
||||||
|
"#button")
|
||||||
|
"click"
|
||||||
|
on-click))
|
||||||
|
|
||||||
|
(big-bang "Jane Doe"
|
||||||
|
(initial-view my-view)
|
||||||
|
(to-draw draw))
|
12
web-world/examples/field/index.html
Normal file
12
web-world/examples/field/index.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>My simple program</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<input type="text" id="text-field"/>
|
||||||
|
<input type="button" id="button" value="Click me"/>
|
||||||
|
|
||||||
|
<p>Hello <span id="template">fill-me-in</span>!</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -35,7 +35,17 @@
|
||||||
view-text
|
view-text
|
||||||
update-view-text
|
update-view-text
|
||||||
|
|
||||||
|
view-bind
|
||||||
|
|
||||||
|
view-show
|
||||||
|
view-hide
|
||||||
|
|
||||||
view-attr
|
view-attr
|
||||||
update-view-attr
|
update-view-attr
|
||||||
|
|
||||||
|
view-id
|
||||||
|
|
||||||
|
view-form-value
|
||||||
|
update-view-form-value
|
||||||
|
view-append-child
|
||||||
))
|
))
|
||||||
|
|
3
web-world/info.rkt
Normal file
3
web-world/info.rkt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#lang setup/infotab
|
||||||
|
|
||||||
|
(define compile-omit-paths '("examples"))
|
|
@ -11,10 +11,45 @@
|
||||||
var isString = plt.baselib.strings.isString;
|
var isString = plt.baselib.strings.isString;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// FIXME: as soon as we get real parameters, use parameters
|
||||||
|
// instead. Global: defines the currently running big bang.
|
||||||
|
// Parameterized around the call to bigBang.
|
||||||
|
var currentBigBangRecord = undefined;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var resourceStructType =
|
var resourceStructType =
|
||||||
MACHINE.modules['whalesong/resource/structs.rkt'].namespace['struct:resource'];
|
MACHINE.modules['whalesong/resource/structs.rkt'].namespace['struct:resource'];
|
||||||
|
|
||||||
|
|
||||||
|
var domToCursor = function(dom) {
|
||||||
|
var domOpenF =
|
||||||
|
// To go down, just take the children.
|
||||||
|
function(n) {
|
||||||
|
return [].slice.call(n.childNodes, 0);
|
||||||
|
};
|
||||||
|
var domCloseF =
|
||||||
|
// To go back up, take the node, do a shallow cloning, and replace the children.
|
||||||
|
function(node, children) {
|
||||||
|
var i;
|
||||||
|
var newNode = node.cloneNode(false);
|
||||||
|
for (i = 0; i < children.length; i++) {
|
||||||
|
newNode.appendChild(children[i].cloneNode(true));
|
||||||
|
}
|
||||||
|
return newNode;
|
||||||
|
};
|
||||||
|
var domAtomicF =
|
||||||
|
function(node) {
|
||||||
|
return node.nodeType !== 1;
|
||||||
|
};
|
||||||
|
return TreeCursor.adaptTreeCursor(dom.cloneNode(true),
|
||||||
|
domOpenF,
|
||||||
|
domCloseF,
|
||||||
|
domAtomicF);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,18 +104,24 @@
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
var MockView = function(cursor, pendingActions, nonce) {
|
// A MockView provides a functional interface to the DOM. It
|
||||||
|
// includes a cursor to the currently focused dom, the pending
|
||||||
|
// actions to perform on the actual view, and a nonce to detect
|
||||||
|
// freshness of the MockView.
|
||||||
|
var MockView = function(cursor, pendingActions, eventHandlers, nonce) {
|
||||||
this.cursor = cursor;
|
this.cursor = cursor;
|
||||||
this.pendingActions = pendingActions;
|
this.pendingActions = pendingActions;
|
||||||
|
this.eventHandlers = eventHandlers;
|
||||||
this.nonce = nonce;
|
this.nonce = nonce;
|
||||||
};
|
};
|
||||||
|
|
||||||
var isMockView = plt.baselib.makeClassPredicate(MockView);
|
var isMockView = plt.baselib.makeClassPredicate(MockView);
|
||||||
|
|
||||||
MockView.prototype.act = function(actionForCursor, actionForReal) {
|
MockView.prototype.act = function(actionForCursor, actionForEventHandlers, actionForReal) {
|
||||||
if (arguments.length !== 2) { throw new Error("act: insufficient arguments"); }
|
if (arguments.length !== 3) { throw new Error("act: insufficient arguments"); }
|
||||||
return new MockView(actionForCursor(this.cursor),
|
return new MockView(actionForCursor(this.cursor),
|
||||||
this.pendingActions.concat([actionForReal]),
|
this.pendingActions.concat([actionForReal]),
|
||||||
|
actionForEventHandlers(this.eventHandlers),
|
||||||
this.nonce);
|
this.nonce);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -100,6 +141,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
function(eventHandlers) { return eventHandlers; },
|
||||||
function(view) {
|
function(view) {
|
||||||
view.focus = view.top.find(selector);
|
view.focus = view.top.find(selector);
|
||||||
}
|
}
|
||||||
|
@ -115,30 +157,59 @@
|
||||||
function(cursor) {
|
function(cursor) {
|
||||||
return cursor.replaceNode($(cursor.node).clone(true).text(text).get(0));
|
return cursor.replaceNode($(cursor.node).clone(true).text(text).get(0));
|
||||||
},
|
},
|
||||||
|
function(eventHandlers) { return eventHandlers; },
|
||||||
function(view) {
|
function(view) {
|
||||||
view.focus.text(text);
|
view.focus.text(text);
|
||||||
})
|
}
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
MockView.prototype.getAttr = function(name) {
|
MockView.prototype.getAttr = function(name) {
|
||||||
return $(this.cursor.node).attr(name);
|
return $(this.cursor.node).attr(name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
MockView.prototype.updateAttr = function(name, value) {
|
MockView.prototype.updateAttr = function(name, value) {
|
||||||
return this.act(
|
return this.act(
|
||||||
function(cursor) {
|
function(cursor) {
|
||||||
return cursor.replaceNode($(cursor.node).clone(true).attr(name, value).get(0));
|
return cursor.replaceNode($(cursor.node).clone(true).attr(name, value).get(0));
|
||||||
},
|
},
|
||||||
|
function(eventHandlers) {
|
||||||
|
return eventHandlers;
|
||||||
|
},
|
||||||
function(view) {
|
function(view) {
|
||||||
view.focus.attr(name, value);
|
view.focus.attr(name, value);
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
MockView.prototype.getFormValue = function() {
|
||||||
|
return $(this.cursor.node).val();
|
||||||
|
};
|
||||||
|
|
||||||
|
MockView.prototype.updateFormValue = function(value) {
|
||||||
|
return this.act(
|
||||||
|
function(cursor) {
|
||||||
|
return cursor.replaceNode($(cursor.node).clone(true).val(value).get(0));
|
||||||
|
},
|
||||||
|
function(eventHandlers) {
|
||||||
|
return eventHandlers;
|
||||||
|
},
|
||||||
|
function(view) {
|
||||||
|
view.focus.val(value);
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MockView.prototype.left = function() {
|
MockView.prototype.left = function() {
|
||||||
return this.act(
|
return this.act(
|
||||||
function(cursor) {
|
function(cursor) {
|
||||||
return cursor.left();
|
return cursor.left();
|
||||||
},
|
},
|
||||||
|
function(eventHandlers) {
|
||||||
|
return eventHandlers;
|
||||||
|
},
|
||||||
function(view) {
|
function(view) {
|
||||||
view.focus = view.focus.prev();
|
view.focus = view.focus.prev();
|
||||||
});
|
});
|
||||||
|
@ -149,6 +220,9 @@
|
||||||
function(cursor) {
|
function(cursor) {
|
||||||
return cursor.right();
|
return cursor.right();
|
||||||
},
|
},
|
||||||
|
function(eventHandlers) {
|
||||||
|
return eventHandlers;
|
||||||
|
},
|
||||||
function(view) {
|
function(view) {
|
||||||
view.focus = view.focus.next();
|
view.focus = view.focus.next();
|
||||||
});
|
});
|
||||||
|
@ -159,6 +233,9 @@
|
||||||
function(cursor) {
|
function(cursor) {
|
||||||
return cursor.up();
|
return cursor.up();
|
||||||
},
|
},
|
||||||
|
function(eventHandlers) {
|
||||||
|
return eventHandlers;
|
||||||
|
},
|
||||||
function(view) {
|
function(view) {
|
||||||
view.focus = view.focus.parent();
|
view.focus = view.focus.parent();
|
||||||
});
|
});
|
||||||
|
@ -169,11 +246,113 @@
|
||||||
function(cursor) {
|
function(cursor) {
|
||||||
return cursor.down();
|
return cursor.down();
|
||||||
},
|
},
|
||||||
|
function(eventHandlers) {
|
||||||
|
return eventHandlers;
|
||||||
|
},
|
||||||
function(view) {
|
function(view) {
|
||||||
view.focus = view.focus.children(':first');
|
view.focus = view.focus.children(':first');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var mockViewIdGensym = 0;
|
||||||
|
|
||||||
|
MockView.prototype.bind = function(name, worldF) {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
// HACK: every node that is bound needs to have an id. We
|
||||||
|
// enforce this by mutating the node.
|
||||||
|
if (! this.cursor.node.id) {
|
||||||
|
this.cursor.node.id = ("__webWorldId_" + mockViewIdGensym++);
|
||||||
|
}
|
||||||
|
return this.act(
|
||||||
|
function(cursor) {
|
||||||
|
var newCursor = cursor.replaceNode($(cursor.node).clone(true).get(0));
|
||||||
|
var handler = new EventHandler(name,
|
||||||
|
new DomEventSource(name, newCursor.node),
|
||||||
|
worldF);
|
||||||
|
if (currentBigBangRecord !== undefined) {
|
||||||
|
currentBigBangRecord.startEventHandler(handler);
|
||||||
|
}
|
||||||
|
return newCursor;
|
||||||
|
},
|
||||||
|
function(eventHandlers) {
|
||||||
|
var handler = new EventHandler(name,
|
||||||
|
new DomEventSource(
|
||||||
|
name,
|
||||||
|
that.cursor.node.id),
|
||||||
|
worldF);
|
||||||
|
return eventHandlers.concat([handler]);
|
||||||
|
},
|
||||||
|
function(view) {
|
||||||
|
// HACK: every node that is bound needs to have an id. We
|
||||||
|
// enforce this by mutating the node.
|
||||||
|
if (! view.focus.get(0).id) {
|
||||||
|
view.focus.get(0).id = ("__webWorldId_" + mockViewIdGensym++);
|
||||||
|
}
|
||||||
|
var handler = new EventHandler(name,
|
||||||
|
new DomEventSource(
|
||||||
|
name,
|
||||||
|
view.focus.get(0).id),
|
||||||
|
worldF);
|
||||||
|
view.addEventHandler(handler);
|
||||||
|
currentBigBangRecord.startEventHandler(handler);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
MockView.prototype.show = function() {
|
||||||
|
return this.act(
|
||||||
|
function(cursor) {
|
||||||
|
return cursor.replaceNode($(cursor.node).clone(true).show().get(0));
|
||||||
|
},
|
||||||
|
function(eventHandlers) { return eventHandlers; },
|
||||||
|
function(view) {
|
||||||
|
view.focus.show();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
MockView.prototype.hide = function() {
|
||||||
|
return this.act(
|
||||||
|
function(cursor) {
|
||||||
|
return cursor.replaceNode($(cursor.node).clone(true).hide().get(0));
|
||||||
|
},
|
||||||
|
function(eventHandlers) { return eventHandlers; },
|
||||||
|
function(view) {
|
||||||
|
view.focus.hide();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
MockView.prototype.appendChild = function(domNode) {
|
||||||
|
return this.act(
|
||||||
|
function(cursor) {
|
||||||
|
if (cursor.canDown()) {
|
||||||
|
cursor = cursor.down();
|
||||||
|
while (cursor.canRight()) {
|
||||||
|
cursor = cursor.right();
|
||||||
|
}
|
||||||
|
return cursor.insertRight(domNode.cloneNode(true));
|
||||||
|
} else {
|
||||||
|
return cursor.insertDown(domNode.cloneNode(true));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
function(eventHandlers) { return eventHandlers; },
|
||||||
|
function(view) {
|
||||||
|
var clone = $(domNode).clone(true);
|
||||||
|
clone.appendTo(view.focus);
|
||||||
|
view.focus = clone;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
MockView.prototype.id = function() {
|
||||||
|
return this.cursor.node.id;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -205,6 +384,10 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
View.prototype.addEventHandler = function(handler) {
|
||||||
|
this.eventHandlers.push(handler);
|
||||||
|
};
|
||||||
|
|
||||||
// Return a list of the event sources from the view.
|
// Return a list of the event sources from the view.
|
||||||
// fixme: may need to apply the pending actions to get the real set.
|
// fixme: may need to apply the pending actions to get the real set.
|
||||||
View.prototype.getEventHandlers = function() {
|
View.prototype.getEventHandlers = function() {
|
||||||
|
@ -213,7 +396,8 @@
|
||||||
|
|
||||||
View.prototype.getMockAndResetFocus = function(nonce) {
|
View.prototype.getMockAndResetFocus = function(nonce) {
|
||||||
this.focus = this.top;
|
this.focus = this.top;
|
||||||
return new MockView(TreeCursor.domToCursor($(this.top).get(0)),
|
return new MockView(domToCursor($(this.top).get(0)),
|
||||||
|
[],
|
||||||
[],
|
[],
|
||||||
nonce);
|
nonce);
|
||||||
};
|
};
|
||||||
|
@ -252,7 +436,9 @@
|
||||||
return onFail(exn);
|
return onFail(exn);
|
||||||
}
|
}
|
||||||
return onSuccess(new View(dom, []));
|
return onSuccess(new View(dom, []));
|
||||||
|
} else if (isMockView(x)) {
|
||||||
|
return onSuccess(new View($(x.cursor.top().node),
|
||||||
|
x.eventHandlers));
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
dom = $(plt.baselib.format.toDomNode(x))
|
dom = $(plt.baselib.format.toDomNode(x))
|
||||||
|
@ -277,18 +463,52 @@
|
||||||
} catch (exn) {
|
} catch (exn) {
|
||||||
return onFail(exn);
|
return onFail(exn);
|
||||||
}
|
}
|
||||||
return onSuccess(new MockView(TreeCursor.domToCursor(dom.get(0)), [], undefined));
|
return onSuccess(new MockView(domToCursor(dom.get(0)), [], [], undefined));
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
dom = $(plt.baselib.format.toDomNode(x))
|
dom = $(plt.baselib.format.toDomNode(x))
|
||||||
} catch (exn) {
|
} catch (exn) {
|
||||||
return onFail(exn);
|
return onFail(exn);
|
||||||
}
|
}
|
||||||
return onSuccess(new MockView(TreeCursor.domToCursor(dom.get(0)), [], undefined));
|
return onSuccess(new MockView(domToCursor(dom.get(0)), [], [], undefined));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var coerseToDomNode = function(x, onSuccess, onFail) {
|
||||||
|
var dom;
|
||||||
|
if (isDomNode(x)) {
|
||||||
|
return onSuccess(x);
|
||||||
|
} else if (isResource(x)) {
|
||||||
|
try {
|
||||||
|
dom = $(resourceContent(x).toString())
|
||||||
|
.css("margin", "0px")
|
||||||
|
.css("padding", "0px")
|
||||||
|
.css("border", "0px");
|
||||||
|
} catch (exn) {
|
||||||
|
return onFail(exn);
|
||||||
|
}
|
||||||
|
return onSuccess(dom.get(0));
|
||||||
|
} else if (isMockView(x)) {
|
||||||
|
return onSuccess(x.cursor.top().node);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
dom = plt.baselib.format.toDomNode(x);
|
||||||
|
} catch (exn) {
|
||||||
|
return onFail(exn);
|
||||||
|
}
|
||||||
|
return onSuccess(dom);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var isDomNode = function(x) {
|
||||||
|
return (x.hasOwnProperty('nodeType') &&
|
||||||
|
x.nodeType === 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -339,6 +559,8 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// An EventHandler combines a EventSource with a racketWorldCallback.
|
||||||
|
|
||||||
var EventHandler = function(name, eventSource, racketWorldCallback) {
|
var EventHandler = function(name, eventSource, racketWorldCallback) {
|
||||||
WorldHandler.call(this);
|
WorldHandler.call(this);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@ -379,7 +601,9 @@
|
||||||
|
|
||||||
/* Event sources.
|
/* Event sources.
|
||||||
|
|
||||||
An event source are the inputs to a web world program.
|
An event source is a way to send input to a web-world program.
|
||||||
|
|
||||||
|
An event source may be started or stopped.
|
||||||
|
|
||||||
|
|
||||||
Pause and Unpause are semantically meant to be cheaper than start, stop, so
|
Pause and Unpause are semantically meant to be cheaper than start, stop, so
|
||||||
|
@ -405,7 +629,8 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Clock ticks.
|
|
||||||
|
// TickEventSource sends tick events.
|
||||||
var TickEventSource = function(delay) {
|
var TickEventSource = function(delay) {
|
||||||
this.delay = delay; // delay in milliseconds.
|
this.delay = delay; // delay in milliseconds.
|
||||||
|
|
||||||
|
@ -419,7 +644,7 @@
|
||||||
TickEventSource.prototype.onStart = function(fireEvent) {
|
TickEventSource.prototype.onStart = function(fireEvent) {
|
||||||
this.id = setInterval(
|
this.id = setInterval(
|
||||||
function() {
|
function() {
|
||||||
fireEvent();
|
fireEvent(undefined);
|
||||||
},
|
},
|
||||||
this.delay);
|
this.delay);
|
||||||
};
|
};
|
||||||
|
@ -432,27 +657,43 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// DomElementSource: string (U DOM string) -> EventSource
|
||||||
var BindEventSource = function(type, element) {
|
// A DomEventSource allows DOM elements to send events over to
|
||||||
|
// web-world.
|
||||||
|
var DomEventSource = function(type, elementOrId) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.element = element;
|
this.elementOrId = elementOrId;
|
||||||
this.handler = undefined;
|
this.handler = undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
BindEventSource.prototype = plt.baselib.heir(EventSource.prototype);
|
DomEventSource.prototype = plt.baselib.heir(EventSource.prototype);
|
||||||
|
|
||||||
BindEventSource.prototype.onStart = function(fireEvent) {
|
DomEventSource.prototype.onStart = function(fireEvent) {
|
||||||
this.handler =
|
var element = this.elementOrId;
|
||||||
function(evt) {
|
if (typeof(this.elementOrId) === 'string') {
|
||||||
fireEvent(evt);
|
element = $('#' + this.elementOrId).get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.handler = function(evt) {
|
||||||
|
if (element !== undefined) {
|
||||||
|
fireEvent(element, evt);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
$(this.element).bind(this.type,
|
if (element !== undefined) {
|
||||||
this.handler);
|
$(element).bind(this.type, this.handler);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
BindEventSource.prototype.onStop = function() {
|
DomEventSource.prototype.onStop = function() {
|
||||||
|
var element = this.elementOrId;
|
||||||
|
if (typeof(this.elementOrId) === 'string') {
|
||||||
|
element = $('#' + this.elementOrId).get(0);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.handler !== undefined) {
|
if (this.handler !== undefined) {
|
||||||
$(this.element).unbind(this.type, this.handler);
|
if (element !== undefined) {
|
||||||
|
$(element).unbind(this.type, this.handler);
|
||||||
|
}
|
||||||
this.handler = undefined;
|
this.handler = undefined;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -479,7 +720,8 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
var EventQueueElement = function(handler, data) {
|
var EventQueueElement = function(who, handler, data) {
|
||||||
|
this.who = who;
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
};
|
};
|
||||||
|
@ -499,6 +741,7 @@
|
||||||
// bigBang.
|
// bigBang.
|
||||||
var bigBang = function(MACHINE, world, handlers) {
|
var bigBang = function(MACHINE, world, handlers) {
|
||||||
var oldArgcount = MACHINE.argcount;
|
var oldArgcount = MACHINE.argcount;
|
||||||
|
var oldCurrentBigBangRecord = currentBigBangRecord;
|
||||||
|
|
||||||
var running = true;
|
var running = true;
|
||||||
var dispatchingEvents = false;
|
var dispatchingEvents = false;
|
||||||
|
@ -510,34 +753,74 @@
|
||||||
var eventQueue = new EventQueue();
|
var eventQueue = new EventQueue();
|
||||||
|
|
||||||
var top = $("<div/>");
|
var top = $("<div/>");
|
||||||
|
var eventHandlers = filter(handlers, isEventHandler).concat(view.getEventHandlers());
|
||||||
|
|
||||||
MACHINE.params.currentDisplayer(MACHINE, top);
|
MACHINE.params.currentDisplayer(MACHINE, top);
|
||||||
|
|
||||||
PAUSE(function(restart) {
|
PAUSE(function(restart) {
|
||||||
|
var i;
|
||||||
|
|
||||||
var onCleanRestart = function() {
|
var onCleanRestart = function() {
|
||||||
running = false;
|
running = false;
|
||||||
var i;
|
stopEventHandlers();
|
||||||
for (i = 0; i < eventHandlers.length; i++) {
|
|
||||||
stopEventHandler(eventHandlers[i]);
|
|
||||||
}
|
|
||||||
restart(function(MACHINE) {
|
restart(function(MACHINE) {
|
||||||
MACHINE.argcount = oldArgcount;
|
MACHINE.argcount = oldArgcount;
|
||||||
|
currentBigBangRecord = oldCurrentBigBangRecord;
|
||||||
finalizeClosureCall(MACHINE, world);
|
finalizeClosureCall(MACHINE, world);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var onMessyRestart = function(exn) {
|
var onMessyRestart = function(exn) {
|
||||||
running = false;
|
running = false;
|
||||||
var i;
|
stopEventHandlers();
|
||||||
for (i = 0; i < eventHandlers.length; i++) {
|
|
||||||
stopEventHandler(eventHandlers[i]);
|
|
||||||
}
|
|
||||||
restart(function(MACHINE) {
|
restart(function(MACHINE) {
|
||||||
|
currentBigBangRecord = oldCurrentBigBangRecord;
|
||||||
plt.baselib.exceptions.raise(MACHINE, exn);
|
plt.baselib.exceptions.raise(MACHINE, exn);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var dispatchEventsInQueue = function() {
|
var startEventHandlers = function() {
|
||||||
|
var i;
|
||||||
|
for (i = 0; i < eventHandlers.length; i++) {
|
||||||
|
startEventHandler(eventHandlers[i]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var stopEventHandlers = function() {
|
||||||
|
var i;
|
||||||
|
for (i = 0; i < eventHandlers.length; i++) {
|
||||||
|
stopEventHandler(eventHandlers[i]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var startEventHandler = function(handler) {
|
||||||
|
var fireEvent = function(who) {
|
||||||
|
if (! running) { return; }
|
||||||
|
var args = [].slice.call(arguments, 1);
|
||||||
|
eventQueue.queue(new EventQueueElement(who, handler, args));
|
||||||
|
if (! dispatchingEvents) {
|
||||||
|
dispatchingEvents = true;
|
||||||
|
setTimeout(
|
||||||
|
function() {
|
||||||
|
dispatchEventsInQueue(
|
||||||
|
function() {
|
||||||
|
refreshView(function() {},
|
||||||
|
onMessyRestart);
|
||||||
|
},
|
||||||
|
onMessyRestart);
|
||||||
|
},
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
handler.eventSource.onStart(fireEvent);
|
||||||
|
};
|
||||||
|
|
||||||
|
var stopEventHandler = function(handler) {
|
||||||
|
handler.eventSource.onStop();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var dispatchEventsInQueue = function(success, fail) {
|
||||||
// Apply all the events on the queue, call toDraw, and then stop.
|
// Apply all the events on the queue, call toDraw, and then stop.
|
||||||
// If the world ever satisfies stopWhen, stop immediately and quit.
|
// If the world ever satisfies stopWhen, stop immediately and quit.
|
||||||
var nextEvent;
|
var nextEvent;
|
||||||
|
@ -549,8 +832,11 @@
|
||||||
// Set up the proxy object so we can do what appear to be functional
|
// Set up the proxy object so we can do what appear to be functional
|
||||||
// queries.
|
// queries.
|
||||||
mockView = view.getMockAndResetFocus();
|
mockView = view.getMockAndResetFocus();
|
||||||
|
|
||||||
nextEvent = eventQueue.dequeue();
|
nextEvent = eventQueue.dequeue();
|
||||||
|
if (nextEvent.who !== undefined) {
|
||||||
|
mockView = mockView.updateFocus('#' + nextEvent.who.id);
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: deal with event data here
|
// FIXME: deal with event data here
|
||||||
racketWorldCallback = nextEvent.handler.racketWorldCallback;
|
racketWorldCallback = nextEvent.handler.racketWorldCallback;
|
||||||
racketWorldCallback(MACHINE,
|
racketWorldCallback(MACHINE,
|
||||||
|
@ -564,24 +850,25 @@
|
||||||
mockView,
|
mockView,
|
||||||
function(shouldStop) {
|
function(shouldStop) {
|
||||||
if (shouldStop) {
|
if (shouldStop) {
|
||||||
refreshViewAndStopDispatching(
|
refreshView(
|
||||||
function() {
|
function() {
|
||||||
onCleanRestart();
|
onCleanRestart();
|
||||||
},
|
},
|
||||||
onMessyRestart);
|
fail);
|
||||||
} else {
|
} else {
|
||||||
dispatchEventsInQueue();
|
dispatchEventsInQueue(success, fail);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onMessyRestart);
|
fail);
|
||||||
},
|
},
|
||||||
onMessyRestart);
|
fail);
|
||||||
} else {
|
} else {
|
||||||
refreshViewAndStopDispatching(function() {}, onMessyRestart);
|
dispatchingEvents = false;
|
||||||
|
success();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var refreshViewAndStopDispatching = function(success, failure) {
|
var refreshView = function(success, failure) {
|
||||||
// Note: we create a random nonce, and watch to see if the MockView we get back
|
// Note: we create a random nonce, and watch to see if the MockView we get back
|
||||||
// from the user came from here. If not, we have no hope to do a nice, efficient
|
// from the user came from here. If not, we have no hope to do a nice, efficient
|
||||||
// update, and have to do it from scratch.
|
// update, and have to do it from scratch.
|
||||||
|
@ -600,47 +887,23 @@
|
||||||
} else {
|
} else {
|
||||||
view.top = $(newMockView.cursor.top().node);
|
view.top = $(newMockView.cursor.top().node);
|
||||||
view.initialRender(top);
|
view.initialRender(top);
|
||||||
// FIXME: how about events embedded in the dom?
|
eventHandlers = newMockView.eventHandlers;
|
||||||
|
startEventHandlers();
|
||||||
}
|
}
|
||||||
dispatchingEvents = false;
|
|
||||||
success();
|
success();
|
||||||
},
|
},
|
||||||
function(err) {
|
function(err) {
|
||||||
dispatchingEvents = false;
|
|
||||||
failure(err);
|
failure(err);
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
currentBigBangRecord = { stop : onCleanRestart,
|
||||||
|
stopWithExn : onMessyRestart,
|
||||||
|
startEventHandler : startEventHandler,
|
||||||
|
stopEventHandler : stopEventHandler };
|
||||||
var startEventHandler = function(handler) {
|
|
||||||
var fireEvent = function() {
|
|
||||||
if (! running) { return; }
|
|
||||||
var args = [].slice.call(arguments, 0);
|
|
||||||
eventQueue.queue(new EventQueueElement(handler, args));
|
|
||||||
if (! dispatchingEvents) {
|
|
||||||
setTimeout(dispatchEventsInQueue, 0);
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// fixme: if we see too many events accumulating, throttle
|
|
||||||
// the ones that are marked as throttleable.
|
|
||||||
};
|
|
||||||
handler.eventSource.onStart(fireEvent);
|
|
||||||
};
|
|
||||||
|
|
||||||
var stopEventHandler = function(handler) {
|
|
||||||
handler.eventSource.onStop();
|
|
||||||
};
|
|
||||||
|
|
||||||
view.initialRender(top);
|
view.initialRender(top);
|
||||||
|
startEventHandlers();
|
||||||
var eventHandlers = filter(handlers, isEventHandler).concat(view.getEventHandlers());
|
refreshView(function() {}, onMessyRestart);
|
||||||
var i;
|
|
||||||
for (i = 0; i < eventHandlers.length; i++) {
|
|
||||||
startEventHandler(eventHandlers[i]);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -659,6 +922,38 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// findDomNodeLocation: dom-node dom-node -> arrayof number
|
||||||
|
// Given a node, returns the child indices we need to follow to reach
|
||||||
|
// it from the top.
|
||||||
|
// Assumption: top must be an ancestor of the node. Otherwise, the
|
||||||
|
// result is partial.
|
||||||
|
var findDomNodeLocation = function(node, top) {
|
||||||
|
var locator = [];
|
||||||
|
var parent, i;
|
||||||
|
while(node !== top && node.parentNode !== null) {
|
||||||
|
parent = node.parentNode;
|
||||||
|
for (i = 0; i < parent.childNodes.length; i++) {
|
||||||
|
if (parent.childNodes[i] === node) {
|
||||||
|
locator.push(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node = parent;
|
||||||
|
}
|
||||||
|
return locator.reverse();
|
||||||
|
};
|
||||||
|
|
||||||
|
var findNodeFromLocation = function(top, location) {
|
||||||
|
var i = 0;
|
||||||
|
var node = top;
|
||||||
|
for (i = 0; i < location.length; i++) {
|
||||||
|
node = node.childNodes[location[i]];
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
var checkReal = plt.baselib.check.checkReal;
|
var checkReal = plt.baselib.check.checkReal;
|
||||||
|
@ -730,9 +1025,10 @@
|
||||||
'->view',
|
'->view',
|
||||||
1,
|
1,
|
||||||
function(MACHINE) {
|
function(MACHINE) {
|
||||||
|
var viewable = MACHINE.env[MACHINE.env.length - 1];
|
||||||
var oldArgcount = MACHINE.argcount;
|
var oldArgcount = MACHINE.argcount;
|
||||||
PAUSE(function(restart) {
|
PAUSE(function(restart) {
|
||||||
coerseToView(viewable,
|
coerseToMockView(viewable,
|
||||||
function(v) {
|
function(v) {
|
||||||
restart(function(MACHINE) {
|
restart(function(MACHINE) {
|
||||||
MACHINE.argcount = oldArgcount;
|
MACHINE.argcount = oldArgcount;
|
||||||
|
@ -888,5 +1184,94 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
EXPORTS['view-bind'] = makePrimitiveProcedure(
|
||||||
|
'view-bind',
|
||||||
|
3,
|
||||||
|
function(MACHINE) {
|
||||||
|
var view = checkMockView(MACHINE, 'view-bind', 0);
|
||||||
|
var name = checkSymbolOrString(MACHINE, 'view-bind', 1);
|
||||||
|
var worldF = wrapFunction(checkProcedure(MACHINE, 'view-bind', 2));
|
||||||
|
return view.bind(name, worldF);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
EXPORTS['view-form-value'] = makePrimitiveProcedure(
|
||||||
|
'view-form-value',
|
||||||
|
1,
|
||||||
|
function(MACHINE) {
|
||||||
|
var view = checkMockView(MACHINE, 'view-form-value', 0);
|
||||||
|
return view.getFormValue();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
EXPORTS['update-view-form-value'] = makePrimitiveProcedure(
|
||||||
|
'update-view-form-value',
|
||||||
|
2,
|
||||||
|
function(MACHINE) {
|
||||||
|
var view = checkMockView(MACHINE, 'update-view-form-value', 0);
|
||||||
|
var value = checkSymbolOrString(MACHINE, 'update-view-form-value', 1).toString();
|
||||||
|
return view.updateFormValue(value);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXPORTS['view-show'] = makePrimitiveProcedure(
|
||||||
|
'view-show',
|
||||||
|
1,
|
||||||
|
function(MACHINE) {
|
||||||
|
var view = checkMockView(MACHINE, 'view-show', 0);
|
||||||
|
return view.show();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
EXPORTS['view-hide'] = makePrimitiveProcedure(
|
||||||
|
'view-hide',
|
||||||
|
1,
|
||||||
|
function(MACHINE) {
|
||||||
|
var view = checkMockView(MACHINE, 'view-hide', 0);
|
||||||
|
return view.hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
EXPORTS['view-append-child'] = makeClosure(
|
||||||
|
'view-append-child',
|
||||||
|
2,
|
||||||
|
function(MACHINE) {
|
||||||
|
var view = checkMockView(MACHINE, 'view-append-child', 0);
|
||||||
|
var oldArgcount = MACHINE.argcount;
|
||||||
|
var x = MACHINE.env[MACHINE.env.length - 2];
|
||||||
|
PAUSE(function(restart) {
|
||||||
|
coerseToDomNode(x,
|
||||||
|
function(dom) {
|
||||||
|
restart(function(MACHINE) {
|
||||||
|
MACHINE.argcount = oldArgcount;
|
||||||
|
var updatedView = view.appendChild(dom);
|
||||||
|
finalizeClosureCall(MACHINE, updatedView);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(err) {
|
||||||
|
restart(function(MACHINE) {
|
||||||
|
plt.baselib.exceptions.raise(
|
||||||
|
MACHINE,
|
||||||
|
new Error(plt.baselib.format.format(
|
||||||
|
"unable to translate ~s to dom node: ~a",
|
||||||
|
[x, exn.message])));
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
EXPORTS['view-id'] = makePrimitiveProcedure(
|
||||||
|
'view-id',
|
||||||
|
1,
|
||||||
|
function(MACHINE) {
|
||||||
|
var view = checkMockView(MACHINE, 'view-hide', 0);
|
||||||
|
return view.id();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
}());
|
}());
|
|
@ -5,7 +5,18 @@
|
||||||
view-focus
|
view-focus
|
||||||
view-left view-right view-up view-down
|
view-left view-right view-up view-down
|
||||||
view-text update-view-text
|
view-text update-view-text
|
||||||
view-attr update-view-attr)
|
view-attr update-view-attr
|
||||||
|
view-id
|
||||||
|
|
||||||
|
view-bind
|
||||||
|
|
||||||
|
view-form-value
|
||||||
|
update-view-form-value
|
||||||
|
|
||||||
|
view-show
|
||||||
|
view-hide
|
||||||
|
view-append-child)
|
||||||
|
|
||||||
|
|
||||||
(define (big-bang world . handlers)
|
(define (big-bang world . handlers)
|
||||||
(error 'big-bang "Please run in JavaScript context."))
|
(error 'big-bang "Please run in JavaScript context."))
|
||||||
|
@ -60,3 +71,28 @@
|
||||||
|
|
||||||
(define (update-view-attr v attr-name value)
|
(define (update-view-attr v attr-name value)
|
||||||
(error 'update-view-attr "Please run in JavaScript context."))
|
(error 'update-view-attr "Please run in JavaScript context."))
|
||||||
|
|
||||||
|
|
||||||
|
(define (view-id v)
|
||||||
|
(error 'view-id "Please run in JavaScript context."))
|
||||||
|
|
||||||
|
|
||||||
|
(define (view-bind v type worldF)
|
||||||
|
(error 'view-bind "Please run in JavaScript context."))
|
||||||
|
|
||||||
|
(define (view-form-value)
|
||||||
|
(error 'view-form-value "Please run in JavaScript context."))
|
||||||
|
|
||||||
|
(define (update-view-form-value val)
|
||||||
|
(error 'view-form-value "Please run in JavaScript context."))
|
||||||
|
|
||||||
|
|
||||||
|
(define (view-show)
|
||||||
|
(error 'view-show "Please run in JavaScript context."))
|
||||||
|
|
||||||
|
(define (view-hide)
|
||||||
|
(error 'view-hide "Please run in JavaScript context."))
|
||||||
|
|
||||||
|
|
||||||
|
(define (view-append-child dom)
|
||||||
|
(error 'view-append "Please run in JavaScript context."))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user