From ab2b06b07112e9692c632371f39f215ea66d7d08 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 24 Jan 2006 01:05:39 +0000 Subject: [PATCH] more html stream work --- contrib/httpd/default-responders.factor | 7 +- contrib/httpd/help-responder.factor | 12 +- contrib/httpd/html.factor | 41 ++++-- contrib/httpd/http-common.factor | 2 +- contrib/httpd/inspect-responder.factor | 2 +- contrib/httpd/live-updater.factor | 158 ++++++++++++++++++++++++ contrib/httpd/liveUpdater.js | 1 + contrib/httpd/load.factor | 3 +- 8 files changed, 206 insertions(+), 20 deletions(-) create mode 100644 contrib/httpd/live-updater.factor create mode 100644 contrib/httpd/liveUpdater.js diff --git a/contrib/httpd/default-responders.factor b/contrib/httpd/default-responders.factor index 705bccff4e..40d87c96a1 100644 --- a/contrib/httpd/default-responders.factor +++ b/contrib/httpd/default-responders.factor @@ -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 diff --git a/contrib/httpd/help-responder.factor b/contrib/httpd/help-responder.factor index 1430c30458..4f5aff21fe 100644 --- a/contrib/httpd/help-responder.factor +++ b/contrib/httpd/help-responder.factor @@ -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 ; diff --git a/contrib/httpd/html.factor b/contrib/httpd/html.factor index a177d92ccc..9a279c13b8 100644 --- a/contrib/httpd/html.factor +++ b/contrib/httpd/html.factor @@ -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 -- ) + + + + + + + + +
+ "replaceme" swap [ + [ with-html-stream ] show-final + ] curry "+" live-anchor + + call +
+
; + +: outliner-tag ( style quot -- ) + outline pick hash [ html-outliner ] [ call ] if* ; + M: html-stream with-nested-stream ( quot style stream -- ) [ [ [ - stdio get swap with-stream* - ] div-tag - ] object-link-tag + [ + stdio get swap with-stream* + ] div-tag + ] object-link-tag + ] outliner-tag ] with-stream* ; M: html-stream stream-terpri [
] with-stream* ; @@ -176,6 +200,7 @@ M: html-stream stream-terpri [
] with-stream* ; write default-css + include-live-updater-js

write

diff --git a/contrib/httpd/http-common.factor b/contrib/httpd/http-common.factor index dff593c799..1d20e96795 100644 --- a/contrib/httpd/http-common.factor +++ b/contrib/httpd/http-common.factor @@ -67,7 +67,7 @@ sequences strings ; [ swap % dup hash-empty? [ "?" % - hash>alist + dup hash>alist [ [ url-encode ] map "=" join ] map "&" join % ] unless drop ] "" make ; diff --git a/contrib/httpd/inspect-responder.factor b/contrib/httpd/inspect-responder.factor index 94114d038d..80b826283c 100644 --- a/contrib/httpd/inspect-responder.factor +++ b/contrib/httpd/inspect-responder.factor @@ -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 index 0000000000..eae2a24bdb --- /dev/null +++ b/contrib/httpd/live-updater.factor @@ -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" 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. + ; + +: 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. + + swap write + ; + +: 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-quot" get call
+ ] 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. + ; + +: 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. + ; + +: 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-quot" get call
+ ] 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. + ; + +: 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 index 0000000000..14c0ac8628 --- /dev/null +++ b/contrib/httpd/liveUpdater.js @@ -0,0 +1 @@ +/* liveUpdater.js originally written by Avi Bryant, author of Seaside (http://www.beta4.com/seaside2) Modifed by Chris Double to add LiveUpdaterPost and use ' instead of " for the id. */ function liveUpdaterUri(uri) { return liveUpdater(function() { return uri; }); } function liveUpdater(uriFunc) { var request = false; var regex = /<(\w+).*?id='(\w+)'.*?>((.|\n)*)<\/\1>/; if (window.XMLHttpRequest) { request = new XMLHttpRequest(); } function update() { if(request && request.readyState < 4) request.abort(); if(!window.XMLHttpRequest) request = new ActiveXObject("Microsoft.XMLHTTP"); request.onreadystatechange = processRequestChange; request.open("GET", uriFunc()); request.send(null); return false; } function processRequestChange() { if(request.readyState == 4) { var results = regex.exec(request.responseText); if(results) document.getElementById(results[2]).innerHTML = results[3]; } } return update; } function liveUpdaterPost(uriFunc) { var request = false; var regex = /<(\w+).*?id='(\w+)'.*?>((.|\n)*)<\/\1>/; if (window.XMLHttpRequest) { request = new XMLHttpRequest(); } function update(data) { if(request && request.readyState < 4) request.abort(); if(!window.XMLHttpRequest) request = new ActiveXObject("Microsoft.XMLHTTP"); request.onreadystatechange = processRequestChange; request.open("POST", uriFunc()); request.send(data); return false; } function processRequestChange() { if(request.readyState == 4) { var results = regex.exec(request.responseText); if(results) document.getElementById(results[2]).innerHTML = results[3]; } } return update; } function liveSearch(id, uri) { var updater = liveUpdaterPost((function() { return uri; })); var last = ""; var timeout = false; function update() { if (last != document.getElementById(id).value) updater("s=" + escape(document.getElementById(id).value)); } function start() { if (timeout) window.clearTimeout(timeout); timeout = window.setTimeout(update, 300); } if (navigator.userAgent.indexOf("Safari") > 0) document.getElementById(id).addEventListener("keydown",start,false); else if (navigator.product == "Gecko") document.getElementById(id).addEventListener("keypress",start,false); else document.getElementById(id).attachEvent("onkeydown",start); } \ No newline at end of file diff --git a/contrib/httpd/load.factor b/contrib/httpd/load.factor index 96df04f9e9..a576f15087 100644 --- a/contrib/httpd/load.factor +++ b/contrib/httpd/load.factor @@ -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"