trying to get simple view stuff working.

This commit is contained in:
Danny Yoo 2011-08-24 16:56:58 -04:00
parent f488db734b
commit 84c6df5f90
5 changed files with 198 additions and 42 deletions

View File

@ -31,7 +31,7 @@ previous attempt of jsworld:
We want to take the design ideas of JQuery.
* The view is a cursor into DOM nodes.
* The view is a cursor into a DOM node.
* Operations refocus the cursor onto particular elements of the
dom.
@ -249,13 +249,13 @@ handler takes, not only the world, but the current view.
;; When the user clicks on the button, grab at the text of the
;; text-field.
(define (on-click w v)
(view-text (view-focus v "text-field")))
(view-text (view-focus v "#text-field")))
;; on-draw: world view -> view
;; Take the view, and replace the template with the world value.
(define (on-draw w v)
(view-text (view-focus v "template")
(view-text (view-focus v "#template")
w))

View File

@ -4,18 +4,21 @@
(define-resource index.html)
;; draw: world view -> view
(define (draw w v)
v
;(view-text (view-focus v "#counter") w)
)
(update-view-text (view-focus v "#counter") w))
;; tick: world view -> world
(define (tick w v)
(printf "Tick\n")
(+ add1 w))
(printf "Tick ~s\n" w)
(+ w 1))
(big-bang 0
(initial-view index.html)
(to-draw draw)
(on-tick tick 1))
(on-tick tick 1)
(stop-when (lambda (w v)
(> w 10))))

View File

@ -23,4 +23,9 @@
to-draw
;; coerse to view
->view))
->view
view-focus
view-text
update-view-text
))

View File

@ -8,7 +8,7 @@
var makeClosure = plt.baselib.functions.makeClosure;
var finalizeClosureCall = plt.baselib.functions.finalizeClosureCall;
var PAUSE = plt.runtime.PAUSE;
var isString = plt.baselib.strings.isString;
var resourceStructType =
@ -16,21 +16,62 @@
// A View represents a functional representation of the DOM tree.
var View = function(top, focused, eventHandlers, pendingActions) {
// See Functional Pearl: The Zipper, by G\'erard Huet
// J. Functional Programming 7 (5): 549--554 Sepember 1997
var TreeCursor = function() {
this.parent;
this
};
//////////////////////////////////////////////////////////////////////
var MockView = function(focused, pendingActions) {
this.focused = focused;
this.pendingActions = pendingActions;
};
var isMockView = plt.baselib.makeClassPredicate(MockView);
MockView.prototype.act = function(actionForMock, actionForReal) {
if (arguments.length !== 2) { throw new Error("act: insufficient arguments"); }
// FIXME: this is not enough. We need a way to do the action
// on a copy of the mock. clone is insufficient: we need to
// copy the whole tree, no?
return new MockView(actionForMock(this.focused),
this.pendingActions.concat([actionForReal]));
};
MockView.prototype.updateFocus = function(selector) {
return this;
};
MockView.prototype.getText = function() {
return "fill me in";
};
MockView.prototype.updateText = function(text) {
return this;
};
//////////////////////////////////////////////////////////////////////
// A View represents a representation of the DOM tree.
var View = function(top, focused, eventHandlers, pendingActions, proxy) {
// top: dom node
this.top = top;
this.focused = focused;
this.eventHandlers = eventHandlers;
this.pendingActions = pendingActions;
};
View.prototype.toString = function() { return "#<View>"; };
View.prototype.updateFocused = function(focused) {
return new View(this.top, focused, this.eventHandlers, this.pendingActions);
};
View.prototype.initialRender = function(top) {
top.empty();
$(document.head).append(this.top.find("head").children());
@ -49,7 +90,43 @@
View.prototype.getEventHandlers = function() {
return this.eventHandlers;
};
View.prototype.getMock = function() {
return new MockView(this.top.clone(true), []);
};
// View.prototype.updateFocus = function(selector) {
// if (this.proxy) {
// return new View(this.top, this.top.find(selector), this.eventHandlers, this.pendingActions, this.proxy);
// } else {
// return new View(this.top, this.top.find(selector), this.eventHandlers, this.pendingActions, this.proxy);
// }
// };
// View.prototype.text = function() {
// if (this.proxy) {
// return (this.proxy.text())
// } else {
// return (this.focused.text());
// }
// };
// View.prototype.updateText = function(s) {
// if (this.proxy) {
// this.proxy.text(s);
// return new View(this.top,
// this.focused,
// this.eventHandlers,
// this.pendingActions.concat([ function(v) { this.focused.text(s); }]),
// this.proxy);
// } else {
// return (this.focused.text());
// }
// };
@ -83,9 +160,10 @@
return onFail(exn);
}
return onSuccess(new View(dom,
dom,
[],
[],
[]));
undefined));
} else {
try {
dom = $(plt.baselib.format.toDomNode(x))
@ -93,9 +171,10 @@
return onFail(exn);
}
return onSuccess(new View(dom,
dom,
[],
[],
[]));
undefined));
}
};
@ -271,14 +350,6 @@
var defaultToDraw = function(world, view, success, fail) {
return success(view);
};
var defaultStopWhen = function(world, success, fail) {
return success(false);
};
var EventQueue = function() {
@ -304,12 +375,23 @@
var defaultToDraw = function(MACHINE, world, view, success, fail) {
return success(view);
};
var defaultStopWhen = function(MACHINE, world, view, success, fail) {
return success(false);
};
// bigBang.
var bigBang = function(MACHINE, world, handlers) {
var oldArgcount = MACHINE.argcount;
var view = (find(handlers, isInitialViewHandler) || { view : new View(plt.baselib.format.toDomNode(world),
[],
var running = true;
var top = $(plt.baselib.format.toDomNode(world));
var view = (find(handlers, isInitialViewHandler) || { view : new View(top,
top,
[],
[])}).view;
var stopWhen = (find(handlers, isStopWhenHandler) || { stopWhen: defaultStopWhen }).stopWhen;
@ -323,6 +405,7 @@
PAUSE(function(restart) {
var onCleanRestart = function() {
running = false;
var i;
for (i = 0; i < eventHandlers.length; i++) {
stopEventHandler(eventHandlers[i]);
@ -334,6 +417,7 @@
};
var onMessyRestart = function(exn) {
running = false;
var i;
for (i = 0; i < eventHandlers.length; i++) {
stopEventHandler(eventHandlers[i]);
@ -343,28 +427,43 @@
});
};
var dispatchEventsInQueue = function() {
// Apply all the events on the queue, call toDraw, and then stop.
// If the world ever satisfies stopWhen, stop immediately and quit.
var nextEvent;
var data;
var racketWorldCallback;
var mockView;
if(! eventQueue.isEmpty() ) {
// Set up the proxy object so we can do what appear to be functional
// queries.
mockView = view.getMock();
nextEvent = eventQueue.dequeue();
// FIXME: deal with event data here
racketWorldCallback = nextEvent.handler.racketWorldCallback;
racketWorldCallback(MACHINE,
world,
view,
// data,
function(newWorld) {
world = newWorld;
dispatchEventsInQueue();
stopWhen(MACHINE,
world,
view,
function(shouldStop) {
if (shouldStop) {
onCleanRestart();
} else {
dispatchEventsInQueue();
}
},
function(err) {
onMessyRestart(err);
});
},
function(err) {
onMessyRestart(err);
@ -377,6 +476,7 @@
var startEventHandler = function(handler) {
var fireEvent = function() {
if (! running) { return; }
var args = [].slice.call(arguments, 0);
eventQueue.queue(new EventQueueElement(handler, args));
setTimeout(dispatchEventsInQueue, 0);
@ -444,7 +544,12 @@
'world handler');
var checkView = plt.baselib.check.makeCheckArgumentType(
isView, 'view');
isMockView, 'view');
var checkSelector = plt.baselib.check.makeCheckArgumentType(
isString, 'selector');
EXPORTS['big-bang'] = makeClosure(
@ -545,9 +650,40 @@
});
EXPORTS['view-focus'] = makePrimitiveProcedure(
'view-focus',
2,
function(MACHINE) {
var view = checkView(MACHINE, 'view-focus', 0);
var selector = checkSelector(MACHINE, 'view-focus', 1);
try {
return view.updateFocus(selector);
} catch (e) {
plt.baselib.exceptions.raise(
MACHINE,
new Error(plt.baselib.format.format(
"unable to focus to ~s",
[selector])));
}
});
EXPORTS['view-text'] = makePrimitiveProcedure(
'view-focus',
1,
function(MACHINE) {
var view = checkView(MACHINE, 'view-focus', 0);
return view.getText();
});
EXPORTS['update-view-text'] = makePrimitiveProcedure(
'update-view-text',
2,
function(MACHINE) {
var view = checkView(MACHINE, 'update-view-text', 0);
var text = checkString(MACHINE, 'update-view-text', 1);
return view.updateText(text);
});
//////////////////////////////////////////////////////////////////////
}());

View File

@ -1,6 +1,7 @@
#lang racket/base
(provide big-bang initial-view stop-when on-tick to-draw ->view)
(provide big-bang initial-view stop-when on-tick to-draw
->view view-focus view-text update-view-text)
(define (big-bang world . handlers)
(error 'big-bang "Please run in JavaScript context."))
@ -21,4 +22,15 @@
(error 'to-draw "Please run in JavaScript context."))
(define (->view x)
(error '->view "Please run in JavaScript context."))
(error '->view "Please run in JavaScript context."))
(define (view-focus v selector)
(error 'view-focus "Please run in JavaScript context."))
(define (view-text v)
(error 'view-text "Please run in JavaScript context."))
(define (update-view-text v text)
(error 'update-view-text "Please run in JavaScript context."))