Wiki source code of Forms Standards: Vertical Layout
Last modified by Lucas Charpentier (Sereza7) on 2024/03/26
Show last authors
author | version | line-number | content |
---|---|---|---|
1 | {{box cssClass="floatinginfobox" title="**Content**"}} | ||
2 | {{toc/}} | ||
3 | {{/box}} | ||
4 | |||
5 | XWiki Forms (##xform## / ##xformInline##) are general usage purpose CSS classes, that need to be used in order to have a consistent view of forms across XWiki. | ||
6 | |||
7 | * Forms Layout Type: | ||
8 | ** **Vertical Layout** (##xform##): uses a dl-dt-dd structure. | ||
9 | ** [[Inline Layout>>xwiki:Documentation.DevGuide.FrontendResources.InlineForms]] (##xformInline##). | ||
10 | |||
11 | This classes implementation has been voted at [[~[Vote~] ~[Standards~] Forms: Usage + Documentation page to XWiki.org>>http://markmail.org/thread/5zrnncdukmc7wmer]] and implemented in [[XSCOLIBRI-260>>https://jira.xwiki.org/browse/XSCOLIBRI-260]]. | ||
12 | |||
13 | = Usage = | ||
14 | |||
15 | * Obs: the CSS classes have as a parent the ##.xform## class. This is supposed to be used on the form tag, but if the styling is done inside dynamically-generated structures, it can be used on other elements, like divs, as long as the element remains the parent for the other form components. For instance, a common use case is when you design a form that is to be used in inline edit mode, you have to wrap the form content in a div element and use ##class='xform'## on the div instead of the form. This is needed because in inline edit mode the entire page content is put inside a form element to which we don't have access as it is generated in a velocity template, and generating a form element inside the page content will produce invalid HTML since nested form elements are not allowed (the inner form element will probably be removed either by the rendering engine or by the browser). | ||
16 | |||
17 | (% summary="Table containg classes for different form components" %) | ||
18 | |=(% rowspan="2" %) Tag |=(% rowspan="2" %)Type |=(% rowspan="2" %)Size |=(% colspan="3" %)Classes|=(% rowspan="2" %)Usage | ||
19 | |=Required     |=Optional      |=Container | ||
20 | |form    | | |##.xform##    |##.half##, ##.third##| |Container for the form controls | ||
21 | |label   | | | | |dt                 |Descriptive label for the control | ||
22 | |span    | | |##.xRequired## | |dt label           |Displays the required status of a control | ||
23 | |a       | | |##.xHelp##    | |dt                 |Attach a link to external documentation about a control | ||
24 | |span    | | |##.xHint##    | |dt                 |Attach hint information to a control | ||
25 | |span    | | |##.xErrorMsg## | |dt                 |Alert or error information for the control | ||
26 | |input   | hidden  | | | | | | ||
27 | |(% rowspan="2" %)input |(% rowspan="2" %)((( | ||
28 | text | ||
29 | Since 12.10: color, date, datetime-local, email, number, search, tel, time | ||
30 | )))|(% rowspan="2" %)size=60 |(% rowspan="2" %) |##.disabled##  |dd                 | | ||
31 | |##.xErrorField##|dd                 |Alert or error triggering control | ||
32 | |(% rowspan="2" %)input |(% rowspan="2" %)password |(% rowspan="2" %)size=60 |(% rowspan="2" %) |##.disabled##  |dd                 | | ||
33 | |##.xErrorField##|dd                 |Alert or error triggering control | ||
34 | |input   | radio   | | | | | | ||
35 | |input   | checkbox | | | | | | ||
36 | |input   | submit  | |##.button##   |##.secondary## ##.disabled##|span##.buttonwrapper##|Button controls | ||
37 | |input   | button  | |##.button##   |##.secondary## ##.disabled##|span##.buttonwrapper##|Button controls | ||
38 | |a       | | |##.button##   |##.secondary## ##.disabled##|span##.buttonwrapper##|Button controls | ||
39 | |(% rowspan="2" %)textarea |(% rowspan="2" %) |(% rowspan="2" %)rows=7 cols=45 |(% rowspan="2" %) | | | | ||
40 | |##.xErrorField##|dd                 |Alert or error triggering control | ||
41 | |select  | |size=1 | | | | | ||
42 | |fieldset | | | | | | | ||
43 | |legend  | | | | | | | ||
44 | |||
45 | = Components = | ||
46 | |||
47 | == 1. Labels == | ||
48 | |||
49 | * This element provides a descriptive label for the containing form control. | ||
50 | * **Obs.1**: Use uppercase ('UPPERCASE') bold fonts for input field labels [ title case ('Title Case') in the translation keys] | ||
51 | * **Obs.2**: Do __not__ use colons(:) at the end of labels | ||
52 | |||
53 | === [preview] === | ||
54 | |||
55 | [[image:label.png]] | ||
56 | |||
57 | === [html] === | ||
58 | |||
59 | {{code language="html"}} | ||
60 | <form action="." class="xform" method="post" name="form_name1"> | ||
61 | <dl> | ||
62 | <dt> | ||
63 | <label for="input_id1">Label</label> | ||
64 | </dt> | ||
65 | <dd> | ||
66 | <input id="input_id1" name="input_name1" type="text" size="60" value=""/> | ||
67 | </dd> | ||
68 | </dl> | ||
69 | <p> | ||
70 | <span class="buttonwrapper"> | ||
71 | <input class="button" type="submit" value="Button"/> | ||
72 | </span> | ||
73 | </p> | ||
74 | </form> | ||
75 | {{/code}} | ||
76 | |||
77 | === [demo] === | ||
78 | |||
79 | {{html clean="false"}} | ||
80 | <form action="." class="xform" method="post" name="form_name9"> | ||
81 | <dl> | ||
82 | <dt> | ||
83 | <label for="input_id1">Label</label> | ||
84 | </dt> | ||
85 | <dd> | ||
86 | <input id="input_id1" name="input_name1" type="text" size="60" value=""/> | ||
87 | </dd> | ||
88 | </dl> | ||
89 | <p> | ||
90 | <span class="buttonwrapper"> | ||
91 | <input class="button" type="submit" value="Button"/> | ||
92 | </span> | ||
93 | </p> | ||
94 | </form> | ||
95 | {{/html}} | ||
96 | |||
97 | === [css] === | ||
98 | |||
99 | {{code language="css"}} | ||
100 | .xform input[type="text" size="60"], .xform input[type="password"], | ||
101 | .xform select, .xform textarea{ | ||
102 | width: 99%; | ||
103 | } | ||
104 | |||
105 | .xform dt { | ||
106 | margin-top: 1.2em; | ||
107 | } | ||
108 | |||
109 | .xform label { | ||
110 | color: $theme.textColor; | ||
111 | display: block; | ||
112 | font-size: .85em; | ||
113 | font-weight: 700; | ||
114 | margin-bottom: .3em; | ||
115 | text-transform: uppercase; | ||
116 | } | ||
117 | {{/code}} | ||
118 | |||
119 | == 2. Required == | ||
120 | |||
121 | * This element displays the required status of a form control. | ||
122 | |||
123 | === [preview] === | ||
124 | |||
125 | [[image:required.png]] | ||
126 | |||
127 | === [html] === | ||
128 | |||
129 | {{code language="html"}} | ||
130 | <label for="input_id2">Label <span class="xRequired">(Required)</span></label> | ||
131 | {{/code}} | ||
132 | |||
133 | === [demo] === | ||
134 | |||
135 | {{html clean="false"}} | ||
136 | <form action="." class="xform" method="post" name="form_name2"> | ||
137 | <dl> | ||
138 | <dt> | ||
139 | <label for="input_id2">Label <span class="xRequired">(Required)</span></label> | ||
140 | </dt> | ||
141 | <dd> | ||
142 | <input id="input_id2" name="input_name2" type="text" size="60" value=""/> | ||
143 | </dd> | ||
144 | </dl> | ||
145 | <p> | ||
146 | <span class="buttonwrapper"> | ||
147 | <input class="button" type="submit" value="Button"/> | ||
148 | </span> | ||
149 | </p> | ||
150 | </form> | ||
151 | {{/html}} | ||
152 | |||
153 | === [css] === | ||
154 | |||
155 | {{code language="css"}} | ||
156 | .xform .xRequired { | ||
157 | color: $theme.textSecondaryColor; | ||
158 | font-size: .9em; | ||
159 | font-style: italic; | ||
160 | font-weight: normal; | ||
161 | margin-left: 1ex; | ||
162 | text-transform: none; | ||
163 | } | ||
164 | {{/code}} | ||
165 | |||
166 | === [translation] === | ||
167 | |||
168 | core.validation.required=(Required) | ||
169 | |||
170 | == 3. Help == | ||
171 | |||
172 | * This element displays an icon pointing to some external documentation about a specific field. | ||
173 | |||
174 | === [preview] === | ||
175 | |||
176 | [[image:help.png]] | ||
177 | |||
178 | === [html] === | ||
179 | |||
180 | {{code language="html"}} | ||
181 | <dt> | ||
182 | <label for="input_id3">Label</label> | ||
183 | <a class="xHelp" title="Documentation" href="#">Documentation</a> | ||
184 | </dt> | ||
185 | {{/code}} | ||
186 | |||
187 | === [demo] === | ||
188 | |||
189 | {{html clean="false"}} | ||
190 | <form action="." class="xform" method="post" name="form_name"> | ||
191 | <dl> | ||
192 | <dt> | ||
193 | <label for="input_id3a">Label</label> | ||
194 | <a class="xHelp" title="Documentation" href="#">Documentation</a> | ||
195 | </dt> | ||
196 | <dd> | ||
197 | <input id="input_id3a" name="input_name1" type="text" size="61" value=""/> | ||
198 | </dd> | ||
199 | </dl> | ||
200 | <p> | ||
201 | <span class="buttonwrapper"> | ||
202 | <input class="button" type="submit" value="Button"/> | ||
203 | </span> | ||
204 | </p> | ||
205 | </form> | ||
206 | {{/html}} | ||
207 | |||
208 | === [css] === | ||
209 | |||
210 | {{code language="css"}} | ||
211 | .xform .xHelp { | ||
212 | background: transparent url("$xwiki.getSkinFile('icons/silk/information.gif')") left top no-repeat; | ||
213 | float: right; | ||
214 | height: 16px; | ||
215 | line-height: 250px; | ||
216 | margin-right: 1px; | ||
217 | margin-top: -20px; | ||
218 | overflow: hidden; | ||
219 | text-align: left !important; | ||
220 | width: 16px; | ||
221 | } | ||
222 | {{/code}} | ||
223 | |||
224 | == 4. Hint == | ||
225 | |||
226 | * This element provides a convenient way to attach hint information to a form control. | ||
227 | |||
228 | === [preview] === | ||
229 | |||
230 | [[image:hint.png]] | ||
231 | |||
232 | === [html] === | ||
233 | |||
234 | {{code language="html"}} | ||
235 | <dt> | ||
236 | <label for="input_id3">Label</label> | ||
237 | <span class="xHint">Hint</span> | ||
238 | </dt> | ||
239 | {{/code}} | ||
240 | |||
241 | === [demo] === | ||
242 | |||
243 | {{html clean="false"}} | ||
244 | <form action="." class="xform" method="post" name="form_name3"> | ||
245 | <dl> | ||
246 | <dt> | ||
247 | <label for="input_id3">Label</label> | ||
248 | <span class="xHint">Hint</span> | ||
249 | </dt> | ||
250 | <dd> | ||
251 | <input id="input_id3" name="input_name3" type="text" size="60" value=""/> | ||
252 | </dd> | ||
253 | </dl> | ||
254 | <p> | ||
255 | <span class="buttonwrapper"> | ||
256 | <input class="button" type="submit" value="Button"/> | ||
257 | </span> | ||
258 | </p> | ||
259 | </form> | ||
260 | {{/html}} | ||
261 | |||
262 | === [css] === | ||
263 | |||
264 | {{code language="css"}} | ||
265 | .xform .xHint { | ||
266 | color: $theme.textSecondaryColor; | ||
267 | display: block; | ||
268 | font-size: .8em; | ||
269 | font-style: normal; | ||
270 | font-weight: 400; | ||
271 | margin-bottom: .3em; | ||
272 | } | ||
273 | {{/code}} | ||
274 | |||
275 | == 5. Error == | ||
276 | |||
277 | * This element provides a convenient way to attach alert or error information to a form control. | ||
278 | |||
279 | === [preview] === | ||
280 | |||
281 | [[image:error.png]] | ||
282 | |||
283 | === [html] === | ||
284 | |||
285 | {{code language="html"}} | ||
286 | <dl> | ||
287 | <dt> | ||
288 | <label for="input_id5">Label</label> | ||
289 | <span class="xHint">Hint</span> | ||
290 | <span class="xErrorMsg">Error</span> | ||
291 | </dt> | ||
292 | <dd> | ||
293 | <input class="xErrorField" id="input_id5" name="input_name5" type="text" size="60" value=""/> | ||
294 | </dd> | ||
295 | </dl> | ||
296 | {{/code}} | ||
297 | |||
298 | === [demo] === | ||
299 | |||
300 | {{html clean="false"}} | ||
301 | <form action="." class="xform" method="post" name="form_name5"> | ||
302 | <dl> | ||
303 | <dt> | ||
304 | <label for="input_id5">Label</label> | ||
305 | <span class="xHint">Hint</span> | ||
306 | <span class="xErrorMsg">Error</span> | ||
307 | </dt> | ||
308 | <dd> | ||
309 | <input class="xErrorField" id="input_id5" name="input_name5" type="text" size="60" value=""/> | ||
310 | </dd> | ||
311 | </dl> | ||
312 | <p> | ||
313 | <span class="buttonwrapper"> | ||
314 | <input class="button" type="submit" value="Button"/> | ||
315 | </span> | ||
316 | </p> | ||
317 | </form> | ||
318 | {{/html}} | ||
319 | |||
320 | === [css] === | ||
321 | |||
322 | {{code language="css"}} | ||
323 | .xform .xErrorMsg { | ||
324 | color: #CC3333; | ||
325 | display: block; | ||
326 | font-size: .8em; | ||
327 | font-weight: normal; | ||
328 | margin-bottom: .3em; | ||
329 | } | ||
330 | |||
331 | .xform .xErrorField { | ||
332 | border: 1px solid #CC3333; | ||
333 | } | ||
334 | {{/code}} | ||
335 | |||
336 | == 6. Buttons == | ||
337 | |||
338 | * Group multiple buttons in a ##.buttons## div | ||
339 | |||
340 | === [preview] === | ||
341 | |||
342 | [[image:buttons.png]] | ||
343 | |||
344 | === [html] === | ||
345 | |||
346 | * Use an additional ##.buttonwrapper## class span container to surround button elements | ||
347 | |||
348 | {{code language="html"}} | ||
349 | <div class="buttons"> | ||
350 | <span class="buttonwrapper"> | ||
351 | <input class="button" type="submit" value="Button"/> | ||
352 | </span> | ||
353 | <span class="buttonwrapper"> | ||
354 | <a href="." class="button">Link</a> | ||
355 | </span> | ||
356 | <span class="buttonwrapper"> | ||
357 | <input class="button secondary" type="submit" value="Secondary Button"/> | ||
358 | </span> | ||
359 | <span class="buttonwrapper"> | ||
360 | <a href="." class="button secondary">Secondary Link</a> | ||
361 | </span> | ||
362 | </div> | ||
363 | {{/code}} | ||
364 | |||
365 | === [demo] === | ||
366 | |||
367 | {{html clean="false"}} | ||
368 | <form action="." class="xform" method="post" name="form_name6"> | ||
369 | <dl> | ||
370 | <dt> | ||
371 | <label for="input_id6">Label</label> | ||
372 | </dt> | ||
373 | <dd> | ||
374 | <input id="input_id6" name="input_name6" type="text" size="60" value=""/> | ||
375 | </dd> | ||
376 | </dl> | ||
377 | <p class="buttons"> | ||
378 | <span class="buttonwrapper"> | ||
379 | <input class="button" type="submit" value="Button"/> | ||
380 | </span> | ||
381 | <span class="buttonwrapper"> | ||
382 | <a href="." class="button">Link</a> | ||
383 | </span> | ||
384 | <span class="buttonwrapper"> | ||
385 | <input class="button secondary" type="submit" value="Secondary Button"/> | ||
386 | </span> | ||
387 | <span class="buttonwrapper"> | ||
388 | <a href="." class="button secondary">Secondary Link</a> | ||
389 | </span> | ||
390 | </p> | ||
391 | </form> | ||
392 | {{/html}} | ||
393 | |||
394 | === [css] === | ||
395 | |||
396 | ##.buttonwrapper## and ##.button## (##.secondary##) classes are described in ##colibri.css## | ||
397 | |||
398 | == 7. Disabling == | ||
399 | |||
400 | * Use the ##.disabled## class if you want to have disabled input elements | ||
401 | |||
402 | === [preview] === | ||
403 | |||
404 | [[image:disabledElements.png]] | ||
405 | |||
406 | === [html] === | ||
407 | |||
408 | {{code language="html"}} | ||
409 | <dd> | ||
410 | <input type="text" class="disabled" disabled="disabled" ... /> | ||
411 | </dd> | ||
412 | ... | ||
413 | <span class="buttonwrapper"> | ||
414 | <input type="submit" class="button" value="Primary" ... /> | ||
415 | </span> | ||
416 | <span class="buttonwrapper"> | ||
417 | <input type="submit" class="button disabled" disabled="disabled" value="Primary Disabled" ... /> | ||
418 | </span> | ||
419 | <span class="buttonwrapper"> | ||
420 | <input type="submit" class="button secondary" value="Secondary" ... /> | ||
421 | </span> | ||
422 | <span class="buttonwrapper"> | ||
423 | <input type="submit" class="button secondary disabled" disabled="disabled" value="Primary Disabled" ... /> | ||
424 | </span> | ||
425 | ... | ||
426 | <span class="buttonwrapper"> | ||
427 | <a href="." class="secondary button disabled" ... >Secondary Disabled</a> | ||
428 | </span> | ||
429 | {{/code}} | ||
430 | |||
431 | == 8. Grouping == | ||
432 | |||
433 | * Grouping can be done by using fieldset/legend or other markup (like headers) | ||
434 | |||
435 | === [preview] === | ||
436 | |||
437 | [[image:grouping.png]] | ||
438 | |||
439 | === [html] === | ||
440 | |||
441 | {{code language="html"}} | ||
442 | <h2>Group 1</h2> | ||
443 | {{/code}} | ||
444 | |||
445 | === [demo] === | ||
446 | |||
447 | {{html clean="false"}} | ||
448 | <form action="." class="xform" method="post" name="form_name10"> | ||
449 | <h2>Group 1</h2> | ||
450 | <dl> | ||
451 | <dt> | ||
452 | <label for="input_id10">Label</label> | ||
453 | </dt> | ||
454 | <dd> | ||
455 | <input id="input_id10" name="input_name10" type="text" size="60" value=""/> | ||
456 | </dd> | ||
457 | </dl> | ||
458 | <h2>Group 2</h2> | ||
459 | <dl> | ||
460 | <dt> | ||
461 | <label for="input_id11">Label</label> | ||
462 | </dt> | ||
463 | <dd> | ||
464 | <input id="input_id11" name="input_name11" type="text" size="60" value=""/> | ||
465 | </dd> | ||
466 | </dl> | ||
467 | <p> | ||
468 | <span class="buttonwrapper"> | ||
469 | <input class="button" type="submit" value="Button"/> | ||
470 | </span> | ||
471 | </p> | ||
472 | </form> | ||
473 | {{/html}} | ||
474 | |||
475 | === [css] === | ||
476 | |||
477 | {{code language="css"}} | ||
478 | .xform h2 { | ||
479 | font-size: 1.2em; | ||
480 | font-weight: bold; | ||
481 | margin: 2em 0 0; | ||
482 | } | ||
483 | {{/code}} | ||
484 | |||
485 | = Form Examples = | ||
486 | |||
487 | == [preview] == | ||
488 | |||
489 | [[image:example.png]] | ||
490 | |||
491 | == [demo] == | ||
492 | |||
493 | {{html clean="false"}} | ||
494 | <form action="." class="xform" method="post" name="form_name7"> | ||
495 | <dl> | ||
496 | <dt> | ||
497 | <label for="input_id7">Browser Title Bar Text <span class="xRequired">(Required)</span></label> | ||
498 | <span class="xHint">Type the text you want to be displayed in the browser's title bar</span> | ||
499 | </dt> | ||
500 | <dd> | ||
501 | <input id="input_id7" name="input_name7" type="text" size="60" value=""/> | ||
502 | </dd> | ||
503 | <dt> | ||
504 | <label for="checkbox_id1">Indexing</label> | ||
505 | <span class="xHint">Index only elements that are not already indexed</span> | ||
506 | </dt> | ||
507 | <dd> | ||
508 | <label for="checkbox_id1"><input type="checkbox" name="checkbox_id1"/> Standard Index</label> | ||
509 | </dd> | ||
510 | <dt> | ||
511 | <label for="select_id1">Show Left Panels</label> | ||
512 | </dt> | ||
513 | <dd> | ||
514 | <select id="select_id1" size="1"> | ||
515 | <option value="" label="---">---</option> | ||
516 | <option value="1" label="Yes">Yes</option> | ||
517 | <option selected="selected" value="0" label="No">No</option> | ||
518 | </select> | ||
519 | </dd> | ||
520 | <dt> | ||
521 | <label>Activate annotations</label> | ||
522 | <span class="xHint">Configure if annotations are available for the current wiki</span> | ||
523 | </dt> | ||
524 | <dd> | ||
525 | <label for="radio_id1"> | ||
526 | <input type="radio" value="1" name="radio_name1" id="radio_id1" checked="checked"/> | ||
527 | Yes | ||
528 | </label> | ||
529 | <label for="radio_id2"> | ||
530 | <input type="radio" value="0" name="radio_name1" id="radio_id2"/> | ||
531 | No | ||
532 | </label> | ||
533 | </dd> | ||
534 | <dt> | ||
535 | <label for="textarea_id1">HTTP Meta Information</label> | ||
536 | </dt> | ||
537 | <dd> | ||
538 | <textarea id="textarea_id1" rows="7" cols="45">Text</textarea> | ||
539 | </dd> | ||
540 | </dl> | ||
541 | <p> | ||
542 | <span class="buttonwrapper"> | ||
543 | <input class="button" type="submit" value="Button"/> | ||
544 | </span> | ||
545 | <span class="buttonwrapper"> | ||
546 | <input class="secondary button" type="submit" value="Secondary Button"/> | ||
547 | </span> | ||
548 | </p> | ||
549 | </form> | ||
550 | {{/html}} | ||
551 | |||
552 | = Tips = | ||
553 | |||
554 | == Other useful CSS classes == | ||
555 | |||
556 | * Read about [[Special CSS classes>>Documentation.DevGuide.FrontendResources.SpecialCSSClasses.WebHome]] that can be used for forms elements. | ||
557 | |||
558 | == LiveValidation == | ||
559 | |||
560 | * [[XWIKI-4792>>https://jira.xwiki.org/browse/XWIKI-4792]]: Add javascript LiveValidation input validation library | ||
561 | |||
562 | == Captchas == | ||
563 | |||
564 | * [[Captcha Module>>extensions:Extension.Captcha Module]] | ||
565 | |||
566 | == WCAG == | ||
567 | |||
568 | * A form created within XWiki must be validated accordingly with the WCAG rules. There are some [[exceptions>>dev:Community.WCAGTesting]] stated for XWiki. |