trying to get simple view stuff working.
This commit is contained in:
parent
f488db734b
commit
84c6df5f90
|
@ -31,7 +31,7 @@ previous attempt of jsworld:
|
||||||
|
|
||||||
We want to take the design ideas of JQuery.
|
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
|
* Operations refocus the cursor onto particular elements of the
|
||||||
dom.
|
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
|
;; When the user clicks on the button, grab at the text of the
|
||||||
;; text-field.
|
;; text-field.
|
||||||
(define (on-click w v)
|
(define (on-click w v)
|
||||||
(view-text (view-focus v "text-field")))
|
(view-text (view-focus v "#text-field")))
|
||||||
|
|
||||||
|
|
||||||
;; on-draw: world view -> view
|
;; on-draw: world view -> view
|
||||||
;; Take the view, and replace the template with the world value.
|
;; Take the view, and replace the template with the world value.
|
||||||
(define (on-draw w v)
|
(define (on-draw w v)
|
||||||
(view-text (view-focus v "template")
|
(view-text (view-focus v "#template")
|
||||||
w))
|
w))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,18 +4,21 @@
|
||||||
|
|
||||||
(define-resource index.html)
|
(define-resource index.html)
|
||||||
|
|
||||||
|
|
||||||
;; draw: world view -> view
|
;; draw: world view -> view
|
||||||
(define (draw w v)
|
(define (draw w v)
|
||||||
v
|
(update-view-text (view-focus v "#counter") w))
|
||||||
;(view-text (view-focus v "#counter") w)
|
|
||||||
)
|
|
||||||
|
|
||||||
;; tick: world view -> world
|
;; tick: world view -> world
|
||||||
(define (tick w v)
|
(define (tick w v)
|
||||||
(printf "Tick\n")
|
(printf "Tick ~s\n" w)
|
||||||
(+ add1 w))
|
(+ w 1))
|
||||||
|
|
||||||
(big-bang 0
|
(big-bang 0
|
||||||
(initial-view index.html)
|
(initial-view index.html)
|
||||||
(to-draw draw)
|
(to-draw draw)
|
||||||
(on-tick tick 1))
|
(on-tick tick 1)
|
||||||
|
(stop-when (lambda (w v)
|
||||||
|
(> w 10))))
|
||||||
|
|
|
@ -23,4 +23,9 @@
|
||||||
to-draw
|
to-draw
|
||||||
|
|
||||||
;; coerse to view
|
;; coerse to view
|
||||||
->view))
|
->view
|
||||||
|
|
||||||
|
view-focus
|
||||||
|
view-text
|
||||||
|
update-view-text
|
||||||
|
))
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
var makeClosure = plt.baselib.functions.makeClosure;
|
var makeClosure = plt.baselib.functions.makeClosure;
|
||||||
var finalizeClosureCall = plt.baselib.functions.finalizeClosureCall;
|
var finalizeClosureCall = plt.baselib.functions.finalizeClosureCall;
|
||||||
var PAUSE = plt.runtime.PAUSE;
|
var PAUSE = plt.runtime.PAUSE;
|
||||||
|
var isString = plt.baselib.strings.isString;
|
||||||
|
|
||||||
|
|
||||||
var resourceStructType =
|
var resourceStructType =
|
||||||
|
@ -16,21 +16,62 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// A View represents a functional representation of the DOM tree.
|
// See Functional Pearl: The Zipper, by G\'erard Huet
|
||||||
var View = function(top, focused, eventHandlers, pendingActions) {
|
// 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
|
// top: dom node
|
||||||
this.top = top;
|
this.top = top;
|
||||||
this.focused = focused;
|
this.focused = focused;
|
||||||
this.eventHandlers = eventHandlers;
|
this.eventHandlers = eventHandlers;
|
||||||
this.pendingActions = pendingActions;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
View.prototype.toString = function() { return "#<View>"; };
|
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) {
|
View.prototype.initialRender = function(top) {
|
||||||
top.empty();
|
top.empty();
|
||||||
$(document.head).append(this.top.find("head").children());
|
$(document.head).append(this.top.find("head").children());
|
||||||
|
@ -50,6 +91,42 @@
|
||||||
return this.eventHandlers;
|
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 onFail(exn);
|
||||||
}
|
}
|
||||||
return onSuccess(new View(dom,
|
return onSuccess(new View(dom,
|
||||||
|
dom,
|
||||||
[],
|
[],
|
||||||
[],
|
[],
|
||||||
[]));
|
undefined));
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
dom = $(plt.baselib.format.toDomNode(x))
|
dom = $(plt.baselib.format.toDomNode(x))
|
||||||
|
@ -93,9 +171,10 @@
|
||||||
return onFail(exn);
|
return onFail(exn);
|
||||||
}
|
}
|
||||||
return onSuccess(new View(dom,
|
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() {
|
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.
|
// bigBang.
|
||||||
var bigBang = function(MACHINE, world, handlers) {
|
var bigBang = function(MACHINE, world, handlers) {
|
||||||
var oldArgcount = MACHINE.argcount;
|
var oldArgcount = MACHINE.argcount;
|
||||||
|
var running = true;
|
||||||
var view = (find(handlers, isInitialViewHandler) || { view : new View(plt.baselib.format.toDomNode(world),
|
var top = $(plt.baselib.format.toDomNode(world));
|
||||||
[],
|
var view = (find(handlers, isInitialViewHandler) || { view : new View(top,
|
||||||
|
top,
|
||||||
[],
|
[],
|
||||||
[])}).view;
|
[])}).view;
|
||||||
var stopWhen = (find(handlers, isStopWhenHandler) || { stopWhen: defaultStopWhen }).stopWhen;
|
var stopWhen = (find(handlers, isStopWhenHandler) || { stopWhen: defaultStopWhen }).stopWhen;
|
||||||
|
@ -323,6 +405,7 @@
|
||||||
PAUSE(function(restart) {
|
PAUSE(function(restart) {
|
||||||
|
|
||||||
var onCleanRestart = function() {
|
var onCleanRestart = function() {
|
||||||
|
running = false;
|
||||||
var i;
|
var i;
|
||||||
for (i = 0; i < eventHandlers.length; i++) {
|
for (i = 0; i < eventHandlers.length; i++) {
|
||||||
stopEventHandler(eventHandlers[i]);
|
stopEventHandler(eventHandlers[i]);
|
||||||
|
@ -334,6 +417,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
var onMessyRestart = function(exn) {
|
var onMessyRestart = function(exn) {
|
||||||
|
running = false;
|
||||||
var i;
|
var i;
|
||||||
for (i = 0; i < eventHandlers.length; i++) {
|
for (i = 0; i < eventHandlers.length; i++) {
|
||||||
stopEventHandler(eventHandlers[i]);
|
stopEventHandler(eventHandlers[i]);
|
||||||
|
@ -343,28 +427,43 @@
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var dispatchEventsInQueue = function() {
|
var dispatchEventsInQueue = function() {
|
||||||
// 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;
|
||||||
var data;
|
var data;
|
||||||
var racketWorldCallback;
|
var racketWorldCallback;
|
||||||
|
var mockView;
|
||||||
|
|
||||||
if(! eventQueue.isEmpty() ) {
|
if(! eventQueue.isEmpty() ) {
|
||||||
|
// Set up the proxy object so we can do what appear to be functional
|
||||||
|
// queries.
|
||||||
|
mockView = view.getMock();
|
||||||
|
|
||||||
nextEvent = eventQueue.dequeue();
|
nextEvent = eventQueue.dequeue();
|
||||||
// FIXME: deal with event data here
|
// FIXME: deal with event data here
|
||||||
racketWorldCallback = nextEvent.handler.racketWorldCallback;
|
racketWorldCallback = nextEvent.handler.racketWorldCallback;
|
||||||
|
|
||||||
racketWorldCallback(MACHINE,
|
racketWorldCallback(MACHINE,
|
||||||
world,
|
world,
|
||||||
view,
|
view,
|
||||||
// data,
|
// data,
|
||||||
function(newWorld) {
|
function(newWorld) {
|
||||||
world = newWorld;
|
world = newWorld;
|
||||||
dispatchEventsInQueue();
|
|
||||||
|
stopWhen(MACHINE,
|
||||||
|
world,
|
||||||
|
view,
|
||||||
|
function(shouldStop) {
|
||||||
|
if (shouldStop) {
|
||||||
|
onCleanRestart();
|
||||||
|
} else {
|
||||||
|
dispatchEventsInQueue();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
function(err) {
|
||||||
|
onMessyRestart(err);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
function(err) {
|
function(err) {
|
||||||
onMessyRestart(err);
|
onMessyRestart(err);
|
||||||
|
@ -377,6 +476,7 @@
|
||||||
|
|
||||||
var startEventHandler = function(handler) {
|
var startEventHandler = function(handler) {
|
||||||
var fireEvent = function() {
|
var fireEvent = function() {
|
||||||
|
if (! running) { return; }
|
||||||
var args = [].slice.call(arguments, 0);
|
var args = [].slice.call(arguments, 0);
|
||||||
eventQueue.queue(new EventQueueElement(handler, args));
|
eventQueue.queue(new EventQueueElement(handler, args));
|
||||||
setTimeout(dispatchEventsInQueue, 0);
|
setTimeout(dispatchEventsInQueue, 0);
|
||||||
|
@ -444,7 +544,12 @@
|
||||||
'world handler');
|
'world handler');
|
||||||
|
|
||||||
var checkView = plt.baselib.check.makeCheckArgumentType(
|
var checkView = plt.baselib.check.makeCheckArgumentType(
|
||||||
isView, 'view');
|
isMockView, 'view');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var checkSelector = plt.baselib.check.makeCheckArgumentType(
|
||||||
|
isString, 'selector');
|
||||||
|
|
||||||
|
|
||||||
EXPORTS['big-bang'] = makeClosure(
|
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);
|
||||||
|
});
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
}());
|
}());
|
|
@ -1,6 +1,7 @@
|
||||||
#lang racket/base
|
#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)
|
(define (big-bang world . handlers)
|
||||||
(error 'big-bang "Please run in JavaScript context."))
|
(error 'big-bang "Please run in JavaScript context."))
|
||||||
|
@ -22,3 +23,14 @@
|
||||||
|
|
||||||
(define (->view x)
|
(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."))
|
Loading…
Reference in New Issue
Block a user