]> gitweb.factorcode.org Git - factor.git/commitdiff
more html stream work
authorSlava Pestov <slava@factorcode.org>
Tue, 24 Jan 2006 01:05:39 +0000 (01:05 +0000)
committerSlava Pestov <slava@factorcode.org>
Tue, 24 Jan 2006 01:05:39 +0000 (01:05 +0000)
contrib/httpd/default-responders.factor
contrib/httpd/help-responder.factor
contrib/httpd/html.factor
contrib/httpd/http-common.factor
contrib/httpd/inspect-responder.factor
contrib/httpd/live-updater.factor [new file with mode: 0644]
contrib/httpd/liveUpdater.js [new file with mode: 0644]
contrib/httpd/load.factor

index 705bccff4e59722ad645d551555c68c18acfae10..40d87c96a10ac822ee11f71c835d7c62bf58a0ca 100644 (file)
@@ -2,7 +2,7 @@
 ! See http://factor.sf.net/license.txt for BSD license.
 IN: httpd
 USING: browser-responder cont-responder file-responder
-help-responder kernel namespaces prettyprint ;
+help-responder inspect-responder kernel namespaces prettyprint ;
 
 #! Remove all existing responders, and create a blank
 #! responder table.
@@ -16,10 +16,7 @@ global [
     ] make-responder
 
     ! Online help browsing
-    [
-        "help" "responder" set
-        [ help-responder ] "get" set
-    ] make-responder
+    "help" [ help-responder ] install-cont-responder
 
     ! Global variables
     "inspector" [ inspect-responder ] install-cont-responder
index 1430c30458d015c13a1f74be2c4d119b119730a3..4f5aff21feb2983bd90ed0e09df04fda7c6c4dce 100644 (file)
@@ -1,9 +1,13 @@
 ! Copyright (C) 2006 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 IN: help-responder
-USING: help html kernel sequences ;
+USING: cont-responder hashtables help html kernel namespaces
+sequences ;
 
 : help-responder ( filename -- )
-    dup empty? [ drop "handbook" ] when
-    dup article-title
-    [ [ (help) ] with-html-stream ] html-document ;
+    [
+        "topic" "query" get hash
+        dup empty? [ drop "handbook" ] when
+        dup article-title
+        [ [ (help) ] with-html-stream ] html-document
+    ] show-final ;
index a177d92ccc4828dfa580a58b565ccc0478545319..9a279c13b8d1a5989cbeb985411db2bef8f1d370 100644 (file)
@@ -1,8 +1,9 @@
 ! Copyright (C) 2004, 2006 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 IN: html
-USING: generic hashtables help http inspector io
-kernel lists math namespaces sequences strings styles words xml ;
+USING: cont-responder generic hashtables help http inspector io
+kernel lists live-updater math namespaces sequences strings
+styles words xml ;
 
 : hex-color, ( triplet -- )
     3 swap head
@@ -60,7 +61,7 @@ kernel lists math namespaces sequences strings styles words xml ;
 
 : padding-css, ( padding -- ) "padding: " % # "px; " % ;
 
-: pre-css, ( -- ) "white-space: pre; " % ;
+: pre-css, ( -- ) "white-space: pre; font-family:monospace; " % ;
 
 : div-css-style ( style -- str )
     [
@@ -104,7 +105,7 @@ GENERIC: browser-link-href ( presented -- href )
 M: object browser-link-href drop f ;
 
 M: word browser-link-href
-    "/responder/browser" swap [
+    "/responder/browser/" swap [
         dup word-vocabulary "vocab" set word-name "word" set
     ] make-hash build-url ;
 
@@ -112,7 +113,7 @@ M: link browser-link-href
     link-name [ \ f ] unless* dup word? [
         browser-link-href
     ] [
-        [ "/responder/help/" % url-encode % ] "" make
+        "/responder/help/" swap "topic" associate build-url
     ] if ;
 
 : object-link-tag ( style quot -- )
@@ -148,13 +149,36 @@ M: html-stream stream-format ( str style stream -- )
         ] object-link-tag
     ] with-stream* ;
 
+: html-outliner ( caption contents -- )
+    <table>
+        <tr>
+            <td>
+                "replaceme" swap [
+                    [ with-html-stream ] show-final
+                ] curry "+" live-anchor
+            </td>
+            <td>
+                call
+            </td>
+        </tr>
+        <tr>
+            <td> </td>
+            <td> <div "replaceme" =id div> </div>
+        </tr>
+    </table> ;
+
+: outliner-tag ( style quot -- )
+    outline pick hash [ html-outliner ] [ call ] if* ;
+
 M: html-stream with-nested-stream ( quot style stream -- )
     [
         [
             [
-                stdio get <nested-stream> swap with-stream*
-            ] div-tag
-        ] object-link-tag
+                [
+                    stdio get <nested-stream> swap with-stream*
+                ] div-tag
+            ] object-link-tag
+        ] outliner-tag
     ] with-stream* ;
 
 M: html-stream stream-terpri [ <br/> ] with-stream* ;
@@ -176,6 +200,7 @@ M: html-stream stream-terpri [ <br/> ] with-stream* ;
         <head>
             <title> write </title>
             default-css
+            include-live-updater-js
         </head>
         <body>
             <h1> write </h1>
index dff593c7991ed2567140adcbbaa0ecd3c93e7883..1d20e967955e0c0183fde2552842036a3f18b70a 100644 (file)
@@ -67,7 +67,7 @@ sequences strings ;
     [
         swap % dup hash-empty? [
             "?" %
-            hash>alist
+            dup hash>alist
             [ [ url-encode ] map "=" join ] map "&" join %
         ] unless drop
     ] "" make ;
index 94114d038dc986dfb2654eab3b3c47eb4131dfc1..80b826283cc9536190063b9f146b8bd96b662802 100644 (file)
@@ -15,4 +15,4 @@ M: general-t browser-link-href
     append ;
 
 : inspect-responder ( url -- )
-    drop [ global http-inspect ] show-final ;
+    [ global http-inspect ] show-final ;
diff --git a/contrib/httpd/live-updater.factor b/contrib/httpd/live-updater.factor
new file mode 100644 (file)
index 0000000..eae2a24
--- /dev/null
@@ -0,0 +1,158 @@
+! Copyright (C) 2004 Chris Double.
+! 
+! Redistribution and use in source and binary forms, with or without
+! modification, are permitted provided that the following conditions are met:
+! 
+! 1. Redistributions of source code must retain the above copyright notice,
+!    this list of conditions and the following disclaimer.
+! 
+! 2. Redistributions in binary form must reproduce the above copyright notice,
+!    this list of conditions and the following disclaimer in the documentation
+!    and/or other materials provided with the distribution.
+! 
+! THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+! INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+! FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+! DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+! OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+! WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+!
+! cont-responder code for display forms and anchors that use XMLHttpRequest
+! and the 'liveUpdater.js' code.
+IN: live-updater
+USING: kernel io strings html cont-responder namespaces lists ;
+
+: get-live-updater-js* ( stream -- string )
+  #! Read all lines from the stream, creating a string of the result.
+  dup stream-readln dup [ % "\n" % get-live-updater-js* ] [ drop stream-close ] if ;
+
+: get-live-updater-js ( filename -- string )
+  #! Return the liveUpdater javascript code as a string.
+  "/contrib/httpd/liveUpdater.js" <resource-stream> contents ;
+
+: live-updater-url ( -- url )
+  #! Generate an URL to the liveUpdater.js code.
+  t [
+    [ get-live-updater-js write ] show        
+  ] register-continuation id>url ;
+
+: include-live-updater-js ( -- )
+  #! Write out the HTML script to include the live updater
+  #! javascript code.
+  <script "JavaScript" =language live-updater-url =src script> 
+    "" write
+  </script> ;
+
+: write-live-anchor-tag ( text -- id )
+  #! Write out the HTML for the clickable anchor. This
+  #! will have no actionable HREF assigned to it. Instead
+  #! an onclick is set via DHTML later to make it run a
+  #! quotation on the server. The randomly generated id
+  #! for the anchor is returned.
+  <a get-random-id dup =id "#" =href a>  
+    swap write
+  </a> ;  
+
+: register-live-anchor-quot ( div-id div-quot -- kid )
+  #! Register the 'quot' with the cont-responder so
+  #! that when it is run it will produce an HTML
+  #! fragment which is the output generated by calling 
+  #! 'quot'. That HTML fragment will be wrapped in a 
+  #! 'div' with the given id.  
+  [
+    "div-quot" set
+    "div-id" set
+  ] make-hash [ 
+    [
+      t "disable-initial-redirect?" set
+      [ 
+        <div "div-id" get =id div> "div-quot" get call </div>    
+      ] show 
+    ] bind 
+  ] cons t swap register-continuation ;
+  
+: write-live-anchor-script ( div-id div-quot anchor-id -- )
+  #! Write the javascript that will attach the onclick
+  #! event handler to the anchor with the 'anchor-id'. The
+  #! onclick, when clicked, will retrieve from the server
+  #! the HTML generated by the output of 'div-quot' wrapped
+  #! in a 'div' tag with the 'div-id'. That 'div' tag will
+  #! replace whatever HTML DOM object currently has that same
+  #! id.
+  <script "JavaScript" =language script> 
+    "document.getElementById('" write
+    write
+    "').onclick=liveUpdaterUri('" write
+    register-live-anchor-quot id>url write
+    "');" write
+  </script> ;
+  
+: live-anchor ( id quot text -- )
+  #! Write out the HTML for an anchor that when clicked
+  #! will replace the DOM object on the current page with
+  #! the given 'id' with the result of the output of calling
+  #! 'quot'. 
+  write-live-anchor-tag
+  write-live-anchor-script ;
+
+: write-live-search-tag ( -- id )
+  #! Write out the HTML for the input box. This
+  #! will have no actionable keydown assigned to it. Instead
+  #! a keydown is set via DHTML later to make it run a
+  #! quotation on the server. The randomly generated id
+  #! for the input box is returned.
+  <input get-random-id dup =id "text" =type input/> ;
+
+: register-live-search-quot ( div-id div-quot -- kid )
+  #! Register the 'quot' with the cont-responder so
+  #! that when it is run it will produce an HTML
+  #! fragment which is the output generated by calling 
+  #! 'quot'. That HTML fragment will be wrapped in a 
+  #! 'div' with the given id. The 'quot' is called with
+  #! a string on top of the stack. This is the input string
+  #! entered in the live search input box.
+  [
+    "div-quot" set
+    "div-id" set
+  ] make-hash [ 
+    [
+      t "disable-initial-redirect?" set
+      #! Retrieve the search query value from the POST parameters.
+      [ "s" get ] bind
+      [ 
+        #! Don't need the URL as the 'show' won't be resumed.
+        drop
+        <div "div-id" get =id div> "div-quot" get call </div>    
+      ] show 
+    ] bind 
+  ] cons t swap register-continuation ;
+
+: write-live-search-script ( div-id div-quot id-id -- )
+  #! Write the javascript that will attach the keydown handler
+  #! to the input box with the give id. Whenever a keydown is
+  #! received the 'div-quot' will be executed on the server,
+  #! with the input boxes text on top of the stack. The 
+  #! output of the quot will be an HTML fragment, it is wrapped in
+  #! a 'div' with the id 'div-id' and will 
+  #! replace whatever HTML DOM object currently has that same
+  #! id.
+  <script "JavaScript" =language script> 
+    "liveSearch('" write
+    write
+    "', '" write
+    register-live-search-quot id>url write
+    "');" write
+  </script> ;
+
+: live-search ( div-id div-quot -- )
+  #! Write an input text field. The keydown of this
+  #! text field will run 'div-quot' on the server with
+  #! the value of the text field on the stack. The output
+  #! of div-quot will replace the HTML DOM object with the
+  #! given id.
+  write-live-search-tag
+  write-live-search-script ;
diff --git a/contrib/httpd/liveUpdater.js b/contrib/httpd/liveUpdater.js
new file mode 100644 (file)
index 0000000..14c0ac8
--- /dev/null
@@ -0,0 +1 @@
+/* \r   liveUpdater.js originally written by Avi Bryant, author of\r   Seaside (http://www.beta4.com/seaside2)  \r\r   Modifed by Chris Double to add LiveUpdaterPost and use ' \r   instead of " for the id.\r*/\rfunction liveUpdaterUri(uri)\r{\r    return liveUpdater(function() { return uri; });\r}\r\rfunction liveUpdater(uriFunc)\r{\r    var request = false;\r    var regex = /<(\w+).*?id='(\w+)'.*?>((.|\n)*)<\/\1>/;\r    \r    if (window.XMLHttpRequest) {\r            request = new XMLHttpRequest();\r    }\r    \r    function update()\r    {\r        if(request && request.readyState < 4)\r            request.abort();\r            \r        if(!window.XMLHttpRequest)\r            request = new ActiveXObject("Microsoft.XMLHTTP");\r        \r        request.onreadystatechange = processRequestChange;\r        request.open("GET", uriFunc());\r        request.send(null);\r        return false;\r    }\r   \r    function processRequestChange()\r    {\r        if(request.readyState == 4)\r        {\r            var results = regex.exec(request.responseText);\r            if(results)\r                document.getElementById(results[2]).innerHTML = results[3];\r        }\r    }\r\r    return update;\r}\r\rfunction liveUpdaterPost(uriFunc)\r{\r    var request = false;\r    var regex = /<(\w+).*?id='(\w+)'.*?>((.|\n)*)<\/\1>/;\r    \r    if (window.XMLHttpRequest) {\r            request = new XMLHttpRequest();\r    }\r    \r    function update(data)\r    {\r        if(request && request.readyState < 4)\r            request.abort();\r            \r        if(!window.XMLHttpRequest)\r            request = new ActiveXObject("Microsoft.XMLHTTP");\r        \r        request.onreadystatechange = processRequestChange;\r        request.open("POST", uriFunc());\r        request.send(data);\r        return false;\r    }\r   \r    function processRequestChange()\r    {\r        if(request.readyState == 4)\r        {\r            var results = regex.exec(request.responseText);\r            if(results)\r                document.getElementById(results[2]).innerHTML = results[3];\r        }\r    }\r\r    return update;\r}\r\r\rfunction liveSearch(id, uri)\r{\r    var updater = liveUpdaterPost((function() { return uri; }));\r    var last = "";\r    var timeout = false;\r   \r    function update()\r    {\r       if (last != document.getElementById(id).value)\r            updater("s=" + escape(document.getElementById(id).value));\r    }\r        \r    function start() {\r       if (timeout)\r               window.clearTimeout(timeout);\r      \r               timeout = window.setTimeout(update, 300);\r    }\r\r    \r       if (navigator.userAgent.indexOf("Safari") > 0)\r         document.getElementById(id).addEventListener("keydown",start,false);\r    else if (navigator.product == "Gecko")\r                document.getElementById(id).addEventListener("keypress",start,false);\r    else\r         document.getElementById(id).attachEvent("onkeydown",start);\r}
\ No newline at end of file
index 96df04f9e9dcee9d31242891e0e27816fa7f67a1..a576f15087cf322053c7143f5eee5925c8a6c087 100644 (file)
@@ -6,10 +6,11 @@ USING: words kernel parser sequences io compiler ;
     "xml"
     "http-common"
     "html-tags"
-    "html"
     "responder"
     "httpd"
     "cont-responder"
+    "live-updater"
+    "html"
     "file-responder"
     "help-responder"
     "inspect-responder"