4 Jsworld
jsworld provides a world programming library that allows simple
animation and games, as well as reactive HTML graphical user
interfaces.
(require (planet dyoo/js-vm:1:7/jsworld/jsworld)) |
(big-bang a-world handlers ...) → world |
a-world : world |
handlers : handler |
Starts a reactive computation with
big-bang.
The rest of the arguments hook into the reactive computation.
By default, the page that’s displayed contains a rendering of the
world value. In the presence of an to-draw or
to-draw-page handler, big-bang will show a
customized view.
The majority of the handlers register different stimuli that can
trigger changes to the world. One instance is on-tick, which
registers a function to update the world on a clock tick.
When the big-bang computation terminates through a
stop-when, the final world is returned as its value.
(to-draw hook) → handler |
hook : (world -> scene) |
For simple applications,
to-draw is sufficient to draw a scene onto the display.
The following program shows a ball falling down a scene.
#lang planet dyoo/js-vm:1:7 |
(define WIDTH 320) |
(define HEIGHT 480) |
(define RADIUS 15) |
|
(define INITIAL-WORLD 0) |
|
(define (tick w) |
(+ w 5)) |
|
(define (hits-floor? w) |
(>= w HEIGHT)) |
|
(check-expect (hits-floor? 0) false) |
(check-expect (hits-floor? HEIGHT) true) |
|
(define (render w) |
(place-image (circle RADIUS "solid" "red") (/ WIDTH 2) w |
(empty-scene WIDTH HEIGHT))) |
|
(big-bang INITIAL-WORLD |
(on-tick tick 1/15) |
(to-draw render) |
(stop-when hits-floor?)) |
(stop-when stop?) → handler? |
stop? : (world -> boolean) |
When the world should be stopped – when
stop? applied to the world
produces
true – then the
big-bang terminates.
The program:
counts up to ten and then stops.
(on-tick world-updater [delay]) → handler? |
world-updater : (world -> world) |
delay : number? = 1/20 |
Produces a handler that responds to clock ticks. By default,
every tick comes every 1/20’th of a second.
(on-key world-updater) → handler? |
world-updater : (world key? -> world) |
Produces a handler that responds to key events.
(key=? key1 key2) → boolean? |
key1 : key? |
key2 : key? |
Produces true if key1 is equal to key2.
(to-draw-page to-dom to-css) → handler |
to-dom : (world -> (DOM-sexp)) |
to-css : (world -> (CSS-sexp)) |
One of the main handlers to
big-bang is
to-draw-page,
which controls how the world is rendered on screen. The first
argument computes a rendering of the world as a DOM tree, and the
second argument computes that tree’s styling.
4.1 Jsworld Types
A dom-sexp describes the structure of a web page:
dom-sexp | | = | | (list dom-element dom-sexp ...) |
a css-sexp describes the structure of a page’s styling:
css-sexp | | = | | (listof (cons (or dom-element string) | (listof attrib))) |
|
An attrib is a:
attrib | | = | | (list string string) |
Each of the dom-elements can take in an optional attribute list to
assign to the new dom element; the common useful attribute is a key-value binding for an "id",
which can be used to identify an element in the css-drawing function.
Here are examples of a dom-expr and a css-sexp.
(define a-dom-sexp (list (js-div '(("id" "main-div"))) |
(list (js-text "Hello world")))) |
|
(define a-css-sexp (list (list "main-div" |
(list "background" "white") |
(list "font-size" "40px")))) |
4.2 HTML user interface constructors
Here are the dom-element constructors.
(js-div [attribs]) → dom-element? |
attribs : (listof attrib?) = '() |
Constructs a div element.
(js-p [attribs]) → dom-element? |
attribs : (listof attrib?) = '() |
Constructs a paragraph element.
(js-button world-update-f [attribs]) → dom-element |
world-update-f : (world -> world) |
attribs : (listof attrib) = '() |
Constructs a button. When the button is pressed, the world is updated through world-update-f.
The following example counts how many times a button has been clicked.
(js-text text) → dom-element |
text : string? |
Constructs regular text.
(js-input type world-update-f [attribs]) → dom-element |
type : string |
| world-update-f | | : | | (or/c (world string -> world) | (world boolean -> world)) |
|
|
attribs : (listof attrib) = '() |
Creates an input form element. The types that are currently supported are:
"text"
"password"
"checkbox"
When the user changes the content of the form element, the runtime
uses world-update-f to update the world. If the
type is either "text" or "password", then
the string value of the element will be passed as the second argument
to it. If type is "checkbox", a boolean
representing the checked status of the element will be passed to it.
The example below has a single text input form element, which allows the user to enter
some value.
#lang planet dyoo/js-vm:1:7 |
(define (refresh w form-val) |
form-val) |
|
(define input-node |
(js-input "text" refresh '(("id" "myname")))) |
|
(define (draw w) |
(list (js-div) |
(list (js-div) (list (js-text (format "I see: ~s~n" w)))) |
(list (js-div) (list input-node)))) |
|
|
(define (draw-css w) |
'()) |
|
(big-bang "" |
(to-draw-page draw draw-css)) |
The example below uses a checkbox to select among three elements:
#lang planet dyoo/js-vm:1:7 |
(define (make-ingredient-checkbox-sexp ingredient) |
(local [(define (on-check w v) |
(cond |
[v |
(cons ingredient w)] |
[else |
(remove ingredient w)]))] |
(list (js-div) |
(list (js-text ingredient)) |
(list (js-input "checkbox" |
on-check |
`(("value" ,ingredient))))))) |
|
(define c1 (make-ingredient-checkbox-sexp "mushrooms")) |
(define c2 (make-ingredient-checkbox-sexp "green peppers")) |
(define c3 (make-ingredient-checkbox-sexp "olives")) |
|
(define (draw w) |
(list (js-div) |
c1 |
c2 |
c3 |
(list (js-text (format "The world is: ~s" w))))) |
|
(define (draw-css w) |
'()) |
|
(big-bang '() |
(to-draw-page draw draw-css)) |
(js-img url [attribs]) → dom-element |
url : string |
attribs : (listof attrib) = '() |
Creates an image element.
(js-select options world-update-f [attribs]) → dom-element |
options : (listof string?) |
world-update-f : (world string -> world) |
attribs : (listof attrib) = '() |
Constructs a select element with the given options. Whenever a new
option is selected, the world-update-f function is called to
get the new world.
The example below has a select with five elements.
#lang planet dyoo/js-vm:1:7 |
(define (select-house w an-option) |
an-option) |
|
(define a-select-element |
(js-select (list "" |
"Gryffindor" |
"Hufflepuff" |
"Ravenclaw" |
"Slytherin") |
select-house)) |
|
(define (draw w) |
(list (js-div) |
(list a-select-element) |
(list (js-text (format "House: ~a" w))))) |
|
(define (draw-css w) |
'()) |
|
(big-bang "" |
(to-draw-page draw draw-css)) |