Documentation ¶
Overview ¶
Package qst implements a four levels deep nested structure with input controls, groups, pages and questionnaire; contains HTML rendering, page navigation, loading/saving from/to JSON file, consistence validation, multi-language support.
Index ¶
- Constants
- Variables
- func AddStaticDynamicGroups(page pageT)
- func BIIILater(q *QuestionnaireT, pageIdx int) bool
- func BIIIMeasure(q *QuestionnaireT, pageIdx int) bool
- func BIIINow(q *QuestionnaireT, pageIdx int) bool
- func BasePath() string
- func CleanseUserAgent(s string) string
- func DeadlineAndPublication(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
- func DelocalizeNumber(s string) string
- func EnglishTextAndNumbersOnly(s string) string
- func ErrorProxy(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
- func FederalStateAboveOrBelowMedian(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
- func GermanOnly(q *QuestionnaireT, pageIdx int) bool
- func LinkBack(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
- func Mustaz09Underscore(s string) bool
- func NewInput() inputT
- func ParseJavaScript(tName string) (*template.Template, error)
- func PatLogos(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
- func PermaLink(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
- func PersonalLink(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
- func RenderStaticContent(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
- func ResponseStatistics(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
- func ResponseTextHasEuro(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
- func UNUSEDpdsPage23(q *QuestionnaireT, page *pageT, acIdx int) error
- type CompositeFuncT
- type DropdownT
- func (d *DropdownT) Add(k string, v trl.S) string
- func (d *DropdownT) AddPleaseSelect(v trl.S)
- func (d *DropdownT) HasAttr(k string) bool
- func (d *DropdownT) Len() int
- func (d *DropdownT) Less(i, j int) bool
- func (d *DropdownT) RemoveAllAttrs() string
- func (d *DropdownT) RemoveAttrVal(k, v string) string
- func (d *DropdownT) Render(w io.Writer)
- func (d *DropdownT) RenderStr() string
- func (d *DropdownT) Select(selectKey string) string
- func (d *DropdownT) Selected() string
- func (d *DropdownT) SetAttr(k string, vi interface{}) string
- func (d *DropdownT) SetAutoSubmit(b bool) string
- func (d *DropdownT) SetDisabled(b bool) string
- func (d *DropdownT) SetName(s string) string
- func (d *DropdownT) SortOptionsByLabel()
- func (d *DropdownT) Swap(i, j int)
- type ErrorForward
- type GridBuilder
- type P
- type ParamT
- type Q
- type QuestionnaireT
- func (q *QuestionnaireT) AddFinishButtonNextToLast()
- func (q *QuestionnaireT) AddPage() *pageT
- func (q *QuestionnaireT) AddPageAfter(idx int) *pageT
- func (q *QuestionnaireT) AddPageIf() P
- func (q *QuestionnaireT) ByName(n string) *inputT
- func (q *QuestionnaireT) Compare(v *QuestionnaireT, lenient bool) (bool, error)
- func (q *QuestionnaireT) ComputeDynamicContent(idx int) error
- func (q *QuestionnaireT) ComputeMaxGroups()
- func (q *QuestionnaireT) CurrentPageHTML() (string, error)
- func (q *QuestionnaireT) DumpErrors()
- func (q *QuestionnaireT) DynamicPageValues(onlyThisIndex int) map[string]string
- func (q *QuestionnaireT) DynamicPages(onlyThisIndex int) error
- func (q *QuestionnaireT) DynamicPagesApplyValues(kv map[string]string) (hasContent bool)
- func (q *QuestionnaireT) EditPage(idx int) *pageT
- func (q *QuestionnaireT) EnumeratePages()
- func (q *QuestionnaireT) ErrByName(n string) (string, error)
- func (q *QuestionnaireT) FilePath1() string
- func (q *QuestionnaireT) FindNewPage(sess *sessx.SessT)
- func (q *QuestionnaireT) GetLangCode() string
- func (q QuestionnaireT) GroupHTMLGridBased(pageIdx, grpIdx int) string
- func (q QuestionnaireT) GroupHTMLTableBased(pageIdx, grpIdx int) string
- func (q *QuestionnaireT) HasComposit(pgIdx, grIdx int) ([]string, bool, error)
- func (q *QuestionnaireT) HasNext() bool
- func (q *QuestionnaireT) HasPrev() bool
- func (q *QuestionnaireT) Hyphenize()
- func (q QuestionnaireT) InputHTMLGrid(pageIdx, grpIdx, inpIdx int, langCode string) string
- func (q *QuestionnaireT) IsInNavigation(pageIdx int) bool
- func (q *QuestionnaireT) Join(q2 *QuestionnaireT) error
- func (q *QuestionnaireT) KeysValues(cleanse bool, getRangeInfo bool) (keys, vals, types, finishes []string)
- func (q *QuestionnaireT) LabelCleanse(s string) string
- func (q *QuestionnaireT) LabelIsOutline(s string) bool
- func (q *QuestionnaireT) LabelsByInputNames() (lblsByNames map[string]string, keys, lbls []string)
- func (q *QuestionnaireT) Next() int
- func (q *QuestionnaireT) NextNaviNum() string
- func (q *QuestionnaireT) PageHTML(pageIdx int) (string, error)
- func (q *QuestionnaireT) Prev() int
- func (q *QuestionnaireT) PrevNaviNum() string
- func (q *QuestionnaireT) PrevPage() (prevPage int)
- func (q *QuestionnaireT) ProgressBar() string
- func (q *QuestionnaireT) ProgressBarLine() string
- func (q *QuestionnaireT) RandomizeOrder(pageIdx int) []int
- func (q *QuestionnaireT) RenderJS(w io.Writer, fileName string, translations map[string]trl.S, ...)
- func (q *QuestionnaireT) ResponseByName(n string) (string, error)
- func (q *QuestionnaireT) Save1(fn string) error
- func (q *QuestionnaireT) SetColspans()
- func (q *QuestionnaireT) SetLangCode(newCode string) error
- func (q *QuestionnaireT) SiteSpecificTrl(key string) trl.S
- func (q *QuestionnaireT) Split() (*QuestionnaireT, error)
- func (q *QuestionnaireT) Statistics() (int, int, float64)
- func (q *QuestionnaireT) SuppressProgressBar() bool
- func (q *QuestionnaireT) TranslationCompleteness() error
- func (q *QuestionnaireT) UserIDInt() int
- func (q *QuestionnaireT) Validate() error
- func (q *QuestionnaireT) ValidateResponseData(pageNum int, langCode string) (last error, forward *ErrorForward)
- func (q *QuestionnaireT) Version() int
- type SurveyT
- func (s SurveyT) Filename() string
- func (s *SurveyT) HTMLForm(questTypes []string, errStr string) string
- func (s SurveyT) MonthOfQuarter() int
- func (s *SurveyT) Param(name string) (string, error)
- func (s SurveyT) Quarter(offs ...int) string
- func (s SurveyT) String() string
- func (s SurveyT) TemplateLogoText(langCode string) template.HTML
- func (s SurveyT) WaveID() string
- func (s SurveyT) WaveIDPretty() string
- func (s SurveyT) YearStr(offs ...int) string
- type WrappedPageT
- func (p WrappedPageT) AddBiiiPrio(mainLbl trl.S, labels []trl.S, names []string, idxOther map[int]bool, ...) *groupT
- func (p WrappedPageT) AddBiiiPrio2Cols(mainLbl trl.S, labels []trl.S, names []string, idxOther map[int]bool) *groupT
- func (p WrappedPageT) AddGrid(gb *GridBuilder) *groupT
- func (p WrappedPageT) AddGroup() *groupT
- func (page WrappedPageT) ConsolidateRadioErrors(grpOrder []int)
- func (p WrappedPageT) RedirectFuncExec(q *QuestionnaireT, w http.ResponseWriter, r *http.Request) error
- func (p WrappedPageT) SetSection(s trl.S)
- func (p WrappedPageT) WidthDefault()
- func (p WrappedPageT) WidthMax(s string)
Constants ¶
const ( // ValSet is returned, if the checkbox was checked ValSet = "1" // RemainOpen is a value for the HTML option input 'finished' RemainOpen = "remain-open" // Finished is a value for the HTML option input 'finished' Finished = "qst-finished" )
const ( // HLeft encodes left horizontal alignment HLeft = horizontalAlignment(0) // HCenter encodes centered horizontal alignment HCenter = horizontalAlignment(1) // HRight encodes right horizontal alignment HRight = horizontalAlignment(2) )
Variables ¶
var CompositeFuncs = map[string]CompositeFuncT{ "PoliticalFoundationsPretext": cppat.PoliticalFoundationsPretext, "PoliticalFoundations": cppat.PoliticalFoundations, "PoliticalFoundationsStatic": cppat.PoliticalFoundationsStatic, "PoliticalFoundationsComprehensionCheck": cppat.PoliticalFoundationsComprehensionCheck, "TimePreferenceSelf": cppat.TimePreferenceSelf, "TimePreferenceSelfStatic": cppat.TimePreferenceSelfStatic, "TimePreferenceSelfComprehensionCheck": cppat.TimePreferenceSelfComprehensionCheck, "GroupPreferences": cppat.GroupPreferences, "GroupPreferencesPOP3": cppat.GroupPreferencesPOP3, "QuestForOrg": cpbiii.QuestForOrg, "Special202212Q3": cpfmt.Special202212Q3, "Special202303": cpfmt.Special202303, "Special202403QS1": cpfmt.Special202403QS1, "Special202403QS2": cpfmt.Special202403QS2, }
CompositeFuncs is a lookup map
var PDSAssetClassGlob = assetClass{ NameUnused: "acx_global", Prefix: "acx", Lbl: trl.S{ "en": "Global", "de": "Global", }, Short: trl.S{ "de": "Global", "en": "Global", }, TrancheTypes: []trancheType{ { Prefix: "ac1", Lbl: trl.S{ "en": "Corporate Direct Lending", "de": "Corporate Direct Lending", }, }, { Prefix: "ac2", Lbl: trl.S{ "en": "European Real Estate Debt", "de": "European Real Estate Debt", }, }, { Prefix: "ac3", Lbl: trl.S{ "en": "European Infrastructure Debt", "de": "European Infrastructure Debt", }, }, }, }
PDSAssetClassGlob
var PDSAssetClasses = []assetClass{ { NameUnused: "ac1_corplending", Prefix: "ac1", LblOld: trl.S{ "en": "Corporate Direct Lending", "de": "Corporate Direct Lending", }, Lbl: trl.S{ "en": "European Corporate Direct Lending", "de": "European Corporate Direct Lending", }, Short: trl.S{ "en": "Corporate<br>Direct Lending", "de": "Corporate<br>Direct Lending", }, TrancheTypes: []trancheType{ { NameUnused: "tt1_senior", Prefix: "tt1", Lbl: trl.S{ "en": "Senior", "de": "Senior", }, }, { NameUnused: "tt2_unittranche", Prefix: "tt2", Lbl: trl.S{ "en": "Uni­tranche ", "de": "Uni­tranche ", }, }, { NameUnused: "tt3_subordinated", Prefix: "tt3", Lbl: trl.S{ "en": "Subordinated", "de": "Subordinated", }, }, }, }, { NameUnused: "ac2_realestate", Prefix: "ac2", Lbl: trl.S{ "en": "European Real Estate Debt", "de": "European Real Estate Debt", }, Short: trl.S{ "en": "Real Estate<br> Debt", "de": "Real Estate<br> Debt", }, TrancheTypes: []trancheType{ { NameUnused: "tt1_wholeloan", Prefix: "tt1", Lbl: trl.S{ "en": "Whole loan", "de": "Whole loan", }, }, { NameUnused: "tt2_subordinated", Prefix: "tt2", Lbl: trl.S{ "en": "Subordinated", "de": "Subordinated", }, }, }, }, { NameUnused: "ac3_infrastruct", Prefix: "ac3", Lbl: trl.S{ "en": "European Infrastructure Debt", "de": "European Infrastructure Debt", }, Short: trl.S{ "en": "Infrastructure <br> Debt", "de": "Infrastructure <br> Debt", }, TrancheTypes: []trancheType{ { NameUnused: "tt1_senior", Prefix: "tt1", Lbl: trl.S{ "en": "Senior", "de": "Senior", }, }, { NameUnused: "tt2_subordinated", Prefix: "tt2", Lbl: trl.S{ "en": "Subordinated", "de": "Subordinated", }, }, }, }, }
ultra short abbreviations would be
CDL / RED / ID
so far unused
var PDSLbls = map[string][]trl.S{
"teamsize": {
{
"en": "<5",
"de": "<5",
},
{
"en": "5-10",
"de": "5-10",
},
{
"en": "11-20",
"de": "11-20",
},
{
"en": ">20",
"de": ">20",
},
},
"relevance1-5": {
{
"en": "not rele­vant<br>(1)",
"de": "not rele­vant<br>(1)",
},
{
"en": "some­what<br>rele­vant<br>(2)",
"de": "some­what<br>rele­vant<br>(2)",
},
{
"en": "rele­vant<br>(3)",
"de": "rele­vant<br>(3)",
},
{
"en": "core prin­ciple<br>(4)",
"de": "core prin­ciple<br>(4)",
},
{
"en": "potential<br>deal­breaker<br>(5)",
"de": "potential<br>deal­breaker<br>(5)",
},
},
"improveDecline1-5-prev": {
{
"en": "bad ",
"de": "bad ",
},
{
"en": " ",
"de": " ",
},
{
"en": "satis­factory",
"de": "satis­factory",
},
{
"en": " ",
"de": " ",
},
{
"en": " good",
"de": " good",
},
},
"improveDecline1-5-prev-spec": {
{
"en": "bad ",
"de": "bad ",
},
{
"en": " ",
"de": " ",
},
{
"en": "not change",
"de": "not change",
},
{
"en": " ",
"de": " ",
},
{
"en": " good",
"de": " good",
},
},
"improveDecline1-5-next": {
{
"en": "will<br>de­cline",
"de": "will<br>de­cline",
},
{
"en": " ",
"de": " ",
},
{
"en": "not change",
"de": "not change",
},
{
"en": " ",
"de": " ",
},
{
"en": "will<br>im­prove",
"de": "will<br>im­prove",
},
},
"improveDecline1-5-next-2": {
{
"en": "<span style='font-size:90%'> will de­te­ri­o­rate </span>",
"de": "<span style='font-size:90%'> will de­te­ri­o­rate </span>",
},
{
"en": " ",
"de": " ",
},
{
"en": "not change",
"de": "not change",
},
{
"en": " ",
"de": " ",
},
{
"en": "will<br>im­prove",
"de": "will<br>im­prove",
},
},
"closing-time-weeks": {
{
"en": "<<br>4",
"de": "<<br>4",
},
{
"en": " <br>4‑8",
"de": " <br>4‑8",
},
{
"en": "weeks<br><br>8‑12",
"de": "weeks<br><br>8‑12",
},
{
"en": " <br>12‑16",
"de": " <br>12‑16",
},
{
"en": "><br>16",
"de": "><br>16",
},
},
"covenants-per-credit": {
{
"en": "0‑1",
"de": "0‑1",
},
{
"en": "2‑3",
"de": "2‑3",
},
{
"en": "4‑5",
"de": "4‑5",
},
{
"en": " >5",
"de": " >5",
},
},
}
Functions ¶
func AddStaticDynamicGroups ¶
func AddStaticDynamicGroups(page pageT)
AddStaticDynamicGroups adds five groups the second remains static, the others are randomized based on
func BIIILater ¶
func BIIILater(q *QuestionnaireT, pageIdx int) bool
func BIIIMeasure ¶
func BIIIMeasure(q *QuestionnaireT, pageIdx int) bool
func BIIINow ¶
func BIIINow(q *QuestionnaireT, pageIdx int) bool
func BasePath ¶
func BasePath() string
BasePath gives the 'root' for loading and saving questionnaire JSON files. Duplicate of lgn.basePath - cyclic dependencies
func CleanseUserAgent ¶
CleanseUserAgent is stricter than EnglishTextAndNumbersOnly
func DeadlineAndPublication ¶
func DeadlineAndPublication(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
DeadlineAndPublication
func DelocalizeNumber ¶
DelocalizeNumber removes localized number formatting; HTML5 input type number does not de-localize values; 123,456.78 is allowed - and so is 123.456,78; at least we have at most *one* dot and *one* comma; https://www.ryadel.com/en/html-input-type-number-with-localized-decimal-values-jquery/
func EnglishTextAndNumbersOnly ¶
EnglishTextAndNumbersOnly replaces all other UTF characters by space
func ErrorProxy ¶
func ErrorProxy(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
ErrorProxy - shows errors for inputs named like paramSet
func FederalStateAboveOrBelowMedian ¶
func FederalStateAboveOrBelowMedian(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
FederalStateAboveOrBelowMedian returns "besser" or "schlechter"; depending on the user's federal state education ranking
func GermanOnly ¶
func GermanOnly(q *QuestionnaireT, pageIdx int) bool
func LinkBack ¶
func LinkBack(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
LinkBack
func Mustaz09Underscore ¶
Mustaz09Underscore tests strings for a-z, 0-9, _
func NewInput ¶
func NewInput() inputT
NewInput returns an input filled in with globally enumerated label, decription etc.
func ParseJavaScript ¶
ParseJavaScript loads js file and embeds its contents into a <script> tag; so that parsing the template does not do harmful escaping;
would better belong into package tpl - but circular dependencies;
func PatLogos ¶
func PatLogos(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
PatLogos - only for the img src URLs
func PermaLink ¶
func PermaLink(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
PermaLink returns the perma link; only possible if the initial login was accomplished via direct login.
func PersonalLink ¶
func PersonalLink(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
PersonalLink is only a reminder, does not contain the personal link; see PermaLink
func RenderStaticContent ¶
func RenderStaticContent(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
RenderStaticContent - http request time display of a markdown file
func ResponseStatistics ¶
func ResponseStatistics(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
ResponseStatistics returns the percentage of answers responded to.
func ResponseTextHasEuro ¶
func ResponseTextHasEuro(q *QuestionnaireT, inp *inputT, paramSet string) (string, error)
ResponseTextHasEuro yields texts => want to keep € - want to have €
func UNUSEDpdsPage23 ¶
func UNUSEDpdsPage23(q *QuestionnaireT, page *pageT, acIdx int) error
Types ¶
type CompositeFuncT ¶
CompositeFuncT inputs combine challenging HTML and multiple inputs in complicated ways
Compare dynFuncT, validatorT ¶
A composite func returns dynamic HTML with session values inserted from the questionnaire A composite func also returns the input *names* for json generation of the questionnaire template
Matching is required for
returned input names input names in HTML form input names to query session values from *q argument
Parameters
dynamic questionnaire - filled with response values sequence idx - usually a visible page sequence number param set idx - statically determined - from a slice of param sets preflight - only return the input names for questionnaire generation; dont render HTML output
Returns
rendered HTML of the group slice of input names error
type DropdownT ¶
type DropdownT struct { Name string AutoSubmit bool // onchange this.Form.Submit() is suppressed Disabled bool // management of 'style' and 'class' HTML attributes Attrs map[template.HTMLAttr]template.HTMLAttr LC string // for rendering the labels inside the template below Options []optionT NameJavaScriptExpression template.JSStr `json:"-"` // helper }
DropdownT represents a HTML dropdown control Methods need to return a string, so we can use them in templates
func (*DropdownT) AddPleaseSelect ¶
AddPleaseSelect adds a default option at the top
func (*DropdownT) RemoveAllAttrs ¶
RemoveAllAttrs removes all attributes
func (*DropdownT) RemoveAttrVal ¶
RemoveAttrVal - removing the value in an attribute
func (*DropdownT) SetAutoSubmit ¶
SetAutoSubmit - for usage in templates
func (*DropdownT) SetDisabled ¶
SetDisabled - for usage in templates
func (*DropdownT) SortOptionsByLabel ¶
func (d *DropdownT) SortOptionsByLabel()
SortOptionsByLabel for quest generation time
type ErrorForward ¶
type ErrorForward struct {
// contains filtered or unexported fields
}
ErrorForward contains a markdown page or page id to jump to
func (ErrorForward) Error ¶
func (ef ErrorForward) Error() string
Error implements the errors.Error interface
func (ErrorForward) MarkDownPath ¶
func (ef ErrorForward) MarkDownPath() string
MarkDownPath returns the path to redirect to;
it should be renamed - since it might also contain absolute URLs
type GridBuilder ¶
type GridBuilder struct { MainLabel trl.S // first row - before column headers - as wide as the group CellTopLeft trl.S // contains filtered or unexported fields }
GridBuilder to generate a matrix or grid or table of labels and inputs; cells are stored column-wise - enforcing equal spans for label and control; columns together constitute a CSS-grid-column-template rendering is done row-wise;
func NewGridBuilderRadios ¶
func NewGridBuilderRadios( columnTemplate []float32, hdrLabels []trl.S, inputNames []string, radioVals []string, firstColLabels []trl.S, ) *GridBuilder
NewGridBuilderRadios - see NewGridBuilderRadiosWithValidator
firstColLabels only appear, if columnTemplate has space > 0 for them
func NewGridBuilderRadiosWithValidator ¶
func NewGridBuilderRadiosWithValidator( columnTemplate []float32, hdrLabels []trl.S, inputNames []string, radioVals []string, firstColLabels []trl.S, Validator string, ) *GridBuilder
NewGridBuilderRadiosWithValidator uses GridBuilder.AddCol() and GridBuilder.AddRadioRow() to compile a matrix of cells; basically, each cell can contain input names, input values and input labels
firstColLabels can be nil
func (*GridBuilder) AddCol ¶
func (gb *GridBuilder) AddCol(headerCell trl.S, spanLabel, spanControl float32)
AddCol adds a column; to the grid builder template
func (*GridBuilder) AddRadioRow ¶
AddRadioRow adds a row radio inputs - empty columns are filled with empty text; sparse labels allows to set labels for selected columns only; often only the first columns has a label
type P ¶
type P interface { // Setters, and some getters for every struct field are required. // We could use reflection: // // SetField(name string, value interface{}) // // sacrificing type safety. // // We could use AST code generation to // create setters and getters like in Java. // => 15 pairs for pageT // => 25 pairs for inputT SetSection(trl.S) WidthMax(string) // setting max width }
type ParamT ¶
type ParamT struct { Name string `json:"name,omitempty"` // i.e. main_refinance_rate_ecb Val string `json:"val,omitempty"` // i.e. "0,5%" }
ParamT contains changing parameters to a questionnaire
type Q ¶
type Q interface { // Questionnaire level UserIDInt() int Version() int GetLangCode() string // AddPage() *pageT AddPageIf() P ResponseByName(n string) (string, error) ErrByName(n string) (string, error) }
Q decouples
type QuestionnaireT ¶
type QuestionnaireT struct { Survey SurveyT `json:"survey,omitempty"` UserID string `json:"user_id,omitempty"` // participant ID, decimal, but string, i.E. 1011 // Attrs are user specific key-value pairs - // i.e. user country or euro-member // whereas surveyT.Params are specific to the survey + wave // Attrs survey ID and wave ID and lang code come from login; // additional Attrs come from cfg.Profiles - mediated by login `p` parameter // // key 'survey_variant' loads distinct questionnaire templates // // Attrs are dynamically replaced // attr-country Attrs map[string]string `json:"user_attrs,omitempty"` // if any response key "finished" equals qst.Finished // this is set to time.Now() - truncated to second // it is the marker for preventing any more edits ClosingTime time.Time `json:"closing_time,omitempty"` RemoteIP string `json:"remote_ip,omitempty"` UserAgent string `json:"user_agent,omitempty"` MD5 string `json:"md_5,omitempty"` LangCodes []string `json:"lang_codes,omitempty"` // default, order and availability - [en, de, ...] or [de, en, ...] LangCode string `json:"lang_code,omitempty"` // current lang code - i.e. 'de' - session key lang_code CurrPage int `json:"curr_page,omitempty"` HasErrors bool `json:"has_errors,omitempty"` // If any response is faulty; set by ValidateReponseData // ShufflingVariations indicated how many different reshufflings occur; // until repetition; primitive permutation mechanism; // deterministically reordering / reshuffling a set of groups // based on // * user id // * groupT.RandomizationSeed // // page idx is no longer relevant // groupT.RandomizationGroup is only to distinguish multiple groups per page ShufflingVariations int `json:"shuffling_variations,omitempty"` ShufflingRepetitions int `json:"shuffling_repetitions,omitempty"` // if equals 0, then defaults to three; usually you dont have to touch this value // PreventSkipForward - skipping back always possible, // skipping forward is preventable PreventSkipForward bool `json:"allow_skip_forward"` PostponeNavigationButtons int `json:"postpone_navigation_buttons,omitempty"` // Previously we had SurveyT.Variant; now all questionnaire variations // should be captured with a distinct VersionEffective. // Notice the difference to tpl.SiteCore(); // tpl.SiteCore() yields a common *style* identifier // for completely different questionnaires VersionMax int `json:"version_max,omitempty"` // total number of versions - usually permutations AssignVersion string `json:"assign_version,omitempty"` // default is UserID modulo VerionMax - other value is "round-robin" based on in memory atomic counter VersionEffective int `json:"version_effective"` // zero based, result of q.Version() - intended for read access - written on first call of q.Version() - can be reset with to -2 MaxGroups int `json:"max_groups,omitempty"` // Max number of groups - a helper value - computed during questionnaire creation - previously used for shuffing of groups. Pages []*pageT `json:"pages,omitempty"` }
QuestionnaireT contains pages with groups with inputs
func FromSession ¶
FromSession loads a graph from session; second return value contains 'is set'.
func Load1 ¶
func Load1(fn string) (*QuestionnaireT, error)
Load1 loads a questionnaire from a JSON file. On error returns completely empty Questionnaire
func (*QuestionnaireT) AddFinishButtonNextToLast ¶
func (q *QuestionnaireT) AddFinishButtonNextToLast()
AddFinishButtonNextToLast from page
Adding explicit button to finish page, which is outsite navigation. Button is added to the next-to-last page. Call this method at the end of page insertions.
func (*QuestionnaireT) AddPage ¶
func (q *QuestionnaireT) AddPage() *pageT
AddPage creates a new page and adds this page to the questionnaire's pages
func (*QuestionnaireT) AddPageAfter ¶
func (q *QuestionnaireT) AddPageAfter(idx int) *pageT
AddPageAfter creates a new page and adds this page to the questionnaire's pages
func (*QuestionnaireT) AddPageIf ¶
func (q *QuestionnaireT) AddPageIf() P
AddPageIf like AddPage compare WrapPage
func (*QuestionnaireT) ByName ¶
func (q *QuestionnaireT) ByName(n string) *inputT
ByName retrieves an input element by name. Returns nil if the input element was not found.
func (*QuestionnaireT) Compare ¶
func (q *QuestionnaireT) Compare(v *QuestionnaireT, lenient bool) (bool, error)
Compare compares page completion times and input responses. Compare stops with the first difference and returns an error.
func (*QuestionnaireT) ComputeDynamicContent ¶
func (q *QuestionnaireT) ComputeDynamicContent(idx int) error
ComputeDynamicContent computes elements of type dynamic func
func (*QuestionnaireT) ComputeMaxGroups ¶
func (q *QuestionnaireT) ComputeMaxGroups()
ComputeMaxGroups computes the maximum number of groups and puts them into q.MaxGroups
func (*QuestionnaireT) CurrentPageHTML ¶
func (q *QuestionnaireT) CurrentPageHTML() (string, error)
CurrentPageHTML is a comfort shortcut to PageHTML called in html template
func (*QuestionnaireT) DumpErrors ¶
func (q *QuestionnaireT) DumpErrors()
DumpErrors logs all ErrMsgs from the questionnaire
func (*QuestionnaireT) DynamicPageValues ¶
func (q *QuestionnaireT) DynamicPageValues(onlyThisIndex int) map[string]string
func (*QuestionnaireT) DynamicPages ¶
func (q *QuestionnaireT) DynamicPages(onlyThisIndex int) error
DynamicPages dynamically re-creates groups and inputs based on conditions like q.UserID or values from other pages;
there are three issues integrating this method with the Join() method:
- the structure depends on user input from other pages - we must call Join() first
- Join() will see distinct structures for groups/inputs between base (empty) and split (previously entered data) - we coded an exception
- DynamicPages() will now create re-groups and _empty_ inputs
- We now pull _previous_ dynamic page values (qSplit.DynamicPageValues) and apply them to the joined questionnaire
We have to do a similar thing in PageHTML() because conditional values in other forms may have changed
func (*QuestionnaireT) DynamicPagesApplyValues ¶
func (q *QuestionnaireT) DynamicPagesApplyValues(kv map[string]string) (hasContent bool)
func (*QuestionnaireT) EditPage ¶
func (q *QuestionnaireT) EditPage(idx int) *pageT
EditPage returns page X compare WrapPage
func (*QuestionnaireT) EnumeratePages ¶
func (q *QuestionnaireT) EnumeratePages()
EnumeratePages allocates a sequence number based on IsInNavigation()
func (*QuestionnaireT) ErrByName ¶
func (q *QuestionnaireT) ErrByName(n string) (string, error)
ErrByName returns the error for an input name; implements qstif.Q
func (*QuestionnaireT) FilePath1 ¶
func (q *QuestionnaireT) FilePath1() string
FilePath1 returns the location of the questionnaire file. Similar to lgn.LoginT.QuestPath()
func (*QuestionnaireT) FindNewPage ¶
func (q *QuestionnaireT) FindNewPage(sess *sessx.SessT)
FindNewPage determines the new page
func (QuestionnaireT) GroupHTMLGridBased ¶
func (q QuestionnaireT) GroupHTMLGridBased(pageIdx, grpIdx int) string
GroupHTMLGridBased renders a group of inputs to grid based HTML
func (QuestionnaireT) GroupHTMLTableBased ¶
func (q QuestionnaireT) GroupHTMLTableBased(pageIdx, grpIdx int) string
GroupHTMLTableBased renders a group of inputs to GroupHTMLTableBased
func (*QuestionnaireT) HasComposit ¶
func (q *QuestionnaireT) HasComposit(pgIdx, grIdx int) ([]string, bool, error)
HasComposit - group contains composit element?
if yes, we retrieve its input names
func (*QuestionnaireT) HasNext ¶
func (q *QuestionnaireT) HasNext() bool
HasNext if a next page exists
func (*QuestionnaireT) HasPrev ¶
func (q *QuestionnaireT) HasPrev() bool
HasPrev if a previous page exists
func (*QuestionnaireT) Hyphenize ¶
func (q *QuestionnaireT) Hyphenize()
Hyphenize replaces "mittelfristig" with "mittel­fristig" for all labels and descriptions
func (QuestionnaireT) InputHTMLGrid ¶
func (q QuestionnaireT) InputHTMLGrid(pageIdx, grpIdx, inpIdx int, langCode string) string
InputHTMLGrid renders an input to HTML
func (*QuestionnaireT) IsInNavigation ¶
func (q *QuestionnaireT) IsInNavigation(pageIdx int) bool
IsInNavigation checks whether pageIdx is suitable as next or previous page and whether it should show up in progress bar
func (*QuestionnaireT) Join ¶
func (q *QuestionnaireT) Join(q2 *QuestionnaireT) error
Join adds user input from q2 onto q
func (*QuestionnaireT) KeysValues ¶
func (q *QuestionnaireT) KeysValues(cleanse bool, getRangeInfo bool) (keys, vals, types, finishes []string)
KeysValues returns all pages finish times; keys and values in defined order. Empty values are also returned. Major purpose is CSV export across several questionnaires. Does deduplicate radio fieldnames, since they have the same value.
func (*QuestionnaireT) LabelCleanse ¶
func (q *QuestionnaireT) LabelCleanse(s string) string
LabelCleanse removes some common HTML stuff; argument q is not yet used
func (*QuestionnaireT) LabelIsOutline ¶
func (q *QuestionnaireT) LabelIsOutline(s string) bool
LabelIsOutline - if s starts with some outline see unit test
func (*QuestionnaireT) LabelsByInputNames ¶
func (q *QuestionnaireT) LabelsByInputNames() (lblsByNames map[string]string, keys, lbls []string)
LabelsByInputNames extracts the label texts for each input; starting from the input to the top; since there is a lot of summarized labeling for multiple inputs, we have no clear relationship; for each input, we traverse up on the page collecting all text until we hit a piece of text which is an outline number.
If no limiting outline number is found, text is concatenated all the way up to the start of the page.
functions cleanseIdentical(...) and cleansePrefixes(...) are used to clear out redundancies; see documentation.
func (*QuestionnaireT) Next ¶
func (q *QuestionnaireT) Next() int
Next returns index of the next page
func (*QuestionnaireT) NextNaviNum ¶
func (q *QuestionnaireT) NextNaviNum() string
NextNaviNum returns navigational number of the next page
func (*QuestionnaireT) PageHTML ¶
func (q *QuestionnaireT) PageHTML(pageIdx int) (string, error)
PageHTML generates HTML for a specific page of the questionnaire
func (*QuestionnaireT) Prev ¶
func (q *QuestionnaireT) Prev() int
Prev returns index of the previous page
func (*QuestionnaireT) PrevNaviNum ¶
func (q *QuestionnaireT) PrevNaviNum() string
PrevNaviNum returns navigational number of the prev page
func (*QuestionnaireT) PrevPage ¶
func (q *QuestionnaireT) PrevPage() (prevPage int)
PrevPage computation; q contains currPage from *last* request; we remember this, because we want to store request values *there*
func (*QuestionnaireT) ProgressBar ¶
func (q *QuestionnaireT) ProgressBar() string
ProgressBar generates a discrete position indicator https://fribly.com/2015/01/01/scalable-responsive-progress-bar/
It should be clickable and jump to the indicated page. This means, we have to submit the form and submit the destination page. Compare MenuMobile()
func (*QuestionnaireT) ProgressBarLine ¶
func (q *QuestionnaireT) ProgressBarLine() string
func (*QuestionnaireT) RandomizeOrder ¶
func (q *QuestionnaireT) RandomizeOrder(pageIdx int) []int
RandomizeOrder creates a shuffled ordering of groups determined by UserID and .RandomizationGroup; groups with RandomizationGroup==0 retain their position on fixed order position; others get a randomized position
func (*QuestionnaireT) RenderJS ¶
func (q *QuestionnaireT) RenderJS( w io.Writer, fileName string, translations map[string]trl.S, jsStrings map[string]string, )
RenderJS prints the contents of a JavaScript template into the HTML response; used for page level JavaScript blocks; used also for inputs of type 'javascript-block'
func (*QuestionnaireT) ResponseByName ¶
func (q *QuestionnaireT) ResponseByName(n string) (string, error)
ResponseByName implements qstif.Q
func (*QuestionnaireT) Save1 ¶
func (q *QuestionnaireT) Save1(fn string) error
Save1 a questionnaire to JSON
func (*QuestionnaireT) SetColspans ¶
func (q *QuestionnaireT) SetColspans()
func (*QuestionnaireT) SetLangCode ¶
func (q *QuestionnaireT) SetLangCode(newCode string) error
SetLangCode tries to change the questionnaire langCode if supported by langCodes.
func (*QuestionnaireT) SiteSpecificTrl ¶
func (q *QuestionnaireT) SiteSpecificTrl(key string) trl.S
SiteSpecificTrl returns a survey type or site specific configuration resource string. Compare cfg.ConfigT.SiteSpecificTrl and its usage in templates: {{ cfg.SiteSpecificTrl ...
func (*QuestionnaireT) Split ¶
func (q *QuestionnaireT) Split() (*QuestionnaireT, error)
Split creates a copy of q containing only the user responses and q metadata
func (*QuestionnaireT) Statistics ¶
func (q *QuestionnaireT) Statistics() (int, int, float64)
Statistics returns the percentage of answers responded to. It is helper to ResponseStatistics().
func (*QuestionnaireT) SuppressProgressBar ¶
func (q *QuestionnaireT) SuppressProgressBar() bool
SuppressProgressBar - dont show progress bar in current page; while back/forth buttons may still be rendered convenience func for templates;
func (*QuestionnaireT) TranslationCompleteness ¶
func (q *QuestionnaireT) TranslationCompleteness() error
TranslationCompleteness tests all multilanguage strings for completeness. Use only at JSON creation time, since dynamic elements have only one language.
func (*QuestionnaireT) UserIDInt ¶
func (q *QuestionnaireT) UserIDInt() int
UserIDInt retrieves the userID as int. For dynamic questionaires - use q.Version().
func (*QuestionnaireT) Validate ¶
func (q *QuestionnaireT) Validate() error
Validate performs integrity tests on a static base questionnaire. Validate should be run for every JSON load operation.
Checks performed:
waveId, langCodes valid input names uniqueness input type valid submit button jump page exists validator func exists
Validate also does some initialization stuff. This is needed only at JSON creation time.
Setting page and group width to 100 Setting values for radiogroups Setting navigation sequence enumeration values
Compare funcs above, which are only called on JSON creation time and for DynamicPages()
func (*QuestionnaireT) ValidateResponseData ¶
func (q *QuestionnaireT) ValidateResponseData(pageNum int, langCode string) (last error, forward *ErrorForward)
ValidateResponseData applies all input validation rules on the responses. Restricted by page, since validation errors are handled page-wise. Errors are collected for groups of inputs and stored into those group's errorProxy. The last error is returned. If any validation demands a HTTP forwarding, then the second return value contains the URL
func (*QuestionnaireT) Version ¶
func (q *QuestionnaireT) Version() int
Version sets and returns the questionnaire's version; default - version depends on user ID 'round-robin' - version depends on login order 'version-from-login-url' - version depends parameter v=[xx] during login
Version() is idempotent - once it is set to greater zero, this value remains Version() called first when a new QuestionaireT is loaded from a JSON base file. Version() can be recomputed if q.VersionEffective has been set to -1 before
type SurveyT ¶
type SurveyT struct { Type string `json:"type,omitempty"` // The type identifier, i.e. "fmt" or "cep" Org trl.S `json:"org,omitempty"` // organization, i.e. Unicef Name trl.S `json:"name,omitempty"` // full name, i.e. programming languages survey Year int `json:"year,omitempty"` // The wave year Month time.Month `json:"month,omitempty"` // The wave month, 1-based, int Deadline time.Time `json:"deadline,omitempty"` // No more responses accepted Params []ParamT `json:"params,omitempty"` // I.e. NASDAQ at the time begin of the wave - being used in the wording of the questions }
SurveyT stores the interval components of a questionnaire wave. For quarterly intervals, it needs to be extended
func (SurveyT) MonthOfQuarter ¶
MonthOfQuarter returns 1 for Jan, 2 for Feb, 3 for March; 1 for April
func (SurveyT) Quarter ¶
General rule: Ask for the forecast for the *current* quarter.
Exception: If previous quarter growth numbers were not yet published by Statistisches Bundesamt, then ask for previous quarter.
You find out by calling <https://www.destatis.de/SiteGlobals/Forms/Suche/Termine/DE/Terminsuche_Formular.html?startDate_dt=2021-06-30T22%3A00%3A00Z&cl2Taxonomies_Themen_0=volkswirtschaftliche_gesamtrechnungen_inlandsprodukt> or searching for "volkswirtschaftliche gesamtrechnungen inlandsprodukt" Also <https://www.finanzen.net/konjunktur/bruttoinlandsprodukt>
This exception usually applies in the first month of the current quarter. => set questionnaire survey parameter destatis to -1
Quarter yields quarter plus year; based on the survey month; offset adds/subtracts to/from quarter; overflowing over 4; underflowing under 1
January of 0 - => Q1 0
January of 2021 - => Q1 2021 January of 2021 - plus 1 Quarter => Q2 2021 January of 2021 - plus 3 Quarters => Q4 2021 January of 2021 - plus 4 Quarters => Q1 2022 January of 2021 - plus 5 Quarters => Q2 2022 March of 0 - => Q1 0 March of 2021 - => Q1 2021 March of 2021 - plus 1 Quarter => Q2 2021 March of 2021 - plus 3 Quarters => Q4 2021 March of 2021 - plus 4 Quarters => Q1 2022 April of 2021 - => Q2 2021 April of 2021 - plus 1 Quarter => Q3 2021 April of 2021 - plus 3 Quarters => Q1 2022 April of 2021 - plus 4 Quarters => Q2 2022 October of 2021 - => Q4 2021 October of 2021 - plus 1 Quarter => Q1 2022 October of 2021 - plus 4 Quarters => Q4 2022 October of 2021 - plus 1 Quarter => Q2 2024 December of 2021 - => Q4 2021 December of 2021 - plus 1 Quarter => Q1 2022 December of 2021 - plus 4 Quarters => Q4 2022 December of 2021 - plus 1 Quarter => Q2 2024 January of 2021 - minus 1 Quarter => Q4 2020 March of 2021 - minus 1 Quarter => Q4 2020 April of 2021 - minus 1 Quarter => Q1 2021 January of 2021 - minus 4 Quarters => Q1 2020 January of 2021 - minus 5 Quarters => Q4 2019
func (SurveyT) TemplateLogoText ¶
TemplateLogoText for display in HTML
func (SurveyT) WaveIDPretty ¶
WaveIDPretty is empty, if we dont have proper year, otherwise like WaveID()
type WrappedPageT ¶
type WrappedPageT struct {
// contains filtered or unexported fields
}
WrappedPageT for creating helper funcs outside the package - *temporarily*. compare EditPage
func (WrappedPageT) AddBiiiPrio ¶
func (p WrappedPageT) AddBiiiPrio( mainLbl trl.S, labels []trl.S, names []string, idxOther map[int]bool, showFreeInput int, ) *groupT
AddBiiiPrio question block
func (WrappedPageT) AddBiiiPrio2Cols ¶
func (p WrappedPageT) AddBiiiPrio2Cols( mainLbl trl.S, labels []trl.S, names []string, idxOther map[int]bool, ) *groupT
AddBiiiPrio question block
func (WrappedPageT) AddGrid ¶
func (p WrappedPageT) AddGrid(gb *GridBuilder) *groupT
AddGrid statically adds inputs to the page; these inputs are based on the preconfigured GridBuilder's cells
func (WrappedPageT) AddGroup ¶
func (p WrappedPageT) AddGroup() *groupT
AddGroup creates a new group and adds this group to the pages's groups
func (WrappedPageT) ConsolidateRadioErrors ¶
func (page WrappedPageT) ConsolidateRadioErrors(grpOrder []int)
ConsolidateRadioErrors removes repeating error messages from radio inputs
func (WrappedPageT) RedirectFuncExec ¶
func (p WrappedPageT) RedirectFuncExec(q *QuestionnaireT, w http.ResponseWriter, r *http.Request) error
RedirectFuncExec replaces the ErrorForward design
func (WrappedPageT) SetSection ¶
SetSection corresponds to the struct field Section. Setters, and some getters for every struct field required
func (WrappedPageT) WidthDefault ¶
func (p WrappedPageT) WidthDefault()
WidthDefault is called for every page - setting auto margins
Source Files ¶
- constants.go
- dropdown.go
- funcs-composite.go
- funcs-dynamic.go
- funcs-navigation.go
- funcs-page-fmt-202212.go
- funcs-page-fmt-202312.go
- funcs-page-fmt-202402.go
- funcs-page-fmt-202405.go
- funcs-page-kneb-202306-guidedtour.go
- funcs-page-kneb-202306-simtool.go
- funcs-page-pds-config.go
- funcs-page-pds-config1-restr-text.go
- funcs-page-pds-config2-multiple-ch.go
- funcs-page-pds-config3-slider.go
- funcs-page-pds-disable-cols.go
- funcs-page-pds-func1.go
- funcs-page-pds-func2.go
- funcs-page-pds-func3.go
- funcs-page-pds-func3a.go
- funcs-page-pds-func3b.go
- funcs-page-pds-func3c.go
- funcs-page-pds-func4.go
- funcs-page-pds-func41.go
- funcs-page-pds-func42.go
- funcs-page-pds-p11.go
- funcs-page-pds-p12.go
- funcs-page-pds-p21.go
- funcs-page-pds-p23.go
- funcs-page-pds-p3.go
- funcs-page-pds-p3x.go
- funcs-page-pds-p4.go
- funcs-page-pds-p4x.go
- funcs-page.go
- funcs-redirect.go
- funcs-server-validation.go
- interface.go
- load-save.go
- progress-bar.go
- questionnaire-grid.go
- questionnaire.go
- split-join.go
- static-builder-biii.go
- static-builders-grid-builder.go
- static-validate-struct.go
- survey.go
- test-group-randomizaton.go