1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/examples/BaseHTTPRequestHandler/QuestionnaireApp.py Fri Jan 21 13:44:47 2005 +0000
1.3 @@ -0,0 +1,15 @@
1.4 +#!/usr/bin/env python
1.5 +
1.6 +from WebStack.Adapters import BaseHTTPRequestHandler
1.7 +from Questionnaire import QuestionnaireEditorResource
1.8 +import BaseHTTPServer
1.9 +
1.10 +# Special magic incantation.
1.11 +
1.12 +handler = BaseHTTPRequestHandler.HandlerFactory(QuestionnaireEditorResource())
1.13 +address = ("", 8080)
1.14 +server = BaseHTTPServer.HTTPServer(address, handler)
1.15 +print "Serving..."
1.16 +server.serve_forever()
1.17 +
1.18 +# vim: tabstop=4 expandtab shiftwidth=4
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/examples/Common/Questionnaire/Resources/question_template.xhtml Fri Jan 21 13:44:47 2005 +0000
2.3 @@ -0,0 +1,77 @@
2.4 +<?xml version="1.0" encoding="iso-8859-1"?>
2.5 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN"
2.6 + "http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">
2.7 +<html xmlns="http://www.w3.org/1999/xhtml"
2.8 + xmlns:template="http://www.boddie.org.uk/ns/xmltools/template">
2.9 +<head>
2.10 + <title>Questionnaire Editor</title>
2.11 + <meta name="generator" content="amaya 8.1a, see http://www.w3.org/Amaya/" />
2.12 + <link xmlns:xlink="http://www.w3.org/1999/xlink" href="styles.css"
2.13 + rel="stylesheet" type="text/css" />
2.14 +</head>
2.15 +
2.16 +<body template:element="questionnaire">
2.17 +<h1>Questionnaire Editor</h1>
2.18 +
2.19 +<p>Enter questions and possible responses below.</p>
2.20 +
2.21 +<form method="get" action="">
2.22 +
2.23 + <table class="questionnaire">
2.24 + <tbody template:element="question">
2.25 + <tr>
2.26 + <th class="question">Question</th>
2.27 + <td class="question" template:attribute="question-text"><textarea cols="40" rows="4"
2.28 + name="{template:field-name()}" template:value="$this-value">Question</textarea></td>
2.29 + <td class="question-options">
2.30 + <input type="submit" value="Remove question" name="remove-question={template:this-position()}"
2.31 + /></td>
2.32 + </tr>
2.33 + <tr>
2.34 + <th class="response">Response</th>
2.35 + <td class="response" template:attribute="question-type"><input type="radio"
2.36 + name="{template:field-name()}" value="text" template:expr-attr="checked"
2.37 + template:expr="$this-value = 'text'" /> Text</td>
2.38 + <td></td>
2.39 + </tr>
2.40 + <tr>
2.41 + <td class="response"></td>
2.42 + <td class="response" template:attribute="response-text"><input type="text" size="40"
2.43 + name="{template:field-name()}" value="{$this-value}" /></td>
2.44 + <td></td>
2.45 + </tr>
2.46 + <tr>
2.47 + <td class="response"></td>
2.48 + <td class="response" template:attribute="question-type"><input type="radio"
2.49 + name="{template:field-name()}" value="choice" template:expr-attr="checked"
2.50 + template:expr="$this-value = 'choice'" /> Multiple choice</td>
2.51 + <td></td>
2.52 + </tr>
2.53 + <tr template:element="choice">
2.54 + <td class="response"></td>
2.55 + <td class="choice" template:attribute="response-choice"><input type="text" size="40"
2.56 + name="{template:field-name()}" value="{$this-value}" /></td>
2.57 + <td class="choice-options">
2.58 + <input type="submit" value="Remove choice" name="remove-choice={template:this-position()}"
2.59 + /></td>
2.60 + </tr>
2.61 + <tr>
2.62 + <td class="response"></td>
2.63 + <td class="response"></td>
2.64 + <td class="response">
2.65 + <input type="submit" value="Add choice" name="add-choice={template:this-position()}"
2.66 + /></td>
2.67 + </tr>
2.68 + </tbody>
2.69 + </table>
2.70 +
2.71 + <p>
2.72 + <input type="submit" value="Add question" name="add-question" /> to make
2.73 + the questionnaire longer.</p>
2.74 +
2.75 + <p>
2.76 + <input type="submit" value="Finish" name="finish" /> when all the questions
2.77 + and responses are ready.</p>
2.78 +</form>
2.79 +</body>
2.80 +</html>
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/examples/Common/Questionnaire/Resources/question_template_original.xhtml Fri Jan 21 13:44:47 2005 +0000
3.3 @@ -0,0 +1,74 @@
3.4 +<?xml version="1.0" encoding="iso-8859-1"?>
3.5 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN"
3.6 + "http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">
3.7 +<html xmlns="http://www.w3.org/1999/xhtml">
3.8 +<head>
3.9 + <title>Questionnaire Editor</title>
3.10 + <meta name="generator" content="amaya 8.1a, see http://www.w3.org/Amaya/" />
3.11 + <link xmlns:xlink="http://www.w3.org/1999/xlink" href="styles.css"
3.12 + rel="stylesheet" type="text/css" />
3.13 +</head>
3.14 +
3.15 +<body>
3.16 +<h1>Questionnaire Editor</h1>
3.17 +
3.18 +<p>Enter questions and possible responses below.</p>
3.19 +
3.20 +<form method="get" action="">
3.21 +
3.22 + <table class="questionnaire">
3.23 + <tbody>
3.24 + <tr>
3.25 + <th class="question">Question</th>
3.26 + <td class="question"><textarea cols="40" rows="4"
3.27 + name="question-text">Question </textarea></td>
3.28 + <td class="question-options">
3.29 + <input type="submit" value="Remove question" name="remove-question"
3.30 + /></td>
3.31 + </tr>
3.32 + <tr>
3.33 + <th class="response">Response</th>
3.34 + <td class="response"><input type="radio" name="question-type"
3.35 + value="text" /> Text</td>
3.36 + <td></td>
3.37 + </tr>
3.38 + <tr>
3.39 + <td class="response"></td>
3.40 + <td class="response"><input type="text" size="40"
3.41 + name="response-text" /></td>
3.42 + <td></td>
3.43 + </tr>
3.44 + <tr>
3.45 + <td class="response"></td>
3.46 + <td class="response"><input type="radio" name="question-type"
3.47 + value="choice" /> Multiple choice</td>
3.48 + <td></td>
3.49 + </tr>
3.50 + <tr>
3.51 + <td class="response"></td>
3.52 + <td class="choice"><input type="text" size="40"
3.53 + name="response-choice" /></td>
3.54 + <td class="choice-options">
3.55 + <input type="submit" value="Remove choice" name="remove-choice"
3.56 + /></td>
3.57 + </tr>
3.58 + <tr>
3.59 + <td class="response"></td>
3.60 + <td class="response"></td>
3.61 + <td class="response">
3.62 + <input type="submit" value="Add choice" name="add-choice"
3.63 + /></td>
3.64 + </tr>
3.65 + </tbody>
3.66 + </table>
3.67 +
3.68 + <p>
3.69 + <input type="submit" value="Add question" name="add-question" /> to make
3.70 + the questionnaire longer.</p>
3.71 +
3.72 + <p>
3.73 + <input type="submit" value="Finish" name="finish" /> when all the questions
3.74 + and responses are ready.</p>
3.75 +</form>
3.76 +</body>
3.77 +</html>
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/examples/Common/Questionnaire/Resources/styles.css Fri Jan 21 13:44:47 2005 +0000
4.3 @@ -0,0 +1,22 @@
4.4 +table.questionnaire td, table.questionnaire th {
4.5 + padding: 5px;
4.6 + margin: 0px;
4.7 +}
4.8 +
4.9 +.question, .question-options {
4.10 + background-color: #ffffff;
4.11 + color: #000000;
4.12 + vertical-align: top;
4.13 +}
4.14 +
4.15 +.response, .response-options {
4.16 + background-color: #eeeeee;
4.17 + color: #000000;
4.18 + vertical-align: top;
4.19 +}
4.20 +
4.21 +.choice, .choice-options {
4.22 + background-color: #dddddd;
4.23 + color: #000000;
4.24 + vertical-align: top;
4.25 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/examples/Common/Questionnaire/__init__.py Fri Jan 21 13:44:47 2005 +0000
5.3 @@ -0,0 +1,128 @@
5.4 +#!/usr/bin/env python
5.5 +
5.6 +"A WebStack questionnaire application."
5.7 +
5.8 +import WebStack.Generic
5.9 +import XSLForms.Fields
5.10 +import XSLForms.Output
5.11 +import XSLOutput
5.12 +import libxml2dom
5.13 +import os
5.14 +
5.15 +# NOTE: Move these functions into a common utility library.
5.16 +
5.17 +def add_elements(positions, element_name, element_parent_name=None):
5.18 + if not positions:
5.19 + return
5.20 + for position in positions:
5.21 + if element_parent_name:
5.22 + parent_elements = position.xpath(element_parent_name)
5.23 + if not parent_elements:
5.24 + parent_element = position.ownerDocument.createElementNS(None, element_parent_name)
5.25 + position.appendChild(parent_element)
5.26 + else:
5.27 + parent_element = parent_elements[0]
5.28 + else:
5.29 + parent_element = position
5.30 + parent_element.appendChild(position.ownerDocument.createElementNS(None, element_name))
5.31 +
5.32 +def remove_elements(positions):
5.33 + if not positions:
5.34 + return
5.35 + for position in positions:
5.36 + position.parentNode.removeChild(position)
5.37 +
5.38 +# NOTE: This is so much like ConfiguratorResource that some common parts could
5.39 +# NOTE: be extracted.
5.40 +
5.41 +class QuestionnaireEditorResource:
5.42 +
5.43 + "A resource providing a questionnaire editor."
5.44 +
5.45 + resource_dir = os.path.join(os.path.split(__file__)[0], "Resources")
5.46 + encoding = "utf-8"
5.47 +
5.48 + def respond(self, trans):
5.49 +
5.50 + # Produce stylesheet.
5.51 +
5.52 + if trans.get_path_info().split("/")[-1] == "styles.css":
5.53 + trans.set_content_type(WebStack.Generic.ContentType("text/css", self.encoding))
5.54 + out = trans.get_response_stream()
5.55 + f = open(os.path.join(self.resource_dir, "styles.css"), "rb")
5.56 + out.write(f.read())
5.57 + f.close()
5.58 + raise WebStack.Generic.EndOfResponse
5.59 +
5.60 + global XSLForms # NOTE: Strangely required to avoid UnboundLocalError!
5.61 + method = trans.get_request_method()
5.62 +
5.63 + # Only obtain field information according to the stated method.
5.64 +
5.65 + if method == "GET":
5.66 + fields = XSLForms.Fields.Fields(encoding="iso-8859-1", values_are_lists=1)
5.67 + parameters = trans.get_fields_from_path()
5.68 + documents = fields.make_documents(parameters.items())
5.69 + elif method == "POST":
5.70 + fields = XSLForms.Fields.Fields(encoding=self.encoding, values_are_lists=1)
5.71 + parameters = trans.get_fields_from_body(self.encoding)
5.72 + documents = fields.make_documents(parameters.items())
5.73 + else:
5.74 + trans.set_response_code(405)
5.75 + raise WebStack.Generic.EndOfResponse
5.76 +
5.77 + # Ensure the presence of a document.
5.78 +
5.79 + if documents.has_key("questionnaire"):
5.80 + questionnaire = documents["questionnaire"]
5.81 + else:
5.82 + questionnaire = fields.new_instance("questionnaire")
5.83 +
5.84 + # Add and remove elements according to the selectors found.
5.85 +
5.86 + selectors = fields.get_selectors(parameters.items(), documents)
5.87 + remove_elements(selectors.get("remove-question"))
5.88 + add_elements(selectors.get("add-choice"), "choice")
5.89 + remove_elements(selectors.get("remove-choice"))
5.90 +
5.91 + # Add questions using the normal request parameter.
5.92 +
5.93 + if parameters.has_key("add-question"):
5.94 + new_question = questionnaire.ownerDocument.createElementNS(None, "question")
5.95 + questionnaire.xpath("questionnaire")[0].appendChild(new_question)
5.96 +
5.97 + # Send a response according to certain parameters.
5.98 + # When exported, an XML version of the data is returned.
5.99 +
5.100 + if parameters.has_key("export"):
5.101 + trans.set_content_type(WebStack.Generic.ContentType("text/xml", self.encoding))
5.102 + libxml2dom.toStream(questionnaire, trans.get_response_stream(), trans.get_response_stream_encoding())
5.103 +
5.104 + # When not exported, the data is transformed to produce a normal Web
5.105 + # page.
5.106 +
5.107 + else:
5.108 +
5.109 + # Start the response.
5.110 +
5.111 + trans.set_content_type(WebStack.Generic.ContentType("text/html", self.encoding))
5.112 +
5.113 + # Ensure that an output stylesheet exists.
5.114 +
5.115 + trans_xsl = os.path.join(self.resource_dir, "question_output.xsl")
5.116 + template_xml = os.path.join(self.resource_dir, "question_template.xhtml")
5.117 +
5.118 + if not os.path.exists(trans_xsl) or \
5.119 + os.path.getmtime(trans_xsl) < os.path.getmtime(template_xml):
5.120 +
5.121 + import XSLForms.Prepare
5.122 + template_xml = os.path.join(self.resource_dir, "question_template.xhtml")
5.123 + XSLForms.Prepare.make_stylesheet(template_xml, trans_xsl)
5.124 +
5.125 + # Complete the response.
5.126 +
5.127 + proc = XSLOutput.Processor([trans_xsl])
5.128 + proc.send_output(trans.get_response_stream(), trans.get_response_stream_encoding(),
5.129 + questionnaire)
5.130 +
5.131 +# vim: tabstop=4 expandtab shiftwidth=4