Merge branch 'master' into dom

Conflicts:

	web-world/js-impl.js
This commit is contained in:
Danny Yoo 2011-09-07 16:32:46 -04:00
commit d19e8562ac
9 changed files with 161 additions and 24 deletions

View File

@ -121,7 +121,7 @@
break;
}
}
if (p !== Empty.EMPTY) {
if (p !== EMPTY) {
texts.push('.');
texts.push(baselib.format.toDisplayedString(p, cache));
}
@ -138,14 +138,14 @@
while (p instanceof Cons) {
node.appendChild(baselib.format.toDomNode(p.first, cache));
p = p.rest;
if (p !== Empty.EMPTY) {
if (p !== EMPTY) {
node.appendChild(document.createTextNode(" "));
}
if (typeof (p) === 'object' && cache.containsKey(p)) {
break;
}
}
if (p !== Empty.EMPTY) {
if (p !== EMPTY) {
node.appendChild(document.createTextNode("."));
node.appendChild(document.createTextNode(" "));
node.appendChild(baselib.format.toDomNode(p, cache));
@ -157,13 +157,13 @@
var isPair = function (x) { return x instanceof Cons; };
var isEmpty = function (x) { return x === Empty.EMPTY; };
var isEmpty = function (x) { return x === EMPTY; };
var makePair = Cons.makeInstance;
var makeList = function () {
var result = Empty.EMPTY, i;
var result = EMPTY, i;
for (i = arguments.length - 1; i >= 0; i--) {
result = Cons.makeInstance(arguments[i], result);
}
@ -171,10 +171,21 @@
};
// Coerse a list back into a JavaScript array.
var listToArray = function(lst) {
var result = [];
while (lst !== EMPTY) {
result.push(lst.first);
lst = lst.rest;
}
return result;
};
// isList: Any -> Boolean
// Returns true if x is a list (a chain of pairs terminated by EMPTY).
var isList = function (x) {
while (x !== Empty.EMPTY) {
while (x !== EMPTY) {
if (x instanceof Cons) {
x = x.rest;
} else {
@ -229,6 +240,6 @@
exports.reverse = reverse;
exports.length = length;
exports.listRef = listRef;
exports.listToArray = listToArray;
}(this.plt.baselib));

View File

@ -363,7 +363,7 @@
var marks = frame.marks;
var i;
for (i = 0; i < marks.length; i++) {
if (equals(key, marks[i][0])) {
if (key === marks[i][0]) {
marks[i][1] = value;
return;
}

View File

@ -151,6 +151,13 @@ $ planet link dyoo whalesong.plt 1 0 whalesong
than the latest version that's on PLaneT at the time.)
Let's make the @filepath{whalesong} launcher somewhere appropriate. Run Racket with the following
@racket[require]:
@racketblock[
(require (planet dyoo/whalesong/make-launcher))
]
This will create a @filepath{whalesong} executable in the current working directory.
Finally, we need to set up Whalesong with @tt{raco setup}.
Here's how to do this at the command
@ -158,24 +165,30 @@ line:
@verbatim|{
$ raco setup -P dyoo whalesong.plt 1 0
}|
This should compile Whalesong, as well as set up the @filepath{whalesong} executable.
Any time the source code in @filepath{whalesong} changes, we should repeat
this @tt{raco setup} step again.
This should compile Whalesong. Any time the source code in
@filepath{whalesong} changes, we should repeat this @tt{raco setup}
step again.
At this point, you should be able to rung @filepath{whalesong} from the command line.
At this point, you should be able to run the @filepath{whalesong} executable from the command line.
@verbatim|{
$ ./whalesong
Expected one of the following: [build, get-runtime, get-javascript].
Usage: whalesong <subcommand> [option ...] <arg ...>
where any unambiguous prefix can be used for a subcommand
The Whalesong command-line tool for compiling Racket to JavaScript
For help on a particular subcommand, use 'whalesong <subcommand> --help'
whalesong build build a standalone html and javascript package
whalesong get-runtime print the runtime library to standard output
whalesong get-javascript Gets just the JavaScript code and prints it to standard output
}|
and if this does appear, then Whalesong should be installed successfully.
Note: whenever Whalesong's source code is updated from Github, please
re-run the @tt{raco setup}. Otherwise, Racket will try to recompile
Whalesong on every single use of Whalesong, which can be very
expensive.
To repeat: whenever Whalesong's source code is updated from Github,
please re-run the @tt{raco setup} step. Otherwise, Racket will try to
recompile Whalesong on every single use, which can be very expensive.

View File

@ -0,0 +1,3 @@
""
"some text"
(html (head) (body (p "hello world, this is a test") (div (@ (id "a div")) "some text")))

21
tests/more-tests/view.rkt Normal file
View File

@ -0,0 +1,21 @@
#lang planet dyoo/whalesong
(require (planet dyoo/whalesong/web-world))
(define view (->view (xexp->dom `(html (head)
(body (p "hello world, this is a test")
(div (@ (id "a div"))))))))
(define new-view
(view-focus view "a div"))
(view-text new-view) ;; should be ""
(define updated-new-view
(update-view-text new-view "some text"))
(view-text updated-new-view) ;; should be "some text"
(view->xexp (view-up (view-up updated-new-view)))
;; should be:
; (html (head) (body (p "hello world, this is a test")
; (div (@ (id "a div")) "some text")))

View File

@ -26,3 +26,4 @@
(test "more-tests/hello-bf.rkt")
(test "more-tests/conform.rkt")
(test "more-tests/earley.rkt")
(test "more-tests/view.rkt")

View File

@ -74,4 +74,6 @@
xexp?
xexp->dom
view->xexp
))

View File

@ -124,6 +124,8 @@
}
};
var EMPTY_PENDING_ACTIONS = plt.baselib.lists.EMPTY;
//////////////////////////////////////////////////////////////////////
// A MockView provides a functional interface to the DOM. It
@ -132,17 +134,29 @@
// freshness of the MockView.
var MockView = function(cursor, pendingActions, eventHandlers, nonce) {
this.cursor = cursor;
// (listof (view -> void))
this.pendingActions = pendingActions;
this.eventHandlers = eventHandlers;
this.nonce = nonce;
};
var isMockView = plt.baselib.makeClassPredicate(MockView);
MockView.prototype.toString = function() {
return "<#view>";
};
MockView.prototype.getPendingActions = function() {
return plt.baselib.lists.listToArray(this.pendingActions).reverse();
};
MockView.prototype.act = function(actionForCursor, actionForEventHandlers, actionForReal) {
if (arguments.length !== 3) { throw new Error("act: insufficient arguments"); }
return new MockView(actionForCursor(this.cursor),
this.pendingActions.concat([actionForReal]),
plt.baselib.lists.makePair(actionForReal, this.pendingActions),
actionForEventHandlers(this.eventHandlers),
this.nonce);
};
@ -488,8 +502,9 @@
View.prototype.getMockAndResetFocus = function(nonce) {
this.focus = this.top;
return new MockView(domToArrayTreeCursor($(this.top).get(0)),
[],
EMPTY_PENDING_ACTIONS,
this.eventHandlers.slice(0),
nonce);
};
@ -560,14 +575,14 @@
} catch (exn1) {
return onFail(exn1);
}
return onSuccess(new MockView(domToArrayTreeCursor(dom.get(0)), [], [], undefined));
return onSuccess(new MockView(domToArrayTreeCursor(dom.get(0)), EMPTY_PENDING_ACTIONS, [], undefined));
} else {
try {
dom = $(plt.baselib.format.toDomNode(x));
} catch (exn2) {
return onFail(exn2);
}
return onSuccess(new MockView(domToArrayTreeCursor(dom.get(0)), [], [], undefined));
return onSuccess(new MockView(domToArrayTreeCursor(dom.get(0)), EMPTY_PENDING_ACTIONS, [], undefined));
}
};
@ -1123,7 +1138,7 @@
function(newMockView) {
if (newMockView.nonce === nonce) {
var i;
var actions = newMockView.pendingActions;
var actions = newMockView.getPendingActions();
for (i = 0; i < actions.length; i++) {
actions[i](view);
}
@ -1309,6 +1324,61 @@
return false;
};
var domToXexp = function(dom) {
var child, attrs, name, convertedChildren, i;
if (dom.nodeType === 1) {
attrs = plt.baselib.lists.EMPTY;
name = plt.baselib.symbols.makeSymbol(dom.nodeName.toLowerCase());
child = dom.firstChild;
convertedChildren = plt.baselib.lists.EMPTY;
for (i = 0; i < dom.attributes.length; i++) {
attrs = plt.baselib.lists.makePair(
plt.baselib.lists.makeList(plt.baselib.symbols.makeSymbol(dom.attributes[i].nodeName),
dom.attributes[i].nodeValue),
attrs);
}
while(child !== null) {
if (child.nodeType === 1) {
convertedChildren =
plt.baselib.lists.makePair(
domToXexp(child),
convertedChildren);
} else if (child.nodeType === 3) {
convertedChildren = plt.baselib.lists.makePair(
domToXexp(child),
convertedChildren);
}
// Ignore other types.
child = child.nextSibling;
}
if (attrs === plt.baselib.lists.EMPTY) {
return plt.baselib.lists.makePair(
name,
plt.baselib.lists.reverse(convertedChildren));
} else {
return plt.baselib.lists.makePair(
name,
plt.baselib.lists.makePair(
plt.baselib.lists.makePair(plt.baselib.symbols.makeSymbol("@"),
attrs),
plt.baselib.lists.reverse(convertedChildren)));
}
} else if (dom.nodeType === 3) {
return dom.nodeValue;
} else {
// If we can't convert it, return false.
return false;
}
};
@ -1761,5 +1831,15 @@
});
EXPORTS['view->xexp'] = makePrimitiveProcedure(
'view->xexp',
1,
function(MACHINE) {
var mockView = checkMockView(MACHINE, 'view-hide', 0);
var domNode = arrayTreeToDomNode(mockView.cursor.top().node);
return domToXexp(domNode);
});
//////////////////////////////////////////////////////////////////////
}());

View File

@ -28,7 +28,9 @@
open-output-element
xexp?
xexp->dom)
xexp->dom
view->xexp
)
(define (big-bang world . handlers)
@ -169,3 +171,7 @@
(define (xexp->dom x)
(error 'xexp->dom "Please run in JavaScript context."))
(define (view->xexp x)
(error 'view->xexp "Please run in JavaScript context."))