Merge commit 'origin/master'
This commit is contained in:
commit
1d63af5daf
8
examples/fact.rkt
Normal file
8
examples/fact.rkt
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#lang planet dyoo/whalesong
|
||||||
|
(provide fact)
|
||||||
|
(define (fact x)
|
||||||
|
(cond
|
||||||
|
[(= x 0)
|
||||||
|
1]
|
||||||
|
[else
|
||||||
|
(* x (fact (sub1 x)))]))
|
|
@ -19,10 +19,12 @@
|
||||||
racket/port
|
racket/port
|
||||||
(prefix-in query: "../lang/js/query.rkt")
|
(prefix-in query: "../lang/js/query.rkt")
|
||||||
(prefix-in resource-query: "../resource/query.rkt")
|
(prefix-in resource-query: "../resource/query.rkt")
|
||||||
(planet dyoo/closure-compile:1:1)
|
|
||||||
(prefix-in runtime: "get-runtime.rkt")
|
(prefix-in runtime: "get-runtime.rkt")
|
||||||
(prefix-in racket: racket/base))
|
(prefix-in racket: racket/base))
|
||||||
|
|
||||||
|
;; There is a dynamic require for (planet dyoo/closure-compile) that's done
|
||||||
|
;; if compression is turned on.
|
||||||
|
|
||||||
|
|
||||||
;; TODO: put proper contracts here
|
;; TODO: put proper contracts here
|
||||||
|
|
||||||
|
@ -365,11 +367,13 @@ M.modules[~s] =
|
||||||
(fprintf op "})(plt.runtime.currentMachine,\nfunction(){ plt.runtime.setReadyTrue(); },\nfunction(){},\n{});\n")))
|
(fprintf op "})(plt.runtime.currentMachine,\nfunction(){ plt.runtime.setReadyTrue(); },\nfunction(){},\n{});\n")))
|
||||||
|
|
||||||
|
|
||||||
|
(define closure-compile-ns (make-base-namespace))
|
||||||
(define (compress x)
|
(define (compress x)
|
||||||
(cond [(current-compress-javascript?)
|
(cond [(current-compress-javascript?)
|
||||||
(log-debug "compressing javascript...")
|
(log-debug "compressing javascript...")
|
||||||
(closure-compile x)]
|
(parameterize ([current-namespace closure-compile-ns])
|
||||||
|
(define closure-compile (dynamic-require '(planet dyoo/closure-compile) 'closure-compile))
|
||||||
|
(closure-compile x))]
|
||||||
[else
|
[else
|
||||||
(log-debug "not compressing javascript...")
|
(log-debug "not compressing javascript...")
|
||||||
x]))
|
x]))
|
||||||
|
|
8985
js-assembler/runtime-src/jquery.js
vendored
8985
js-assembler/runtime-src/jquery.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,18 +1,21 @@
|
||||||
|
var VOID = plt.baselib.constants.VOID_VALUE;
|
||||||
|
var makePrimitiveProcedure = plt.baselib.functions.makePrimitiveProcedure;
|
||||||
|
|
||||||
EXPORTS['alert'] =
|
EXPORTS['alert'] =
|
||||||
RUNTIME.makePrimitiveProcedure(
|
makePrimitiveProcedure(
|
||||||
'alert',
|
'alert',
|
||||||
1,
|
1,
|
||||||
function(MACHINE) {
|
function(MACHINE) {
|
||||||
var elt = MACHINE.env[MACHINE.env.length - 1];
|
var elt = MACHINE.env[MACHINE.env.length - 1];
|
||||||
alert(String(elt));
|
alert(String(elt));
|
||||||
return RUNTIME.VOID;
|
return VOID;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
EXPORTS['body'] = $(document.body);
|
EXPORTS['body'] = $(document.body);
|
||||||
|
|
||||||
EXPORTS['$'] =
|
EXPORTS['$'] =
|
||||||
RUNTIME.makePrimitiveProcedure(
|
makePrimitiveProcedure(
|
||||||
'$',
|
'$',
|
||||||
1,
|
1,
|
||||||
function(MACHINE) {
|
function(MACHINE) {
|
||||||
|
@ -21,7 +24,7 @@ EXPORTS['$'] =
|
||||||
});
|
});
|
||||||
|
|
||||||
EXPORTS['call-method'] =
|
EXPORTS['call-method'] =
|
||||||
RUNTIME.makePrimitiveProcedure(
|
makePrimitiveProcedure(
|
||||||
'call-method',
|
'call-method',
|
||||||
plt.baselib.arity.makeArityAtLeast(2),
|
plt.baselib.arity.makeArityAtLeast(2),
|
||||||
function(MACHINE) {
|
function(MACHINE) {
|
||||||
|
@ -40,7 +43,7 @@ EXPORTS['call-method'] =
|
||||||
|
|
||||||
// Javascript-specific extensions. A small experiment.
|
// Javascript-specific extensions. A small experiment.
|
||||||
EXPORTS['viewport-width'] =
|
EXPORTS['viewport-width'] =
|
||||||
RUNTIME.makePrimitiveProcedure(
|
makePrimitiveProcedure(
|
||||||
'viewport-width',
|
'viewport-width',
|
||||||
0,
|
0,
|
||||||
function(MACHINE) {
|
function(MACHINE) {
|
||||||
|
@ -48,7 +51,7 @@ EXPORTS['viewport-width'] =
|
||||||
});
|
});
|
||||||
|
|
||||||
EXPORTS['viewport-height'] =
|
EXPORTS['viewport-height'] =
|
||||||
RUNTIME.makePrimitiveProcedure(
|
makePrimitiveProcedure(
|
||||||
'viewport-height',
|
'viewport-height',
|
||||||
0,
|
0,
|
||||||
function(MACHINE) {
|
function(MACHINE) {
|
||||||
|
@ -57,7 +60,7 @@ EXPORTS['viewport-height'] =
|
||||||
|
|
||||||
|
|
||||||
EXPORTS['in-javascript-context?'] =
|
EXPORTS['in-javascript-context?'] =
|
||||||
RUNTIME.makePrimitiveProcedure(
|
makePrimitiveProcedure(
|
||||||
'in-javascript-context?',
|
'in-javascript-context?',
|
||||||
0,
|
0,
|
||||||
function(MACHINE) {
|
function(MACHINE) {
|
||||||
|
|
|
@ -66,7 +66,7 @@ Google Chrome should be in @filepath{/contrib/bin/google-chrome}.
|
||||||
|
|
||||||
@section{Usage}
|
@section{Usage}
|
||||||
The @filepath{whalesong} launcher in the subdirectory will compile
|
The @filepath{whalesong} launcher in the subdirectory will compile
|
||||||
programs to standalone @filepath{.xhtml} files.
|
programs to @filepath{.html} and @filepath{.js} files.
|
||||||
|
|
||||||
|
|
||||||
Example usage: using @litchar{whalesong build} to compile a whalesong program.
|
Example usage: using @litchar{whalesong build} to compile a whalesong program.
|
||||||
|
@ -81,7 +81,7 @@ fermi ~/whalesong/examples $ cat hello.rkt
|
||||||
|
|
||||||
fermi ~/whalesong/examples $ ../whalesong build hello.rkt
|
fermi ~/whalesong/examples $ ../whalesong build hello.rkt
|
||||||
|
|
||||||
fermi ~/whalesong/examples $ google-chrome hello.xhtml
|
fermi ~/whalesong/examples $ google-chrome hello.html
|
||||||
Created new window in existing browser session.
|
Created new window in existing browser session.
|
||||||
|
|
||||||
fermi ~/whalesong/examples $
|
fermi ~/whalesong/examples $
|
||||||
|
@ -124,12 +124,16 @@ $
|
||||||
However, it can also be packaged with @filepath{whalesong}.
|
However, it can also be packaged with @filepath{whalesong}.
|
||||||
@verbatim|{
|
@verbatim|{
|
||||||
$ whalesong build hello.rkt
|
$ whalesong build hello.rkt
|
||||||
|
Writing program #<path:/home/dyoo/work/whalesong/examples/hello.js>
|
||||||
|
Writing html #<path:/home/dyoo/work/whalesong/examples/hello.html>
|
||||||
|
|
||||||
$ ls -l hello.xhtml
|
$ ls -l hello.html
|
||||||
-rw-rw-r-- 1 dyoo nogroup 692213 Jun 7 18:00 hello.xhtml
|
-rw-r--r-- 1 dyoo dyoo 3817 2011-09-10 15:02 hello.html
|
||||||
|
$ ls -l hello.js
|
||||||
|
-rw-r--r-- 1 dyoo dyoo 2129028 2011-09-10 15:02 hello.js
|
||||||
}|
|
}|
|
||||||
Running @tt{whalesong build} on a Racket program will produce a self-contained
|
Running @tt{whalesong build} on a Racket program will produce
|
||||||
@filepath{.xhtml} file. If we open this file in our favorite web browser,
|
@filepath{.html} and @filepath{.js} files. If we open this file in our favorite web browser,
|
||||||
we should see a triumphant message show on screen.
|
we should see a triumphant message show on screen.
|
||||||
|
|
||||||
|
|
||||||
|
@ -202,10 +206,59 @@ by @racket[on-tick], though because we're on the web, we can
|
||||||
bind to many other kinds of web events (by using @racket[view-bind]).}
|
bind to many other kinds of web events (by using @racket[view-bind]).}
|
||||||
]
|
]
|
||||||
|
|
||||||
The rest of this document describes the API.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@subsection{More web-world examples}
|
||||||
|
Here are a collection of web-world demos:
|
||||||
|
@itemize[
|
||||||
|
@item{@link["http://hashcollision.org/whalesong/examples/attr-animation/attr-animation.html"]{attr-animation.html} [@link["http://hashcollision.org/whalesong/examples/attr-animation/attr-animation.rkt"]{src}] Uses @racket[update-view-attr] and @racket[on-tick] to perform a simple color animation.}
|
||||||
|
|
||||||
|
@item{@link["http://hashcollision.org/whalesong/examples/dwarves/dwarves.html"]{dwarves.html}
|
||||||
|
[@link["http://hashcollision.org/whalesong/examples/dwarves/dwarves.rkt"]{src}]
|
||||||
|
Uses @racket[view-show] and @racket[view-hide] to manipulate a view. Click on a dwarf to make them hide.
|
||||||
|
}
|
||||||
|
|
||||||
|
@item{@link["http://hashcollision.org/whalesong/examples/dwarves-with-remove/dwarves-with-remove.html"]{dwarves-with-remove.html}
|
||||||
|
[@link["http://hashcollision.org/whalesong/examples/dwarves-with-remove/dwarves-with-remove.rkt"]{src}]
|
||||||
|
Uses @racket[view-focus?] and @racket[view-remove] to see if a dwarf should be removed from the view.
|
||||||
|
}
|
||||||
|
|
||||||
|
@item{@link["http://hashcollision.org/whalesong/examples/field/field.html"]{field.html}
|
||||||
|
[@link["http://hashcollision.org/whalesong/examples/field/field.rkt"]{src}]
|
||||||
|
Uses @racket[view-bind] to read a text field, and @racket[update-view-text] to change
|
||||||
|
the text content of an element.
|
||||||
|
}
|
||||||
|
|
||||||
|
@item{@link["http://hashcollision.org/whalesong/examples/phases/phases.html"]{phases.html}
|
||||||
|
[@link["http://hashcollision.org/whalesong/examples/phases/phases.rkt"]{src}]
|
||||||
|
Switches out one view entirely in place of another. Different views can correspond to phases in a program.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@item{@link["http://hashcollision.org/whalesong/examples/tick-tock/tick-tock.html"]{tick-tock.html}
|
||||||
|
[@link["http://hashcollision.org/whalesong/examples/tick-tock/tick-tock.rkt"]{src}]
|
||||||
|
Uses @racket[on-tick] to show a timer counting up.
|
||||||
|
}
|
||||||
|
|
||||||
|
@item{@link["http://hashcollision.org/whalesong/examples/redirected/redirected.html"]{redirected.html}
|
||||||
|
[@link["http://hashcollision.org/whalesong/examples/redirected/redirected.rkt"]{src}]
|
||||||
|
Uses @racket[on-tick] to show a timer counting up, and also uses @racket[open-output-element] to
|
||||||
|
pipe side-effecting @racket[printf]s to a hidden @tt{div}.
|
||||||
|
}
|
||||||
|
|
||||||
|
@item{@link["http://hashcollision.org/whalesong/examples/todo/todo.html"]{todo.html}
|
||||||
|
[@link["http://hashcollision.org/whalesong/examples/todo/todo.rkt"]{src}]
|
||||||
|
A simple TODO list manager.
|
||||||
|
}
|
||||||
|
|
||||||
|
@item{@link["http://hashcollision.org/whalesong/examples/where-am-i/where-am-i.html"]{where-am-i.html}
|
||||||
|
[@link["http://hashcollision.org/whalesong/examples/where-am-i/where-am-i.rkt"]{src}]
|
||||||
|
Uses @racket[on-location-change] and @racket[on-mock-location-change] to demonstrate location services.
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
scribble/eval
|
scribble/eval
|
||||||
racket/sandbox
|
racket/sandbox
|
||||||
racket/port
|
racket/port
|
||||||
|
racket/list
|
||||||
(only-in racket/contract any/c)
|
(only-in racket/contract any/c)
|
||||||
racket/runtime-path
|
racket/runtime-path
|
||||||
"scribble-helpers.rkt"
|
"scribble-helpers.rkt"
|
||||||
|
@ -99,7 +100,8 @@ The GitHub source repository to Whalesong can be found at
|
||||||
|
|
||||||
|
|
||||||
Prerequisites: at least @link["http://racket-lang.org/"]{Racket
|
Prerequisites: at least @link["http://racket-lang.org/"]{Racket
|
||||||
5.1.1}, and a @link["http://www.java.com"]{Java 1.6} SDK.
|
5.1.1}. If you wish to use the JavaScript compression option,
|
||||||
|
you will need @link["http://www.java.com"]{Java 1.6} SDK.
|
||||||
@; (This might be superfluous information, so commented out
|
@; (This might be superfluous information, so commented out
|
||||||
@; for the moment...)
|
@; for the moment...)
|
||||||
@;The majority of the project is written
|
@;The majority of the project is written
|
||||||
|
@ -194,7 +196,7 @@ recompile Whalesong on every single use, which can be very expensive.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@subsection{Making Standalone @tt{.xhtml} files with Whalesong}
|
@subsection{Making @tt{.html} files with Whalesong}
|
||||||
|
|
||||||
Let's try making a simple, standalone executable. At the moment, the
|
Let's try making a simple, standalone executable. At the moment, the
|
||||||
program must be written in the base language of @racket[(planet
|
program must be written in the base language of @racket[(planet
|
||||||
|
@ -220,20 +222,27 @@ $
|
||||||
However, it can also be packaged with @filepath{whalesong}.
|
However, it can also be packaged with @filepath{whalesong}.
|
||||||
@verbatim|{
|
@verbatim|{
|
||||||
$ whalesong build hello.rkt
|
$ whalesong build hello.rkt
|
||||||
|
Writing program #<path:/home/dyoo/work/whalesong/examples/hello.js>
|
||||||
|
Writing html #<path:/home/dyoo/work/whalesong/examples/hello.html>
|
||||||
|
|
||||||
|
$ ls -l hello.html
|
||||||
|
-rw-r--r-- 1 dyoo dyoo 3817 2011-09-10 15:02 hello.html
|
||||||
|
$ ls -l hello.js
|
||||||
|
-rw-r--r-- 1 dyoo dyoo 2129028 2011-09-10 15:02 hello.js
|
||||||
|
|
||||||
$ ls -l hello.xhtml
|
|
||||||
-rw-rw-r-- 1 dyoo nogroup 692213 Jun 7 18:00 hello.xhtml
|
|
||||||
}|
|
}|
|
||||||
Running @tt{whalesong build} on a Racket program will produce a self-contained
|
|
||||||
@filepath{.xhtml} file. If you open this file in your favorite web browser,
|
@margin-note{Visit @link["http://hashcollision.org/whalesong/examples/hello/hello.html"]{hello.html} to execute this program.}
|
||||||
you should see a triumphant message show on screen.
|
Running @tt{whalesong build} on a Racket program will produce a
|
||||||
|
@filepath{.html} and @filepath{.js} file. If you open the
|
||||||
|
@filepath{.html} in your favorite web browser, you should see a
|
||||||
|
triumphant message show on screen.
|
||||||
|
|
||||||
|
|
||||||
We can do something slightly more interesting. Let's write a Whalesong program
|
We can do something slightly more interesting. Let's write a Whalesong program
|
||||||
that accesses the JavaScript DOM. Call this file @filepath{dom-play.rkt}.
|
that accesses the JavaScript DOM. Call this file @filepath{dom-play.rkt}.
|
||||||
@margin-note{
|
@margin-note{
|
||||||
The generated program can be downloaded here: @link["http://hashcollision.org/whalesong/examples/dom-play.xhtml"]{dom-play.xhtml}
|
Visit @link["http://hashcollision.org/whalesong/examples/dom-play/dom-play.html"]{dom-play.html} to execute this program.}
|
||||||
}
|
|
||||||
|
|
||||||
@filebox["dom-play.rkt"]{
|
@filebox["dom-play.rkt"]{
|
||||||
@codeblock|{
|
@codeblock|{
|
||||||
|
@ -272,7 +281,7 @@ The generated program can be downloaded here: @link["http://hashcollision.org/wh
|
||||||
}|}
|
}|}
|
||||||
This program uses the @link["http:/jquery.com"]{JQuery} API provided by @racketmodname[(planet dyoo/whalesong/js)],
|
This program uses the @link["http:/jquery.com"]{JQuery} API provided by @racketmodname[(planet dyoo/whalesong/js)],
|
||||||
as well as the native JavaScript FFI to produce output on the browser.
|
as well as the native JavaScript FFI to produce output on the browser.
|
||||||
If w run Whalesong on this program, and view the resulting @filepath{dom-play.xhtml} in your
|
If w run Whalesong on this program, and view the resulting @filepath{dom-play.html} in your
|
||||||
web browser, we should see a pale, green page with some output.
|
web browser, we should see a pale, green page with some output.
|
||||||
|
|
||||||
|
|
||||||
|
@ -289,12 +298,12 @@ function and define it in a module called @filepath{fact.rkt}:
|
||||||
|
|
||||||
@margin-note{
|
@margin-note{
|
||||||
The files can also be downloaded here:
|
The files can also be downloaded here:
|
||||||
@itemlist[@item{@link["http://hashcollision.org/whalesong/fact-example/fact.rkt"]{fact.rkt}}
|
@itemlist[@item{@link["http://hashcollision.org/whalesong/examples/fact/fact.rkt"]{fact.rkt}}
|
||||||
@item{@link["http://hashcollision.org/whalesong/fact-example/index.html"]{index.html}}]
|
@item{@link["http://hashcollision.org/whalesong/examples/fact/index.html"]{index.html}}]
|
||||||
with generated JavaScript binaries here:
|
with generated JavaScript binaries here:
|
||||||
@itemlist[
|
@itemlist[
|
||||||
@item{@link["http://hashcollision.org/whalesong/fact-example/fact.js"]{fact.js}}
|
@item{@link["http://hashcollision.org/whalesong/examples/fact/fact.js"]{fact.js}}
|
||||||
@item{@link["http://hashcollision.org/whalesong/fact-example/runtime.js"]{runtime.js}}
|
@item{@link["http://hashcollision.org/whalesong/examples/fact/runtime.js"]{runtime.js}}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,7 +320,7 @@ with generated JavaScript binaries here:
|
||||||
(* x (fact (sub1 x)))]))
|
(* x (fact (sub1 x)))]))
|
||||||
}|}
|
}|}
|
||||||
|
|
||||||
Instead of creating a standalone @tt{.xhtml}, we can use @tt{whalesong} to
|
Instead of creating a standalone @tt{.html}, we can use @tt{whalesong} to
|
||||||
get us the module's code. From the command-line:
|
get us the module's code. From the command-line:
|
||||||
@verbatim|{
|
@verbatim|{
|
||||||
$ whalesong get-javascript fact.rkt > fact.js
|
$ whalesong get-javascript fact.rkt > fact.js
|
||||||
|
@ -373,6 +382,7 @@ The factorial of 10000 is <span id="answer">being computed</span>.
|
||||||
}|
|
}|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@margin-note{See: @link["http://hashcollision.org/whalesong/examples/fact/bad-index.html"]{bad-index.html}.}
|
||||||
Replacing the @racket[10000] with @racket["one-billion-dollars"] should
|
Replacing the @racket[10000] with @racket["one-billion-dollars"] should
|
||||||
reliably produce a proper error message.
|
reliably produce a proper error message.
|
||||||
|
|
||||||
|
@ -385,28 +395,29 @@ Whalesong provides a command-line utility called @tt{whalesong} for
|
||||||
translating Racket to JavaScript. It can be run in several modes:
|
translating Racket to JavaScript. It can be run in several modes:
|
||||||
|
|
||||||
@itemize[
|
@itemize[
|
||||||
@item{To create standalone XHTML documents}
|
@item{To create HTML + js documents}
|
||||||
@item{To output the compiled JavaScript as a single @filepath{.js} file}
|
@item{To output the compiled JavaScript as a single @filepath{.js} file}
|
||||||
@item{To output the compiled JavaScript as several @filepath{.js} files, one per module. (this isn't done yet...)}
|
|
||||||
]
|
]
|
||||||
|
|
||||||
Using @tt{whalesong} to generate standalone XHTML documents is
|
Using @tt{whalesong} to generate HTML+js documents is
|
||||||
relatively straightforward with the @tt{build} command. To use it,
|
relatively straightforward with the @tt{build} command. To use it,
|
||||||
pass the name of the file to it:
|
pass the name of the file to it:
|
||||||
@verbatim|{
|
@verbatim|{
|
||||||
$ whalesong build [name-of-racket-file]
|
$ whalesong build [name-of-racket-file]
|
||||||
}|
|
}|
|
||||||
An @filepath{.xhtml} will be written to the current directory.
|
A @filepath{.html} and @filepath{.js} will be written to the current directory, as will any external resources that the program uses.
|
||||||
|
|
||||||
Almost all of the @tt{whalesong} commands support two command line options:
|
Almost all of the @tt{whalesong} commands support two command line options:
|
||||||
|
|
||||||
@itemize{
|
@itemize{
|
||||||
|
|
||||||
@item{@verbatim{--compress-javascript}: Use Google Closure's JavaScript
|
@item{@verbatim{--compress-javascript} Use Google Closure's JavaScript
|
||||||
compiler to significantly compress the JavaScript. Using this
|
compiler to significantly compress the JavaScript. Using this
|
||||||
currently requires a Java 1.6 JDK.}
|
currently requires a Java 1.6 JDK.}
|
||||||
|
|
||||||
@item{@verbatim{--verbose}: write verbose debugging information to standard error.}
|
@item{@verbatim{--verbose} Write verbose debugging information to standard error.}
|
||||||
|
|
||||||
|
@item{@verbatim{--dest-dir} Write files to a separate directory, rather than the current directory.}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -421,11 +432,10 @@ program.
|
||||||
|
|
||||||
@subsection{@tt{build}}
|
@subsection{@tt{build}}
|
||||||
|
|
||||||
Given the name of a program, this builds a standalone
|
Given the name of a program, this builds
|
||||||
@filepath{.xhtml} file into the current working directory that
|
@filepath{.html} and @filepath{.js} files into the current working directory.
|
||||||
executes the program in a web browser.
|
|
||||||
|
|
||||||
The @filepath{.xhtml} should be self-contained, with an exception: if
|
The @filepath{.html} and @filepath{.js} should be self-contained, with an exception: if
|
||||||
the file uses any external @tech{resource}s by using
|
the file uses any external @tech{resource}s by using
|
||||||
@racket[define-resource], those resources are written into the current
|
@racket[define-resource], those resources are written into the current
|
||||||
working directory, if they do not already exist there.
|
working directory, if they do not already exist there.
|
||||||
|
@ -545,7 +555,7 @@ the page itself is a source of state, it too will be passed to
|
||||||
callbacks. This library presents a functional version of the DOM in
|
callbacks. This library presents a functional version of the DOM in
|
||||||
the form of a @tech{view}.
|
the form of a @tech{view}.
|
||||||
|
|
||||||
|
@margin-note{Visit @link["http://hashcollision.org/whalesong/examples/tick-tock/tick-tock.html"]{tick-tock.html} to execute this program.}
|
||||||
Let's demonstrate this by creating a basic ticker that counts on the
|
Let's demonstrate this by creating a basic ticker that counts on the
|
||||||
screen every second.
|
screen every second.
|
||||||
|
|
||||||
|
@ -611,6 +621,56 @@ by @racket[on-tick], though because we're on the web, we can
|
||||||
bind to many other kinds of web events (by using @racket[view-bind]).}
|
bind to many other kinds of web events (by using @racket[view-bind]).}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@subsection{More web-world examples}
|
||||||
|
Here are a collection of web-world demos:
|
||||||
|
@itemize[
|
||||||
|
@item{@link["http://hashcollision.org/whalesong/examples/attr-animation/attr-animation.html"]{attr-animation.html} [@link["http://hashcollision.org/whalesong/examples/attr-animation/attr-animation.rkt"]{src}] Uses @racket[update-view-attr] and @racket[on-tick] to perform a simple color animation.}
|
||||||
|
|
||||||
|
@item{@link["http://hashcollision.org/whalesong/examples/dwarves/dwarves.html"]{dwarves.html}
|
||||||
|
[@link["http://hashcollision.org/whalesong/examples/dwarves/dwarves.rkt"]{src}]
|
||||||
|
Uses @racket[view-show] and @racket[view-hide] to manipulate a view. Click on a dwarf to make them hide.
|
||||||
|
}
|
||||||
|
|
||||||
|
@item{@link["http://hashcollision.org/whalesong/examples/dwarves-with-remove/dwarves-with-remove.html"]{dwarves-with-remove.html}
|
||||||
|
[@link["http://hashcollision.org/whalesong/examples/dwarves-with-remove/dwarves-with-remove.rkt"]{src}]
|
||||||
|
Uses @racket[view-focus?] and @racket[view-remove] to see if a dwarf should be removed from the view.
|
||||||
|
}
|
||||||
|
|
||||||
|
@item{@link["http://hashcollision.org/whalesong/examples/field/field.html"]{field.html}
|
||||||
|
[@link["http://hashcollision.org/whalesong/examples/field/field.rkt"]{src}]
|
||||||
|
Uses @racket[view-bind] to read a text field, and @racket[update-view-text] to change
|
||||||
|
the text content of an element.
|
||||||
|
}
|
||||||
|
|
||||||
|
@item{@link["http://hashcollision.org/whalesong/examples/phases/phases.html"]{phases.html}
|
||||||
|
[@link["http://hashcollision.org/whalesong/examples/phases/phases.rkt"]{src}]
|
||||||
|
Switches out one view entirely in place of another. Different views can correspond to phases in a program.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@item{@link["http://hashcollision.org/whalesong/examples/tick-tock/tick-tock.html"]{tick-tock.html}
|
||||||
|
[@link["http://hashcollision.org/whalesong/examples/tick-tock/tick-tock.rkt"]{src}]
|
||||||
|
Uses @racket[on-tick] to show a timer counting up.
|
||||||
|
}
|
||||||
|
|
||||||
|
@item{@link["http://hashcollision.org/whalesong/examples/redirected/redirected.html"]{redirected.html}
|
||||||
|
[@link["http://hashcollision.org/whalesong/examples/redirected/redirected.rkt"]{src}]
|
||||||
|
Uses @racket[on-tick] to show a timer counting up, and also uses @racket[open-output-element] to
|
||||||
|
pipe side-effecting @racket[printf]s to a hidden @tt{div}.
|
||||||
|
}
|
||||||
|
|
||||||
|
@item{@link["http://hashcollision.org/whalesong/examples/todo/todo.html"]{todo.html}
|
||||||
|
[@link["http://hashcollision.org/whalesong/examples/todo/todo.rkt"]{src}]
|
||||||
|
A simple TODO list manager.
|
||||||
|
}
|
||||||
|
|
||||||
|
@item{@link["http://hashcollision.org/whalesong/examples/where-am-i/where-am-i.html"]{where-am-i.html}
|
||||||
|
[@link["http://hashcollision.org/whalesong/examples/where-am-i/where-am-i.rkt"]{src}]
|
||||||
|
Uses @racket[on-location-change] and @racket[on-mock-location-change] to demonstrate location services.
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@subsection{@racket[big-bang] and its options}
|
@subsection{@racket[big-bang] and its options}
|
||||||
@declare-exporting/this-package[web-world]
|
@declare-exporting/this-package[web-world]
|
||||||
|
@ -824,6 +884,11 @@ Update the form value of the node at the focus.}
|
||||||
@defproc[(view-append-child [d dom]) view]{
|
@defproc[(view-append-child [d dom]) view]{
|
||||||
Add the dom node @racket[d] as the last child of the focused node.}
|
Add the dom node @racket[d] as the last child of the focused node.}
|
||||||
|
|
||||||
|
@defproc[(view-remove [v view]) view]{
|
||||||
|
Remove the dom node at the focus from the view @racket[v]. Focus tries to move
|
||||||
|
to the right, if there's a next sibling. If that fails, focus then
|
||||||
|
moves to the left, if there's a previous sibling. If that fails too,
|
||||||
|
then focus moves to the parent.}
|
||||||
|
|
||||||
|
|
||||||
@subsection{Events}
|
@subsection{Events}
|
||||||
|
@ -1569,14 +1634,26 @@ Whalesong uses code and utilities from the following external projects:
|
||||||
]
|
]
|
||||||
|
|
||||||
The following folks have helped tremendously in the implementation of
|
The following folks have helped tremendously in the implementation of
|
||||||
Whalesong by implementing libraries, giving guidence, and suggesting
|
Whalesong by implementing libraries, giving guidence, reporting bugs,
|
||||||
improvements:
|
and suggesting improvements.
|
||||||
|
|
||||||
@itemlist[
|
@;;;;
|
||||||
|
@; in no particular order... really! I'm shuffling them! :)
|
||||||
|
@;;;;
|
||||||
|
@(apply itemlist
|
||||||
|
(shuffle (list
|
||||||
@item{Ethan Cecchetti}
|
@item{Ethan Cecchetti}
|
||||||
@item{Scott Newman}
|
@item{Scott Newman}
|
||||||
@item{Zhe Zhang}
|
@item{Zhe Zhang}
|
||||||
@item{Jens Axel Søgaard}
|
@item{Jens Axel Søgaard}
|
||||||
|
@item{Jay McCarthy}
|
||||||
|
@item{Sam Tobin-Hochstadt}
|
||||||
|
@item{Doug Orleans}
|
||||||
|
@item{Richard Cleis}
|
||||||
|
@item{Asumu Takikawa}
|
||||||
|
@item{Eric Hanchrow}
|
||||||
|
@item{Greg Hendershott}
|
||||||
@item{Shriram Krishnamurthi}
|
@item{Shriram Krishnamurthi}
|
||||||
@item{Emmanuel Schanzer}
|
@item{Emmanuel Schanzer}
|
||||||
]
|
@item{Robby Findler}))
|
||||||
|
)
|
|
@ -6,19 +6,20 @@
|
||||||
|
|
||||||
|
|
||||||
;; draw: world view -> view
|
;; draw: world view -> view
|
||||||
(define (draw w v)
|
(define (draw w dom)
|
||||||
(update-view-text (view-focus v "counter") w))
|
(update-view-text (view-focus dom "counter") w))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; tick: world view -> world
|
;; tick: world view -> world
|
||||||
(define (tick w v)
|
(define (tick w v)
|
||||||
(printf "Tick ~s\n" w)
|
(add1 w))
|
||||||
(+ w 1))
|
|
||||||
|
(define (stop? world dom)
|
||||||
|
(> world 10))
|
||||||
|
|
||||||
(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)
|
(stop-when stop?))
|
||||||
(> w 10))))
|
|
||||||
|
|
|
@ -44,7 +44,12 @@
|
||||||
var domOpenF =
|
var domOpenF =
|
||||||
// To go down, just take the children.
|
// To go down, just take the children.
|
||||||
function(n) {
|
function(n) {
|
||||||
return [].slice.call(n.childNodes, 0);
|
var i;
|
||||||
|
var result = [];
|
||||||
|
for (i = 0; i < n.childNodes.length; i++) {
|
||||||
|
result.push(n.childNodes[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
var domCloseF =
|
var domCloseF =
|
||||||
// To go back up, take the node, do a shallow cloning, and replace the children.
|
// To go back up, take the node, do a shallow cloning, and replace the children.
|
||||||
|
@ -539,8 +544,7 @@
|
||||||
|
|
||||||
|
|
||||||
var isDomNode = function(x) {
|
var isDomNode = function(x) {
|
||||||
return (x.hasOwnProperty('nodeType') &&
|
return (x.nodeType === 1);
|
||||||
x.nodeType === 1);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -676,7 +680,7 @@
|
||||||
var key, val;
|
var key, val;
|
||||||
var result = makeList();
|
var result = makeList();
|
||||||
for (key in obj) {
|
for (key in obj) {
|
||||||
if (obj.hasOwnProperty(key)) {
|
if (obj.hasOwnProperty && obj.hasOwnProperty(key)) {
|
||||||
val = obj[key];
|
val = obj[key];
|
||||||
if (typeof(val) === 'number') {
|
if (typeof(val) === 'number') {
|
||||||
result = makePair(makeList(makeSymbol(key),
|
result = makePair(makeList(makeSymbol(key),
|
||||||
|
@ -817,7 +821,9 @@
|
||||||
LocationEventSource.prototype.onStart = function(fireEvent) {
|
LocationEventSource.prototype.onStart = function(fireEvent) {
|
||||||
if (this.id === undefined) {
|
if (this.id === undefined) {
|
||||||
var success = function(position) {
|
var success = function(position) {
|
||||||
if (position.hasOwnProperty('coords') &&
|
if (position.hasOwnProperty &&
|
||||||
|
position.hasOwnProperty('coords') &&
|
||||||
|
position.coords.hasOwnProperty &&
|
||||||
position.coords.hasOwnProperty('latitude') &&
|
position.coords.hasOwnProperty('latitude') &&
|
||||||
position.coords.hasOwnProperty('longitude')) {
|
position.coords.hasOwnProperty('longitude')) {
|
||||||
fireEvent(undefined,
|
fireEvent(undefined,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user