Wiki source code of pageMaker

Last modified by Jip-jan Alunkel on April 13, 15:42

Show last authors
1 To assert influence over the evolving structure of the pages and their XObjects within a wiki one can use pageMaker.
2
3 1. Copy pageMaker to /assets/pagemaker on your wiki.
4 1. In the space where you want to use pageMaker (e.g. //MySpace//) you create another space with “Code” added to the end (e.g. //MySpaceCode//). In this space you can create the class, the sheet, the template and the translation file. The easiest way to create these files is by using App Within Minutes.
5 1. Create the spaces you would like to see newly created pages to be stored in.
6
7 By using the examples above, your wiki should have the following spaces added:
8
9 * ##assets.pagemaker##
10 * ##MySpace## and all child spaces thereof (i.e. ##MySpace.ChildSpace1##, ##MySpace.ChildSpace2##, ##MySpace.ChildSpace3##, ... etc.)
11 * ##MySpaceCode.MySpaceSheet##
12 * ##MySpaceCode.MySpaceTemplate##
13 * ##MySpaceCode.MySpaceClass##
14 * ##MySpaceCode.Translations##
15
16 == Required attributes for all input elements ==
17
18 There are four basic attributes needed to create input elements: ##id##, ##type##, ##required## and ##label##. These attributes must be provided for each call to the ###createFormElement## macro.
19
20 === Attributes ===
21
22 __id__
23 Every input element must have its own id. The value of the //id// attribute must be unique within the HTML document.
24
25 {{code language="velocity"}}
26 "id" : "car_type",
27 {{/code}}
28
29 __type__
30 The //type// attribute defines the type of input element that is to be created. The value of this attribute is limited to:
31
32 * ##text##
33 * ##number##
34 * ##email##
35 * ##range##
36 * ##select##
37 * ##checkbox## and ##radio##
38 * ##textarea##
39 * ##date##
40 * ##color##
41 * ##url##
42 * ##tel##
43
44 {{code language="velocity"}}
45 "type" : "select",
46 {{/code}}
47
48 __required__
49 The //required// attribute specifies if this input element is required or not and can correspondingly be set to ##true## or ##false##. This is not a boolean value but a string, one must therefore make sure to put the value of this attribute between quotes.
50
51 {{code language="velocity"}}
52 "required" : "true",
53 {{/code}}
54
55 __label__
56 The //label// attribute specifies the primary description for the input element. The value of this label is also used for the description of the error message.
57 The label should be seen as a short reference to the subject that is being asked for, without the leading article or possessive adjective.
58
59 Define a label for an input element that asks for the type of car you own.
60
61 {{code language="velocity"}}
62 "label" : "Type of car",
63 {{/code}}
64
65 == Required attributes for specific elements ==
66
67 __value__
68 The //value// attribute is required for input elements where the value is predetermined, which are the ##select##, ##checkbox## and ##radio## input elements.
69 The ##select## input element however has its values created from the pages queried or from the JSON provided. These values are added to the ##option## HTML tags within the ##select## HTML tag. The //value// attribute is therefore not applicable in the ##select## input element.
70 The ones that do require a //value// attribute are ##checkbox## and ##radio## input elements.
71
72 == Optional common attributes ==
73
74 Some attributes are not necessary or even proper to bestow upon every type of input element.
75 For example, the ##placeholder## attribute has no place in a ##checkbox## input element but for a ##select## input element its use is strongly advised in the call to the ###createFormElement## macro.
76
77 === Attributes ===
78
79 __placeholder__
80 The //placeholder// attribute specifies a short hint that describes the expected value of an input field. This can be in the form of a sample value or a short description of the expected format. The short hint is displayed in the input field before the user enters a value.
81 All input elements in formMaker can (and should) be provided with a placeholder, except for the following input elements:
82
83 * ##Checkbox## and ##radio##
84 * ##Date##
85 * ##Color##
86 * ##Range##
87
88 {{code language="velocity"}}
89 "placeholder" : "Type",
90 {{/code}}
91
92 __aria-label__
93 The aria-label attribute is used to give the input element a description of its purpose in the form of a full sentence. The value of this attribute is used by screen readers only and therefore improves accessibility of the formʼs presentation.
94
95 Define an aria-label for an input element that asks for the type of car you own.
96
97 {{code language="velocity"}}
98 "aria-label" : "Select the type of car you own",
99 {{/code}}
100
101 __help-block__
102 The //help-block// is a separate block of text, displayed below the input element. It is meant for a complete description of the inputʼs purpose, the format that is expected and eventual examples. The value of this input can be given in the form of plain text or a translation rendering. As such, please remind yourself not to forget the punctuation. It is advised to **always** use this attribute, except for the odd exception where the use of this attribute is truly superfluous.
103
104 {{code language="velocity"}}
105 "help-block" : "Select the type of car you own. If you own multiple cars you can refer to the car that is used most often.",
106 {{/code}}
107
108 __data-error-response-type__
109 The //data-error-response-type// attribute is used for the grammatical makeup by which the error is being displayed. The error response is generated with help from the label, which is why the label should be very concise and without pronoun or article. The main groups of response types are responses based on possessive adjectives (i.e. “your”), definite articles (i.e. “the”) and indefinite articles (i.e. “a” or “an”). All languages have their own articles and sometimes these can add up, the German language for example has 6 different possessive pronouns, 6 different definite and 6 different indefinite articles. These different pronouns and articles can be defined in the pageMaker translation document.
110 The different responses are:
111
112 * ##use_label_possessive_1##, up to ##use_label_possessive_8##
113 * ##use_label_definite_1##, up to ##use_label_definite_8##
114 * ##use_label_indefinite_1##, up to ##use_label_indefinite_8##
115
116 When this attribute is not used, the hint falls back on a non-descript default message.
117
118 {{code language="velocity"}}
119 "data-error-response-type" : "use_label_definite_1",
120 {{/code}}
121
122 == Optional specific attributes ==
123
124 Some attributes are beholden to one specific type of input element only. For example, the //range-step// attribute is meant only for the ##range## input element, it cannot be used in any other type of input element.
125
126 === The ##text## input element ===
127
128 __data-pattern__
129 The //data-pattern// attribute is used to test the input against the regular expression found in the value of this attribute.
130 For example the following code can be used if the user is only allowed to enter letters (case insensitive), numbers and underscores, with a minimum of four characters.
131
132 {{code language="velocity"}}
133 "data-pattern" : "^[a-zA-Z0-9_]{4,}$",
134 {{/code}}
135
136 === The ##number## input element ===
137
138 __data-decimals__
139 The //data-decimals// attribute refers to the number of decimals the input should have. This attribute can only be used when the //type// attribute is set to ##number##. When this attribute is not used it defaults to ##0##.
140
141 {{code language="velocity"}}
142 "data-decimals" : 2,
143 {{/code}}
144
145 __decimal-step__
146 The //decimal-step// attribute is used together with the //data-decimals// attribute and refers to the size of the inclination of the number when the input has the focus and the mouse wheel or keyboard arrows (up and down) is used. This attribute can only be used when the //type// attribute is set to ##number##. When this attribute is not used it defaults to ##1##.
147
148 {{code language="velocity"}}
149 "decimal-step" : .1,
150 {{/code}}
151
152 === The ##date## input element ===
153
154 __date-min__
155 The //date-min// attribute stands for the minimum date that can be chosen from the calendar. The value of this attribute should be a date, in the format ##yyyy-mm-dd##. This is an optional attribute.
156
157 __date-max__
158 The //date-min// attribute stands for the maximum date that can be chosen from the calendar. The value of this attribute should be a date, in the format ##yyyy-mm-dd##. This is an optional attribute.
159
160 {{code language="velocity"}}
161 "date-min" : "1900-01-01",
162 "date-max" : "2024-01-01",
163 {{/code}}
164
165 === The ##range## input element ===
166
167 __range-minmax__
168 The //range-minmax// attribute stands for the range in which the slider of the ##range## input element operates. The value of this attribute should be two numbers, separated by a dash, i.e. ##20-80##. When this attribute is not used it defaults to ##0-100##.
169
170 __range-step__
171 The //range-step// attribute stands for the size of the interval with which the slider moves. In a range of 0-100 with a step of 5 there are 20 different possible positions to set as value for the slider. When this attribute is not used it defaults to ##1##.
172
173 {{code language="velocity"}}
174 "range-minmax" : "0-100",
175 "range-step" : 5,
176 {{/code}}
177
178 === The ##checkbox## or ##radio## input element ===
179
180 __data-opener__
181 The predetermined input elements can also serve the purpose of opening up a new section in the form. This is done by adding the attribute //data-opener// with the value ##true##.
182
183 The section that is controlled by this predetermined input can be added with the Velocity macro ###createExpandStart## and ###createExpandend##.
184
185 {{code language="velocity"}}
186 #set($extra_info = {
187 "id" : "extra_info",
188 "type" : "checkbox",
189 "required" : "no",
190 "label" : "Extra information (optional)",
191 "value" : "1",
192 "data-opener" : "true"
193 })
194 #createFormElement($extra_info)
195 #createExpandStart($extra_info "1")
196 ...
197 Contents of the to-be-expanded section (which can also include any input element(s)).
198 ...
199 #createExpandend()
200 {{/code}}
201
202 === The ##select## input element ===
203
204 One of the ways to create options for the ##select## input element is to have pageMaker search for all first-level decendants in a given parent space. The other way is to provide a map of values (the keys) and descriptions (the values) for each option, it creates child spaces if the key is a an XWiki reference. One of these attributes must be provided because without it, no options are created.
205
206 __select-space-reference__
207 The //select-space-reference// attribute references the parent space which will be queried for all direct descendant spaces it has. The value of this attribute is formatted like an XWiki reference but without the ##.WebHome## ending. This query results in an HTML list of option elements where the values of the option elements are the page reference (including the parent space, without ##.WebHome##) and the contents of the option elements is the title of the page which is referenced.
208
209 {{code language="velocity"}}
210 "select-space-reference" : "cars",
211 {{/code}}
212
213 __select-spaces-json__
214 By using the //select-spaces-json// attribute, pageMaker creates a json object from all the direct descendants, which will be logged in the console (in the browser's development tools). This JSON object can be copied from the console and used in the //select-json// attribute.
215
216 {{code language="velocity"}}
217 "select-space-reference" : "cars",
218 "select-spaces-json" : "true",
219 {{/code}}
220
221 __select-json__
222 The //select-json// attribute contains a map which lists the values and contents of each HTML option tag. When the keys in the map represent an XWiki reference, XWiki pages will be created at the locations referenced if they do not yet exist. The title of these pages are formed from the values in the map if they do not yet exist or if they deviate from the values in the map.
223 If you do not yet have any structure of child spaces set up, this is an easy way of doing so. Not only will all child spaces be created on the fly, the order of the map is also maintained in the options (the order of the map is the order of the options).
224
225 {{code language="velocity"}}
226 ## Example of a standard map
227 "select-json" : {
228 "renault" : "Renault",
229 "zastava" : "Zastava",
230 "fiat" : "Fiat",
231 "aston_martin" : "Aston Martin"
232 },
233
234 ## Example of an enriched map (which makes maintaining the structure easier)
235 "select-json" : {
236 "cars.renault" : "Renault",
237 "cars.zastava" : "Zastava",
238 "cars.fiat" : "Fiat",
239 "cars.aston_martin" : "Aston Martin"
240 },
241 {{/code}}
242
243 __select-json-spaces__
244 By using the //select-json-spaces// attribute, pageMaker creates spaces from the json object properties, where the key will serve as the XWiki reference and the value will be the title of the space. The //select-json-spaces// attribute will also make sure that each of these newly created spaces will be provided with an XObject based on the “pagemaker.pagemakerClass” XWiki class which makes it possible to customize the order of these spaces in the select element (when swithing back to the //select-space-reference// attribute).
245
246 {{code language="velocity"}}
247 "select-json" : {
248 "cars.renault" : "Renault",
249 "cars.zastava" : "Zastava",
250 "cars.fiat" : "Fiat",
251 "cars.aston_martin" : "Aston Martin"
252 },
253 "select-json-spaces" : "true",
254 {{/code}}
255
256 Later on it is possible to switch back to the //select-space-reference// attribute if there is a wish to do so. Using the previous example, this would look like:
257
258 {{code language="velocity"}}
259 "select-space-reference" : "cars",
260 {{/code}}
261
262 __data-opener__
263 With the use of the //data-opener// attribute, the ##select## input element can also serve the purpose of opening up a new section in the form, just as is described in the ##checkbox## or ##radio## input element. The procedure and logic is also the same as in the ##checkbox## or ##radio## input element.
264
265 === The ##textarea## input element ===
266
267 __textarea-rows__
268 The //textarea-rows// attribute refers to the number of rows the textarea input field should get. When this attribute is not used it defaults to ##8##.
269
270 {{code language="velocity"}}
271 "textarea-rows" : 8,
272 {{/code}}
273
274 == Create an active suggestion list for the input ==
275
276 It is very helpful for the user when he or she gets suggestions of what needs to be typed (or should not be typed) in the input field. This is also very helpful in maintaining the logic and integrity of the wiki contents. As the formMaker tool is meant to create wiki pages, a suggestion list is something a user cannot do without.
277
278 To create an active suggestion list for the input, certain information is necessary to define in the macro call for a new input.
279
280 * FormMaker needs to know where to find the JSON file from which it can build up the suggestion list and how this JSON file is created, namely as the result of an XWQL query or just a static JSON file. This is made known to formMaker by the attribute //data-query-type//.
281 * If the JSON file will be the result of an XWQL query, formMaker needs to know where it needs to perform this query, which is done so by using the attribute //data-query-scope//.
282 * Usually an active suggestion list is regarded as a list of suggestions that correspond with the partial input of the user, from which the user can then select the most appropriate item. In formMaker this is called a “suggest-select” list. It can also be the other way around, a list of suggestions of what the user should avoid to type, which is called a “suggest-negate” list. This is defined in the attribute //data-query-list-type//.
283 * FormMaker also needs to be told what needs to be shown in the suggestion list, the value, the key or both, and in which order. This is defined by the attribute //data-query-list-contents//.
284 * The active suggestion list can be provided with a header which can inform the user about what to expect from these suggestions. This is defined by the attribute //data-query-list-header//.
285 * Is the user able to type in new, original input or is the input explicitly beholden to the suggestions given? This can be defined by the attribute //data-query-list-editable//.
286
287 === Attributes ===
288
289 __data-query-type__
290 The //data-query-type// attribute identifies the type and name of the file that is requested through XMLHttpRequest. The value of this attribute is defined in the form of a XWiki reference. Beside the difference in the necessity of also defining the //data-query-scope// attribute, this distinction is made to keep ready made JSON files and XWQL made JSON files seperate from each other in two different spaces. These spaces are:
291
292 * ##/assets/formMaker/JSON##
293 * ##/assets/formMaker/XWQL##
294
295 Define an XWQL query which is created in the XWiki page “matchObject” that produces a JSON object which can be used as a basis for specific results in this form element.
296
297 {{code language="velocity"}}
298 "data-query-type" : "XWQL.matchObject"
299 {{/code}}
300
301 __data-query-scope__
302 The data-query-scope attribute identifies the space (or child space) in which a query is performed. In other words, if the //data-query-type// is defined as XWQL, the //data-query-scope// attribute should **always** be provided. The space in this attribute can also be a nested space, which can be defined by separating the spaces with a circumflex (^). For example: ##ParentSpace^ChildSpace##.
303
304 Define the space on which the XWQL query is being perfomed.
305
306 {{code language="velocity"}}
307 "data-query-scope" : "cases"
308 {{/code}}
309
310 __data-query-list-type__
311 The //data-query-list-type// attribute identifies which function the list has, ##suggest-negate## or ##suggest-select##.
312
313 * ##suggest-negate## checks if the input value is unique and gives a list of similar values that the user should avoid.
314 * ##suggest-select## gives a list of values similar to the input, from which the user can or should choose the right one.
315
316 When this attribute is not being used or has no value or a non existent value it defaults to ##suggest-select##.
317
318 Create a text input that after input of one character, generates a list with clickable suggestions that will be set as the value of the input when clicked.
319
320 {{code language="velocity"}}
321 "data-query-list-type" : "suggest-select"
322 {{/code}}
323
324 __data-query-list-contents__
325 The //data-query-list-contents// attribute identifies how the suggest list will be displayed and what part of the JSON will be queried. The possibilities are:
326
327 * ##key##: Perform a query on the JSON keys and show only the found key(s).
328 * ##key/value##: Perform a query on the JSON keys and show the found key(s) with the value(s) beside it in parenthesis.
329 * ##value##: Perform a query on the JSON values and show only the found value(s).
330 * ##value/key##: Perform a query on the JSON values and show the found value(s) with the key(s) beside it in parenthesis.
331
332 Create a text input with a suggestion list that displays the similar keys from the JSON file and the values in parenthesis next to it.
333
334 {{code language="velocity"}}
335 "data-query-list-contents" : "key/value"
336 {{/code}}
337
338 __data-query-list-header__
339 The //data-query-list-header// attribute defines the text to be displayed as the header of the suggestion list. This can be a line of text or an XWiki translation rendering. The translation file standardly used for formMaker is located at ##assets/formMaker/translations##.
340
341 Create a suggestion list header that can be translated in the available languages on your wiki.
342
343 {{code language="velocity"}}
344 "data-query-list-header" : "$services.localization.render('cases.line.suggest_select_list')"
345 {{/code}}
346
347 __data-query-list-editable__
348 The //data-query-list-editable// attribute identifies if the suggestions are explicit or not. Set to ##false## is making a selection from the suggestions the only possible input. It cannot be altered in the input afterwards. If set to ##true##, random input is possible but the suggestions make the input more easy and helps keeping the stored object property values cleaner or more neato.
349 When this attribute is left out this option will default to ##false##.
350
351 Create a suggestion list that does not have to be followed explicitly so input that differs from the suggestions displayed is allowed.
352
353 {{code language="velocity"}}
354 "data-query-list-editable" : "true"
355 {{/code}}
356
357 === Full example ===
358
359 Create a ##text## input element that offers a list of choices to select the value from. Other values (that differ from the ones suggested in the list) are not allowed.
360
361 {{code language="velocity"}}
362 #set($remedy = {
363 "id" : "remedy",
364 "type" : "text",
365 "required" : "yes",
366 "label" : "Remedy",
367 "aria-label" : "Choose the remedy",
368 "placeholder" : "$services.localization.render('cases.word.remedy.placeholder')",
369 "data-error-response-type" : "use_label_undefined",
370 "data-query-type" : "JSON.remedies",
371 "data-query-list-type" : "suggest-select",
372 "data-query-list-header" : "$services.localization.render('cases.line.suggest_select_list')",
373 "data-query-list-contents" : "value/key",
374 "data-create-xobj" : "true",
375 "data-xobj-classname" : "cases.Code.casesClass",
376 "data-xobj-fieldname" : "remedy",
377 "help-block" : 'Select the remedy that is central in this case.'
378 })
379 #createFormElement($remedy)
380 {{/code}}
381
382 The result:
383 image:suggest-select.png
384
385 == The creation of XWiki pages ==
386
387 As stated in the introduction, this application creates XWiki pages. The construct of this component is fairly straightforward and consists of two different input elements, one for the selection of the space and one for the name of the page.
388
389 === Attributes ===
390
391 __data-set-space__
392 The //data-set-space// attribute must be set to ##true## if this input is used to select the name of the (child) space in which you want to create the wiki page. If set to ##true## the value of the input that is set by the user will be used as the space in which to create the new wiki page.
393
394 Changes to the element that has a //data-set-space// attribute will affect the element with the //data-create-page// attribute. Specifically, it appends the (child space part of the) value of the 'space setting' element to the (parent space part of the) value of the //data-query-scope// attribute from the 'page input' element, thus creating an XWiki reference to the space where the page should be saved.
395
396 Create a ##select## input with which a user can select a space where the page that is to be created will reside.
397
398 {{code language="velocity"}}
399 #set($car_type = {
400 "id" : "car_type",
401 "type" : "select",
402 "required" : "true",
403 "label" : "Type of car",
404 "aria-label" : "Select the type of car",
405 "placeholder" : "Type",
406 "data-error-response-type" : "use_label_definite_1",
407 "data-set-space" : "true",
408 "space-reference" : "cars",
409 "help-block" : "Select the type of car you own. If you own multiple cars you can refer to the car that is used most often."
410 })
411 #createFormElement($car_type)
412 {{/code}}
413
414 __data-create-page__
415 The //data-create-page// attribute should be set to ##true## if this input is used for the creation of a page. The value of the input will be used as the document name and the title of the newly created wiki page. In all but the odd exeption this attribute is used in conjunction with the ##text## input type.
416
417 The input that has this attribute **must** also have a //data-query-scope// attribute.
418
419 Create a ##text## input in which a user can type the name of the page that will be created.
420
421 {{code language="velocity"}}
422 #set($car_brand = {
423 "id" : "car_brand",
424 "type" : "text",
425 "required" : "true",
426 "label" : "Brand of the car",
427 "aria-label" : "Enter the brand of the car",
428 "placeholder" : "Brand",
429 "data-error-response-type" : "use_label_definite_1",
430 "data-query-type" : "XWQL.matchTitle",
431 "data-query-scope" : "cars",
432 "data-query-list-type" : "suggest-negate",
433 "data-query-list-header" : "$services.localization.render('formMaker.line.suggest_negate_list')",
434 "data-query-list-contents" : "value",
435 "data-create-page" : "true",
436 "help-block" : 'Please provide the full brand name of the primary car you own.'
437 }
438 #createFormElement($car_brand)
439 {{/code}}
440
441 == Adding XObjects to the new XWiki page ==
442
443 Limited to 100 objects per page.
444
445 === Attributes ===
446
447 __data-create-xobj__
448 The //data-create-xobj// attribute identifies if an XObject property should be created. When this attribute exists (regardless of the value), the input element that has this attribute will be used to create the XObject property. If the XObject does not exist yet, it will be created. For the purpose of writing correct HTML, set the attribute value to ##true##.
449 This attribute should be used together with the attributes ##data-xobj-classname## and ##data-xobj-fieldname##. The value the user puts into the text input will be used as the value for the XObject.
450
451 __data-xobj-classname__
452 The //data-xobj-classname// attribute refers to the name of the class object that you have created at an earlier point. It should have the fields you need for this purpose.
453
454 __data-xobj-fieldname__
455 The //data-xobj-fieldname// attribute identifies the name of the XObject property that should be created. The value of the XObject property is added by using the value of the input. The value should be the name of the XObject property that you want to create.
456
457 Create a text input that adds a Class XObject to the wiki page you are creating and adds the value of the user input to the ##remedy## field of this Class XObject.
458
459 {{code language="velocity"}}
460 "data-create-xobj" : "true",
461 "data-xobj-classname" : "cases.Code.casesClass",
462 "data-xobj-fieldname" : "remedy"
463 {{/code}}