1
#################################################################################
2
# Example of using patterns to change the appearance of a webform.
4
#from twisted.application import internet, service
5
#from twisted.web import static
7
from zope.interface import implements
11
from nevow import loaders
12
from nevow import tags as T
14
from formless import annotate
15
from formless import webform
18
#################################################################################
19
# This beasty defines how I want the form to look. It's a table (eek!).
20
# webform looks for patterns to use when rendering parts of the form and fills
21
# slots with key information.
24
# freeform-form -- the form itself, mostly just the structure
25
# argument -- the pattern to use for arguments when nothing better
27
# argument!!fo -- the pattern to use for the 'fo' argument
29
# Inside the patterns the following slots are filled:
31
# form-action -- action attribute, where the form will be posted
32
# form-id -- id of the form
33
# form-name -- name of the form
34
# form-label -- form label, extracted from the docstring
35
# form-description -- description, also extracted from the docstring
36
# form-error -- "global" error
37
# form-arguments -- insertion point for the arguments' HTML
40
# input -- the form element (input, textarea, etc)
41
# error -- error message (if any)
42
# description -- description of argument
44
# Note that you do not have to provide slots for all of the above. For
45
# instance, you may not want to display the descriptions.
47
# Chances are that this block of text would be in a disk template or
48
# perhaps defined using stan in a taglib module.
51
FORM_LAYOUT = loaders.xmlstr(
52
"""<?xml version="1.0"?>
53
<form xmlns:n="http://nevow.com/ns/nevow/0.1" n:pattern="freeform-form">
55
<!-- Replace/fill the form attributes -->
56
<n:attr name="action"><n:slot name="form-action"/></n:attr>
57
<n:attr name="id"><n:slot name="form-id"/></n:attr>
58
<n:attr name="name"><n:slot name="form-name"/></n:attr>
60
<!-- General form information -->
61
<p><strong><n:slot name="form-label"/></strong></p>
62
<p><em><n:slot name="form-description"/></em></p>
63
<p><strong><em><n:slot name="form-error"/></em></strong></p>
65
<!-- Start of the form layout table -->
66
<table style="background: #eee; border: 1px solid #bbb; padding: 1em;" >
67
<!-- Mark location arguments will be added -->
68
<n:slot name="form-arguments"/>
69
<!-- General argument layout pattern -->
70
<n:invisible n:pattern="argument" n:render="remove">
72
<th><n:slot name="label"/>:</th>
73
<td><n:slot name="input"/><span class="freeform-error"><n:slot name="error"/></span></td>
77
<td><n:slot name="description"/></td>
80
<!-- Argument layout, just for fum -->
81
<n:invisible n:pattern="argument!!fo" n:render="remove">
83
<th><n:slot name="label"/>:</th>
85
<textarea cols="40" rows="5"><n:attr name="id"><n:slot name="id"/></n:attr><n:attr name="name"><n:slot name="name"/></n:attr><n:slot name="value"/></textarea>
86
<span class="freeform-error"><n:slot name="error"/></span></td>
90
<td><n:slot name="description"/></td>
96
<n:slot name="form-button"/>
104
#################################################################################
105
# ISomething and Page are just something to test the form rendering on.
107
class ISomething(annotate.TypedInterface):
110
ctx = annotate.Context(),
111
fee = annotate.String(required=True, description="Wee!"),
112
fi = annotate.Integer(description="Tra-la-la"),
113
fo = annotate.Text(),
114
fum = annotate.String(),
116
"""Do Something Really Exciting
118
Normally you would put a useful description of the interface here but,
119
since the inteface is useless anyway, I cannot think of anything
120
useful to say about it. Although ... did I mention it is useless?"""
121
doSomething = annotate.autocallable(doSomething)
124
class Root(rend.Page):
125
"""Render a custom and normal form for an ISomething.
127
implements(ISomething)
130
child_webform_css = webform.defaultCSS
132
def render_normalForm(self, ctx, data):
133
return webform.renderForms()
135
def render_customForm(self, ctx, data):
136
return webform.renderForms()[FORM_LAYOUT]
138
def doSomething(self, ctx, **kwargs):
139
print '***** doSomething called with:', kwargs
141
docFactory = loaders.stan(
144
T.title['Example :: Custom Form Layout'],
145
T.link(rel='stylesheet', type='text/css', href=url.here.child("webform_css")),
157
#application = service.Application('hellostan')
158
#webServer = internet.TCPServer(8080, appserver.NevowSite(Root()))
159
#webServer.setServiceParent(application)