changeset 1:f84d5e8aa992

Complete working example with required submit button click
author Adam Chlipala <adam@chlipala.net>
date Thu, 29 Dec 2011 15:26:46 -0500
parents 0c0f903d9440
children df095eecba63
files examples/server.ur examples/server.urp include/ajaxUpload.h src/c/ajaxUpload.c src/ur/ajaxUpload.ur src/ur/ajaxUpload.urs src/ur/ajaxUploadFfi.urs src/ur/lib.urp
diffstat 8 files changed, 94 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/examples/server.ur	Thu Dec 29 14:37:31 2011 -0500
+++ b/examples/server.ur	Thu Dec 29 15:26:46 2011 -0500
@@ -1,5 +1,39 @@
+sequence ids
+
+table images : { Id : int, MimeType : string, Content : blob }
+  PRIMARY KEY Id
+
 fun main () =
-    au <- AjaxUpload.render ();
+    status <- source <xml/>;
+    au <- AjaxUpload.render {OnBegin = set status <xml>Uploading</xml>,
+                             OnSuccess = fn h =>
+                                            let
+                                                fun addImage () =
+                                                    r <- AjaxUpload.claim h;
+                                                    case r of
+                                                        AjaxUpload.NotFound => return None
+                                                      | AjaxUpload.Found r =>
+                                                        id <- nextval ids;
+                                                        dml (INSERT INTO images (Id, MimeType, Content)
+                                                             VALUES ({[id]}, {[r.MimeType]}, {[r.Content]}));
+                                                        return (Some id)
+                                            in
+                                                ido <- rpc (addImage ());
+                                                case ido of
+                                                    None => alert "Newly uploaded image not found!"
+                                                  | Some id =>
+                                                    let
+                                                        fun image () =
+                                                            r <- oneRow1 (SELECT images.MimeType, images.Content
+                                                                          FROM images
+                                                                          WHERE images.Id = {[id]});
+                                                            returnBlob r.Content (blessMime r.MimeType)
+                                                    in
+                                                        set status <xml><img src={url (image ())}/></xml>
+                                                    end
+                                            end};
     return <xml><body>
       {au}
+      <hr/>
+      <dyn signal={signal status}/>
     </body></xml>
--- a/examples/server.urp	Thu Dec 29 14:37:31 2011 -0500
+++ b/examples/server.urp	Thu Dec 29 15:26:46 2011 -0500
@@ -2,5 +2,6 @@
 rewrite url Server/*
 database dbname=test
 sql server.sql
+allow mime image/jpeg
 
 server
--- a/include/ajaxUpload.h	Thu Dec 29 14:37:31 2011 -0500
+++ b/include/ajaxUpload.h	Thu Dec 29 15:26:46 2011 -0500
@@ -1,3 +1,7 @@
 #include <urweb.h>
 
 uw_Basis_string uw_AjaxUploadFfi_tweakForm(uw_context, uw_Basis_string iframeId, uw_Basis_string submitId);
+uw_Basis_string uw_AjaxUploadFfi_notifySuccess(uw_context, uw_Basis_string submitId, uw_Basis_int handle);
+
+uw_Basis_string uw_AjaxUploadFfi_idToString(uw_context, uw_Basis_string);
+uw_Basis_string uw_AjaxUploadFfi_stringToId(uw_context, uw_Basis_string);
--- a/src/c/ajaxUpload.c	Thu Dec 29 14:37:31 2011 -0500
+++ b/src/c/ajaxUpload.c	Thu Dec 29 15:26:46 2011 -0500
@@ -1,3 +1,6 @@
+#include <ctype.h>
+#include <stdio.h>
+
 #include <ajaxUpload.h>
 
 uw_Basis_string uw_AjaxUploadFfi_tweakForm(uw_context ctx, uw_Basis_string iframeId, uw_Basis_string submitId) {
@@ -6,10 +9,37 @@
                           iframeId,
                           "\" name=\"",
                           iframeId,
-                          "\" src=\"#\"></iframe>\n<script type=\"text/javascript\">var subm = document.getElementById(\"",
+                          "\" src=\"#\" style=\"width:0;height:0;border:0px solid #fff;\"></iframe>\n<script type=\"text/javascript\">var subm = document.getElementById(\"",
                           submitId,
                           "\"); subm.parentNode.target = \"",
                           iframeId,
-                          "\";</script>",
+                          "\"; var onSub = subm.onmousedown; subm.onmousedown = undefined; subm.parentNode.onsubmit = function() { onSub(); return true; }; subm.withHandle = subm.onkeydown; subm.onkeydown = undefined; </script>",
                           NULL);
 }
+
+uw_Basis_string uw_AjaxUploadFfi_notifySuccess(uw_context ctx, uw_Basis_string submitId, uw_Basis_int handle) {
+  return uw_Basis_mstrcat(ctx,
+                          "<script type=\"text/javascript\">var subm = window.top.document.getElementById(\"",
+                          submitId,
+                          "\"); window.top.event = {keyCode : ",
+                          uw_Basis_htmlifyInt(ctx, handle),
+                          "}; subm.withHandle(); </script>",
+                          NULL);
+}
+
+uw_Basis_string uw_AjaxUploadFfi_idToString(uw_context ctx, uw_Basis_string s) {
+  return s;
+}
+
+uw_Basis_string uw_AjaxUploadFfi_stringToId(uw_context ctx, uw_Basis_string s) {
+  char *s2 = s;
+
+  if (*s2 == '-')
+    ++s2;
+
+  for (++s2; *s2; ++s2)
+    if (!isdigit(*s2))
+      uw_error(ctx, FATAL, "AjaxUploadFfi.stringToId: Invalid ID");
+
+  return s;
+}
--- a/src/ur/ajaxUpload.ur	Thu Dec 29 14:37:31 2011 -0500
+++ b/src/ur/ajaxUpload.ur	Thu Dec 29 15:26:46 2011 -0500
@@ -25,24 +25,30 @@
     ro <- oneOrNoRows1 (SELECT scratch.Filename, scratch.MimeType, scratch.Content
                         FROM scratch
                         WHERE scratch.Handle = {[h]});
-    return (case ro of
-                None => NotFound
-              | Some r => Found r)
+    case ro of
+        None => return NotFound
+      | Some r =>
+        dml (DELETE FROM scratch
+             WHERE Handle = {[h]});
+        return (Found r)
 
-fun render {} =
+fun render {OnBegin = ob, OnSuccess = os} =
     iframeId <- fresh;
     submitId <- fresh;
+    submitId' <- return (AjaxUploadFfi.idToString submitId);
     let
         fun upload r =
             h <- nextval handles;
             dml (INSERT INTO scratch (Handle, Filename, MimeType, Content, Created)
                  VALUES ({[h]}, {[fileName r.File]}, {[fileMimeType r.File]}, {[fileData r.File]}, CURRENT_TIMESTAMP));
-            return <xml>OK!</xml>
+            return <xml><body>
+              {AjaxUploadFfi.notifySuccess (AjaxUploadFfi.stringToId submitId') h}
+            </body></xml>
     in
         return <xml>
           <form>
             <upload{#File}/>
-            <submit action={upload} id={submitId}/>
+            <submit action={upload} id={submitId} onmousedown={ob} onkeydown={os}/>
           </form>
           {AjaxUploadFfi.tweakForm iframeId submitId}
         </xml>
--- a/src/ur/ajaxUpload.urs	Thu Dec 29 14:37:31 2011 -0500
+++ b/src/ur/ajaxUpload.urs	Thu Dec 29 15:26:46 2011 -0500
@@ -12,5 +12,9 @@
 val claim : handle -> transaction claim_result
 (* In server-side code, claim ownership of a [handle]'s contents, deleting the persistent record of the file data. *)
 
-val render : {} -> transaction xbody
+val render : {OnBegin : transaction {},
+              (* Run this when an upload begins. *)
+              OnSuccess : handle -> transaction {}
+              (* Run this after a successful upload. *)}
+             -> transaction xbody
 (* Produce HTML for a file upload control *)
--- a/src/ur/ajaxUploadFfi.urs	Thu Dec 29 14:37:31 2011 -0500
+++ b/src/ur/ajaxUploadFfi.urs	Thu Dec 29 15:26:46 2011 -0500
@@ -1,1 +1,5 @@
 val tweakForm : id -> id -> xbody
+val notifySuccess : id -> int -> xbody
+
+val idToString : id -> string
+val stringToId : string -> id
--- a/src/ur/lib.urp	Thu Dec 29 14:37:31 2011 -0500
+++ b/src/ur/lib.urp	Thu Dec 29 15:26:46 2011 -0500
@@ -1,5 +1,6 @@
 library config
 ffi ajaxUploadFfi
 link -lurweb_ajaxUpload
+jsFunc AjaxUploadFfi.getHandle=getHandle
 
 ajaxUpload