Mercurial > urweb
changeset 645:1b571a05874c
React demo
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Tue, 10 Mar 2009 11:18:01 -0400 |
parents | 8e17e6b615bd |
children | fb2a0e76dcef |
files | demo/prose demo/react.ur demo/react.urp demo/react.urs include/urweb.h src/c/urweb.c src/cjr_print.sml src/scriptcheck.sml |
diffstat | 8 files changed, 27 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/demo/prose Tue Mar 10 10:49:18 2009 -0400 +++ b/demo/prose Tue Mar 10 11:18:01 2009 -0400 @@ -191,3 +191,9 @@ <p>Ur/Web makes it easy to write code whose execution should be distributed between the web server and client web browsers. Server-side code is compiled to efficient native code, and client-side code is compiled to JavaScript. Ur/Web programmers don't need to worry about these details, because the language and standard library provide a uniform ML-like interface for the whole process.</p> <p>Here's an example of a button that, when clicked, opens an alert dialog on the client.</p> + +react.urp + +<p>Most client-side JavaScript programs modify page contents imperatively, but Ur/Web is based on functional-reactive programming instead. Programs allocate data sources and then describe the page as a pure function of those data sources. When the sources change, the page changes automatically.</p> + +<p>Here's an example where a button modifies a data source that affects some text on the page. The affected portion of the page is indicated with the pseudo-HTML tag <tt>dyn</tt>, whose <tt>signal</tt> attribute specifies one of these pure functions over mutable sources. A source containing data of type <tt>t</tt> has type <tt>source t</tt> and is created with the <tt>source</tt> operation within the <tt>transaction</tt> monad. Functions over sources are represented in the monad <tt>signal</tt>. Like in Haskell, we overload monad notations, so that the same return and bind operators can be used to write signals and transactions. The <tt>signal</tt> function coerces a source to a signal.</p>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demo/react.ur Tue Mar 10 11:18:01 2009 -0400 @@ -0,0 +1,6 @@ +fun main () = + s <- source "You didn't click it yet."; + return <xml><body> + <button value="Click me!" onclick={set s "Now you clicked it."}/><br/> + <dyn signal={v <- signal s; return <xml>{[v]}</xml>}/> + </body></xml>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demo/react.urp Tue Mar 10 11:18:01 2009 -0400 @@ -0,0 +1,2 @@ + +react
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demo/react.urs Tue Mar 10 11:18:01 2009 -0400 @@ -0,0 +1,1 @@ +val main : unit -> transaction page
--- a/include/urweb.h Tue Mar 10 10:49:18 2009 -0400 +++ b/include/urweb.h Tue Mar 10 11:18:01 2009 -0400 @@ -40,7 +40,7 @@ uw_unit uw_Basis_set_client_source(uw_context, uw_Basis_int, uw_Basis_string); void uw_set_script_header(uw_context, const char*); -char *uw_Basis_get_script(uw_context, uw_unit); +const char *uw_Basis_get_script(uw_context, uw_unit); char *uw_Basis_htmlifyInt(uw_context, uw_Basis_int); char *uw_Basis_htmlifyFloat(uw_context, uw_Basis_float);
--- a/src/c/urweb.c Tue Mar 10 10:49:18 2009 -0400 +++ b/src/c/urweb.c Tue Mar 10 11:18:01 2009 -0400 @@ -382,11 +382,9 @@ ctx->script_front += len; } -char *uw_Basis_get_script(uw_context ctx, uw_unit u) { +const char *uw_Basis_get_script(uw_context ctx, uw_unit u) { if (ctx->script_front == ctx->script) { - char *r = uw_malloc(ctx, 1); - r[0] = 0; - return r; + return ctx->script_header; } else { char *r = uw_malloc(ctx, 41 + (ctx->script_front - ctx->script) + strlen(ctx->script_header));
--- a/src/cjr_print.sml Tue Mar 10 10:49:18 2009 -0400 +++ b/src/cjr_print.sml Tue Mar 10 11:18:01 2009 -0400 @@ -2349,7 +2349,10 @@ newline, string "uw_set_script_header(ctx, \"", string (case side of - ServerAndClient => "<script src=\\\"/app.js\\\"></script>\\n" + ServerAndClient => "<script src=\\\"" + ^ OS.Path.joinDirFile {dir = !Monoize.urlPrefix, + file = "app.js"} + ^ "\\\"></script>\\n" | ServerOnly => ""), string "\");", newline]),
--- a/src/scriptcheck.sml Tue Mar 10 10:49:18 2009 -0400 +++ b/src/scriptcheck.sml Tue Mar 10 11:18:01 2009 -0400 @@ -38,8 +38,10 @@ val csBasis = SS.addList (SS.empty, ["new_client_source", "get_client_source", - "set_client_source", - "alert"]) + "set_client_source"]) + +val scriptWords = ["<script", + " onclick="] fun classify (ds, ps) = let @@ -54,7 +56,7 @@ let fun hasClient e = case #1 e of - EPrim (Prim.String s) => inString {needle = "<script", haystack = s} + EPrim (Prim.String s) => List.exists (fn n => inString {needle = n, haystack = s}) scriptWords | EPrim _ => false | ERel _ => false | ENamed n => IS.member (csids, n)