Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1"""Form.""" 

2# Standard Library 

3import re 

4 

5from chameleon.utils import Markup 

6 

7from . import compat 

8from . import field 

9from . import widget 

10 

11 

12class Form(field.Field): 

13 """ 

14 Field representing an entire form. 

15 

16 Arguments: 

17 

18 schema 

19 A :class:`colander.SchemaNode` object representing a 

20 schema to be rendered. Required. 

21 

22 action 

23 The form action (inserted into the ``action`` attribute of 

24 the form's form tag when rendered). Default: the empty string. 

25 

26 method 

27 The form method (inserted into the ``method`` attribute of 

28 the form's form tag when rendered). Default: ``POST``. 

29 

30 buttons 

31 A sequence of strings or :class:`deform.form.Button` 

32 objects representing submit buttons that will be placed at 

33 the bottom of the form. If any string is passed in the 

34 sequence, it is converted to 

35 :class:`deform.form.Button` objects. 

36 

37 formid 

38 The identifier for this form. This value will be used as the 

39 HTML ``id`` attribute of the rendered HTML form. It will also 

40 be used as the value of a hidden form input control 

41 (``__formid__``) which will be placed in this form's 

42 rendering. You should pass a string value for ``formid`` when 

43 more than one Deform form is placed into a single page and 

44 both share the same action. When one of the forms on the page 

45 is posted, your code will to be able to decide which of those 

46 forms was posted based on the differing values of 

47 ``__formid__``. By default, ``formid`` is ``deform``. 

48 

49 autocomplete 

50 Controls this form's ``autocomplete`` attribute. If ``autocomplete`` 

51 is ``None``, no autocomplete attribute will be added to the form tag. 

52 If ``autocomplete`` is a true value, an ``autocomplete='on'`` 

53 attribute will be added to the form tag. If ``autocomplete`` is a 

54 false value, an ``autocomplete='off'`` attribute will be added to the 

55 form tag. Default: ``None``. 

56 

57 focus 

58 Determines this form's input focus. 

59 

60 - If ``focus`` is ``on``, and at least one field has an ``autofocus`` 

61 schema parameter set to ``on``, the first of these fields will 

62 receive focus on page load. 

63 - If ``focus`` is ``on`` or omitted, and no field has an 

64 ``autofocus`` schema parameter set to ``on``, the first input of 

65 the first form on the page will receive focus on page load. 

66 - If ``focus`` is ``off``, no focusing will be done. 

67 

68 Default: ``on``. 

69 

70 use_ajax 

71 If this option is ``True``, the form will use AJAX (actually 

72 AJAH); when any submit button is clicked, the DOM node related 

73 to this form will be replaced with the result of the form post 

74 caused by the submission. The page will not be reloaded. This 

75 feature uses the ``jquery.form`` library ``ajaxForm`` feature 

76 as per `http://jquery.malsup.com/form/ 

77 <http://jquery.malsup.com/form/>`_. Default: ``False``. If 

78 this option is ``True``, the ``jquery.form.js`` library must be 

79 loaded in the HTML page which embeds the form. A copy of it 

80 exists in the ``static`` directory of the ``deform`` package. 

81 

82 ajax_options 

83 A *string* which must represent a JavaScript object 

84 (dictionary) of extra AJAX options as per 

85 `http://jquery.malsup.com/form/#tab3 

86 <http://jquery.malsup.com/form/#tab3>`_. For 

87 example: 

88 

89 .. code-block:: python 

90 

91 '{"success": function (rText, sText, xhr, form) {alert(sText)};}' 

92 

93 Default options exist even if ``ajax_options`` is not provided. 

94 By default, ``target`` points at the DOM node representing the 

95 form and and ``replaceTarget`` is ``true``. 

96 

97 A success handler calls the ``deform.processCallbacks`` method 

98 that will ajaxify the newly written form again. If you pass 

99 these values in ``ajax_options``, the defaults will be 

100 overridden. If you want to override the success handler, don't 

101 forget to call ``deform.processCallbacks``, otherwise 

102 subsequent form submissions won't be submitted via AJAX. 

103 

104 This option has no effect when ``use_ajax`` is False. 

105 

106 The default value of ``ajax_options`` is a string 

107 representation of the empty object. 

108 

109 The :class:`deform.Form` constructor also accepts all the keyword 

110 arguments accepted by the :class:`deform.Field` class. These 

111 keywords mean the same thing in the context of a Form as they do 

112 in the context of a Field (a Form is just another kind of Field). 

113 """ 

114 

115 css_class = "deform" # bw compat only; pass a widget to override 

116 

117 def __init__( 

118 self, 

119 schema, 

120 action="", 

121 method="POST", 

122 buttons=(), 

123 formid="deform", 

124 use_ajax=False, 

125 ajax_options="{}", 

126 autocomplete=None, 

127 focus="on", 

128 **kw 

129 ): 

130 if autocomplete: 

131 autocomplete = "on" 

132 elif autocomplete is not None: 

133 autocomplete = "off" 

134 self.autocomplete = autocomplete 

135 if str(focus).lower() == "off": 

136 self.focus = "off" 

137 else: 

138 self.focus = "on" 

139 # Use kwargs to pass flags to descendant fields; saves cluttering 

140 # the constructor 

141 kw["focus"] = self.focus 

142 field.Field.__init__(self, schema, **kw) 

143 _buttons = [] 

144 for button in buttons: 

145 if isinstance(button, compat.string_types): 

146 button = Button(button) 

147 _buttons.append(button) 

148 self.action = action 

149 self.method = method 

150 self.buttons = _buttons 

151 self.formid = formid 

152 self.use_ajax = use_ajax 

153 self.ajax_options = Markup(ajax_options.strip()) 

154 form_widget = getattr(schema, "widget", None) 

155 if form_widget is None: 

156 form_widget = widget.FormWidget() 

157 self.widget = form_widget 

158 

159 

160class Button(object): 

161 """ 

162 A class representing a form submit button. A sequence of 

163 :class:`deform.widget.Button` objects may be passed to the 

164 constructor of a :class:`deform.form.Form` class when it is 

165 created to represent the buttons renderered at the bottom of the 

166 form. 

167 

168 Arguments: 

169 

170 name 

171 The string or unicode value used as the ``name`` of the button 

172 when rendered (the ``name`` attribute of the button or input 

173 tag resulting from a form rendering). Default: ``submit``. 

174 

175 title 

176 The value used as the title of the button when rendered (shows 

177 up in the button inner text). Default: capitalization of 

178 whatever is passed as ``name``. E.g. if ``name`` is passed as 

179 ``submit``, ``title`` will be ``Submit``. 

180 

181 type 

182 The value used as the type of button. The HTML spec supports 

183 ``submit``, ``reset`` and ``button``. A special value of 

184 ``link`` will create a regular HTML link that's styled to look 

185 like a button. Default: ``submit``. 

186 

187 value 

188 The value used as the value of the button when rendered (the 

189 ``value`` attribute of the button or input tag resulting from 

190 a form rendering). If the button ``type`` is ``link`` then 

191 this setting is used as the URL for the link button. 

192 Default: same as ``name`` passed. 

193 

194 icon 

195 glyph icon name to include as part of button. (Ex. If you 

196 wanted to add the glyphicon-plus to this button then you'd pass 

197 in a value of ``plus``) Default: ``None`` (no icon is added) 

198 

199 disabled 

200 Render the button as disabled if True. 

201 

202 css_class 

203 The name of a CSS class to attach to the button. In the default 

204 form rendering, this string will replace the default button type 

205 (either ``btn-primary`` or ``btn-default``) on the the ``class`` 

206 attribute of the button. For example, if ``css_class`` was 

207 ``btn-danger`` then the resulting default class becomes 

208 ``btn btn-danger``. Default: ``None`` (use default class). 

209 

210 attributes 

211 HTML5 attributes passed in as a dictionary. This is especially 

212 useful for a Cancel button where you do not want the client to 

213 validate the form inputs, for example 

214 ``attributes={"formnovalidate": "formnovalidate"}``. 

215 """ 

216 

217 def __init__( 

218 self, 

219 name="submit", 

220 title=None, 

221 type="submit", # noQA 

222 value=None, 

223 disabled=False, 

224 css_class=None, 

225 icon=None, 

226 attributes=None, 

227 ): 

228 if attributes is None: 

229 attributes = {} 

230 if title is None: 

231 title = name.capitalize() 

232 name = re.sub(r"\s", "_", name) 

233 if value is None and type != "link": 

234 value = name 

235 self.name = name 

236 self.title = title 

237 self.type = type # noQA 

238 self.value = value 

239 self.disabled = disabled 

240 self.css_class = css_class 

241 self.icon = icon 

242 self.attributes = attributes