Mike Gerwitz

Activist for User Freedom

aboutsummaryrefslogtreecommitdiffstats
blob: 5b0d5624ab13fc3cb0f54e70bab048d0bddfc5ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
@c  This document is part of the Liza Data Collection Framework manual.
@c  Copyright (C) 2017 R-T Specialty, LLC.
@c
@c    Permission is granted to copy, distribute and/or modify this document
@c    under the terms of the GNU Free Documentation License, Version 1.3
@c    or any later version published by the Free Software Foundation;
@c    with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
@c    Texts.  A copy of the license is included in the section entitled ``GNU
@c    Free Documentation License''.


@node Program
@chapter Program
@maintstart
@footnote{
  The @code{Program} class was one of the first prototypes created,
    and has evolved poorly with the rest of the system.
  It is the base class for all compiled programs,
    and it glues together too many other systems with a terrible
    API and little to no encapsulation.

  With that said, it is one of the least touched classes (thus its
    state); developers rarely have the need to touch @code{Program}.}
@maintend


@cindex Program
The @dfn{Program} is a declarative representation of an entire system.
It is the highest level of abstraction from a data perspective.
The user observes and interacts with a Program using the
  @ref{Program UI,,Program@tie{}UI}.

@cindex Program, XML
Programs contain a lot of metadata that is not in a convenience
  human-readable (or modifiable) format,
    some of which are redundant.
Programs are ideally compiled from a @ref{Program XML,,Program@tie{}XML}
  document.

@menu
* Program UI::
* Program XML::
* Document Metadata::  Document-level data that cannot be modified by
                       the client.
@end menu



@node Program UI
@section Program UI
@maintenance{
  The @code{Ui} class,
    in addition to @srcref{src/client/Client,Client} (@pxref{Client}),
    represent the two monoliths of the system.
  This mediates all UI-related tasks,
    and still has far too many concerns with far too many
      dependencies.
  Code is to be extracted out of this class as it is touched.
}


@cindex Program, User Interface
@cindex User Interface, Program
The @dfn{Program UI} renders a @ref{Program} as a form.

@cindex Step
@cindex Group
At the highest level,
  steps are rendered in a tab-like manner,
  above the main form content.
A step contains groups,
  which in turn contain elements such as questions.
Groups are delimited in some manner defined by their style
  (@pxref{Group Styles}).

@cindex Question
@cindex Question, Value Formatting
@cindex Bucket, Updating
Questions are rendered as form fields.
Any time the respective @ref{Bucket} field is changed,
  the form field is updated to reflect those changes,
    after having first been formatted with the appropriate validator
    (@pxref{Formatting Values}).
When a question is changed by the user,
  the value is expected to be propagated to the Bucket
  (@pxref{Bucket Assignment}).

@cindex Navigation Bar
@cindex User Interface, Navigation Bar
@cindex User Interface, Button Navigation
Navigation between steps can be done via the
  @dfn{Navigation Bar} above the step@tie{}content,
  or using ``Go@tie{}Back'' and ``Continue'' buttons at the foot of the
  step@tie{}content.

@cindex Sidebar
A @dfn{Sidebar} is rendered adjacent to the step content.
It displays the name of the Program,
  as well as configurable metadata (usually through the @samp{sidebar}
  node of the @ref{Program XML,,Program@tie{}XML}).
It also displays question help text (also configured through the XML)
  and any error messages (@pxref{Error Handling}).

@menu
* Group Styles::     Different ways of displaying groups of questions
                       to the user.
* DOM Abstraction :: Representing and efficiently manipulating the DOM.
@end menu



@node Group Styles
@subsection Group Styles
@refactor{
  Some group styles still use jQuery;
    they should be modified to use modern formatters and Liza DOM
    abstractions (see @srcrefraw{src/ui/field}
      and @srcrefraw{src/ui/styler}).}

@cindex Group, Styling
Groups support a number of @dfn{group styles} that determine how
  they are delimited from other groups (@pxref{Defining Groups});
  how the elements they contain are rendered and laid out;
  and how multiple indexes are displayed, added, and removed.
A list of available styles is detailed in @ref{t:group-styles}.

@float Table, t:group-styles
@multitable @columnfractions 0.15 0.65 0.10 0.10
  @headitem Name @tab Description @tab Multi-Index? @tab Add/Remove Index?

  @item @samp{default}
  @tab
  Groups are unstyled by default@mdash{
    }they render elements as flat fields like a traditional form.
  Only the first index of elements is rendered.
  @tab@center N
  @tab@center N

  @item @samp{accordion}
  @tab
  Styled as a @samp{stacked} group with a header that toggles
    the body associated with that index.
  When collapsed,
    only the header is visible for that index.
  The default styling indicates the collapsed status using an arrow in
    the header.
  @tab@center Y
  @tab@center N

  @item @samp{collapsetable}
  @tab
  Renders element label in the leftmost column like @samp{sidetable}.
  Indexes are groups of rows delimited by headings,
    which collapse the respective group of rows when clicked.
  @tab@center Y
  @tab@center Add

  @item @samp{sidetable}
  @tab
  Renders elements as rows with label in the leftmost column rather
    than the top row.
  Each index is rendered as a column.
  @tab@center Y
  @tab@center Add

  @item @samp{stacked}
  @tab
  Groups respective indexes of elements such that one set of indexes
    appears atop of another set,
      much like separate groups are placed.
  @tab@center Y
  @tab@center N

  @item @samp{tabbedblock}
  @tab
  Each group is rendered as a block,
    with each index rendered as a tab to the right of it.
  Clicking a tab toggles the body content to the associated index.
  Elements are rendered within the box.
  @tab@center Y
  @tab@center N

  @item @samp{tabbed}
  @tab
  Like @samp{default},
    but each index has a tab at the top of the group.
  Clicking a tab toggles the body content to the associated index.
  @tab@center Y
  @tab@center Y

  @item @samp{table}
  @tab
  A vanilla table with elements as columns,
    their labels across the top row.
  Each index is rendered in its own row.
  @tab@center Y
  @tab@center Y
@end multitable
@caption{Group styles and index support}
@end float



@node DOM Abstraction
@subsection DOM Abstraction
@cindex DOM
@cindex Dojo, History
@cindex jQuery
@devnotice{jQuery is still used throughout parts of the framework and
             is a performance bottleneck@mdash{
               }it needs to be fully removed and replaced with this
                 DOM@tie{}abstraction.@footnote{
                   See @srcrefraw{src/ui/ElementStyler}.}}

@trivia{Liza was conceived long before frameworks like React existed.
          The implementation originally used Dojo because of its
            broad widget set,
              but it was later dropped because of extreme performance issues,
                especially on the browsers of the day
                  (Liza had to support Internet Explorer@tie{}6!);
                  at one point,
                    certain steps took over a minute to load for the
                    most unfortunate of users.
          jQuery was then used for various parts of the UI and for ease of
            DOM manipulation,
              because of the lack of good and universal DOM APIs back then.
          It too became a bottleneck.
          Using DOM@tie{}APIs is now easy with modern browsers.}

Liza's DOM abstraction contains a couple of components:

@cindex DOM, Context
@cindex DOM, Field
@itemize
@item @dfn{DOM Fields} represent a field on the DOM.
      Each field has a name and an index associated with the
        DOM@tie{}node.
      Nodes are cached in memory after first access and queue requests
        during lookups to prevent stampeding.
      Provides basic DOM operations,
        including styling, containing row, and  parent/sibling selecting.
      See @srcref{src/ui/field}.
@item @dfn{DOM Context} is a slice of the DOM used for restricting queries.
      It can attach and detach sections of the DOM,
        and be further split into a context hierarchy.
      The @srcrefjs{src/ui/context,DomContext} provides field querying
        (see @srcrefjs{src/ui/field,DomField}) and caching.
      See @srcrefraw{src/ui/context}.
@end itemize

@tip{It is important to always use these abstractions for any portions
      of the DOM under control of this abstraction;
        otherwise, assumptions used for caching may result in
          unintended behavior.}

Using DOM contexts,
  DOM operations can be restricted to small windows (for example,
    groups or tabs),
      further reducing the impact of DOM queries.

The @dfn{root context} is represented by
  @srcrefjs{src/ui/context,RootDomContext}@mdash{
    }sub-contexts can be obtained by invoking @jsmethod{slice} on any
      context,
        which creates a new context from a subset of the parent.
Detaching a parent will detach all child contexts.

Contexts can be manipulated in memory before being re-attached.
Detach a context from the DOM with @jsmethod{detach},
  and attach with@tie{}@jsmethod{attach}.
A context is aware of its parent and will re-attach itself to the DOM
  in the correct place.
A child context always attaches to the parent,
  and so will not be rendered until the parent attaches.

@tip{Always detach from the DOM before performing extensive manipulations;
       this prevents the need for expensive re-painting until
         manipulation is done,
           at which point the context can be re-attached.}


@menu
* Field Styling:: Styling @srcrefjs{src/ui/field,DomField}.
@end menu



@node Field Styling
@subsubsection Field Styling
@cindex Field, Styling
@helpwanted

@srcrefjs{src/ui/field,DomField} is styled using field stylers
  (see @srcrefraw{src/ui/styler}).
The two most notable stylers are
  @srcrefjs{src/ui/field/ErrorFieldStyler} and
  @srcrefjs{src/ui/field/NaFieldStyler},
    which style fields in error and hide fields that are no applicable
    respectively.


@node Program XML
@section Program XML
@helpwanted

@menu
* Defining Groups::       Grouping questions and other entities.
* Specifying Predicates:: Predicating display of entities.
@end menu


@node Defining Groups
@subsection Defining Groups

@cindex Group
A @dfn{group} organizes and relates entities.
If given a @xmlattr{title},
  a header will be displayed above the group with that title.
A group may optionally be given a unique identifier@tie{}@xmlattr{id},
  which is useful for debugging and scripting;
    any such identifier should be @code{snake_case}.

@float Figure, f:group
@example
  <group title="Foo Group">
    <question id="question_1" ... />
    <question id="question_2" ... />
  </group>
@end example
@caption{Defining a simple group with a title}
@end float

@cindex Group, Styling
Groups can be independently styled in a number of different ways to
  provide different data representations (@pxref{Group Styles}).
Style is optional@mdash{
  }the @samp{default} group displays only the first index of each
    entity.
Further styling can be done using CSS using @xmlattr{class}.

@cindex Group, Leader
@cindex Group, Indexes
All questions within a group share the same number of indexes;
  this is accomplished by monitoring the @dfn{group leader}.
By default,
  the leader is the first indexable entity in the group (question,
    answer, or display);
      this can be overridden with the @xmlattr{indexedBy} attribute.
This attribute is only practically meaningful if the chosen group
  style supports indexes (@pxref{Group Styles}).


@float Figure, f:group-leader
@example
  <group id="leader_override" indexedBy="question_2" style="tabbed">
    <question id="question_1" ... />
    <question id="question_2" ... />
  </group>
@end example
@caption{Overriding group leader using @xmlattr{indexedBy}}
@end float

@cindex Group, Locking
Some group styles allow the user to add indexes;
  set @xmlattr{locked} to@tie{}@samp{true} to suppress this feature.

@subsubsection Linking Groups
@cindex Group, Linking
Data collection for similar entities may span multiple steps or
  groups;
    for example,
      one group may allow the user to define their risk locations,
        and a future group may ask for additional information for each
        of those locations.
To have all entities within each of those groups share index length,
  they may be linked.

A @dfn{group link} is an arbitrary name given to a set of groups.
Each group that wants to be part of the same link must set
  @xmlattr{link} to the same string.
The name of the link does not matter@mdash{
  }it is @emph{not} a reference to a group@tie{}@xmlattr{id}.

@float Figure, f:group-link
@example
  <group id="location" link="locations" style="tabbed">
    <question id="address" ... />
    <question id="city" ... />
  </group>

  <group id="underwriting" link="locations" style="tabbed">
    <question id="diving_board" ... />
    <question id="rabid_dog" ... />
  </group>
@end example
@caption{Linking groups using @xmlattr{link}}
@end float

In @ref{f:group-link},
  each question in @var{location} and @var{underwriting} will have the
  same number of indexes@mdash{
    }any time a new index is added to @var{location},
      @var{underwriting} questions too will gain another index and
      vice versa.
There is no limit to the number of groups that can share the same link.

@devnote{Linked groups are implemented such that the union of all fields
       in each of the groups of a given link are assigned to each of the
       individual groups.
     When the leader of any group changes,
       a new index is initialized for each group field,
         which (in the case of linked groups) is comprised of all
         fields in the link.}



@node Specifying Predicates
@subsection Specifying Predicates

@cindex Predicate
Object predicates (@pxref{Predicate System}) are specified using the
  @xmlattr{when} attribute of certain nodes.
It must contain a string of references understood by the system
  (see domain of discourse, @ref{Predicate System}),
    all of which much match for the predicate to be true.

@float Figure, f:pred-when
@example
  <question id="describe" type="noyes"
            label="Any special notes for this location?" />

  <question id="vacant_desc" type="textarea"
            when="q:describe vacant property"
            label="Show only when a vacant property with the
                   question 'describe' non-empty and non-zero" />
@end example
@caption{Using the @xmlattr{when} attribute}
@end float

In @ref{f:pred-when} above,
  question @samp{vacant_desc} will be applicable when @emph{all} of
  the values of @samp{vacant}, @samp{property},
  and@tie{}@samp{q:describe} are true.@footnote{
    @xref{Predicate System} for what ``true'' means for a particular
      variable in the domain of discourse.}
Within the context of the @progxml,
  this concretely means that the classifications
  @samp{vacant} and@tie{}@samp{property} are true,
    and that the question @samp{describe} is answered ``yes''.
It reads as a sentence:
  ``@samp{vacant_desc}'' is applicable when we should @tie{}``describe
  a vacant property''.



@node Document Metadata
@section Document Metadata
@dfn{Document metadata} are metadata that describe certain aspects of the document;
  they are stored adjacent to the bucket in @samp{meta}@tie{}on the
  document root.@footnote{
    Terminology note: ``document'' and ``quote'' are the same thing;
      the latter is transitioning to the former for generality.}
They should be used in place of a bucket field any time
  the client has no business knowing about the data.
The @samp{meta} record is called the @dfn{Metabucket}.

@c don't use a dapi xref here; don't want to confuse the reader by
@c directing them away from this section before they continue reading
@tip{Metadata in the Metabucket should@tie{}@emph{not} be
  directly populated by external systems@mdash{
    }@dapi integration should be used instead (see below).}

Metadata can be populated using any@tie{}@dapiref@mdash{
  }return data populate the Metabucket in the same way that they
  populate the Bucket.
Definitions are stored in @code{meta.fields},
  as shown in @ref{f:meta-fields}.

@float Figure, f:meta-fields
@example
"fields":@{
  ["string(name)": @{
    "desc": "string",
    "dapi": @{
      "name": "string",
      "map": @{
        "string(dest field)": "string(source field)"
      @}
    @}
  @}
@}
@end example
@caption{Format of @code{meta.fields}.}
@end float

Further, a key-value mapping of all bucket fields that@mdash{
  }when modified,
    need to result in a metadata API@tie{}call@mdash{
  }are stored in the @code{mapis}@tie{}object;
    this is shown in @ref{f:mapis}.

@float Figure, f:mapis
@example
"mapis":@{
  ["string(field name)"]: [ "string(dapi name)", ... ]
@}
@end example
@caption{Format of @code{mapis}.}
@end float