Basic Quest markup
In this section, we describe the basics of the markup. More complex markup is available, and a description can be found online in the Quest wiki.[6] In this section, italic text will be used to distinguish markup elements and their orchestration from the text describing them.
The basic markup structure for a questionnaire module is a series of questions. Questions are defined in the markup with a question id surrounded by square brackets followed by the question text and a set of responses. The first letter of a question id must be a capital letter (A-Z); the rest of the id can be capital letters, numbers, underscores, or octothorps (hash tags). Examples of valid question identifiers include [Q], [Q1], [Q#1], and [THIS_IS_VALID]. The final question uses the question id [END].
Question Syntax
As is the case for markup languages in general, the questions themselves are composed of plain text. The elements of each question are represented with simplified syntactic patterns mapped to another markup language, HTML. In essence, this follows the same rationale associated with other markup languages [3, 4]. Correspondingly, each question block consists of the question text and responses that can use a range of HTML form elements to handle different response types. The most common cases are select one of the responses or select multiple responses, which map into an HTML input type = radio or type = checkbox, respectively. The markup uses parentheses surrounding a value to represent a radio button and square brackets surrounding the return value for checkboxes. For the markup to remain consistent, return values cannot be valid question ids. A wide range of text and numeric input formats are supported, which are specified using a vertical bar followed by two underscores and another vertical bar, |__| for basic text values, while numeric input is specific by |__|__|. Other HTML element types can be specified using |date|, |tel|, and |SSN|. Quest’s GitHub wiki contains detailed information on additional response types. Advanced developers can also have responsive grids that display multiple questions with the same responses. An in-browser application is provided at https://episphere.github.io/quest where the questionnaire markup can be tested interactively during development.
Questionnaire logic
The markup logic includes simple and more complex syntax to allow for skip logic. The simple logic is the arrow markup: response -> question id. The arrow indicates that if this response is selected, go to the question with the given id. This simple logic allows the developer to skip parts of the module that are not applicable to the participant. The no response markup, < #NR -> question id>, can be used for cases when the user does not select one of the responses.
The arrow markup adds a question to a stack (last in, first out list) of questions that assembled for the participant. When the stack empty, next question is assumed to immediately follow the current question. However, questionnaire modules may include follow-up questions for situations when the participant can choose multiple responses. In this situation, each response may contain arrows pointing to the follow up questions, and a default next question, in which < -> question id > points to the next question after all the follow-up questions are answered by the participant. All selected responses with arrows are added to the question list along with the default next question. The default next question is always added to the stack. Care should be taken with follow up questions. All additional follow-up questions must specifically be added to the stack with an arrow or the default arrow, otherwise they will be ignored as the next question will come from the stack regardless of where it appears in the markup.
Finally, for questions that cannot be skipped by any other means, a displayif mechanism can skip a question based on previous results. This basic syntax will cover the most straightforward situations, but there are situations where complex logic requires a more functional representation than conditional event algebra. That expert level logic grammar allows, for example, the definition of loops within the module. This is explained in Quest’s wiki[6] in detail.
Figure 1 is a simple example of a questionnaire module using Quest markup. This example illustrates both the markup and its rendering by the reference application: the markup is available online as a text file at https://danielruss.github.io/questionnaire/paper_example1.txt.
Supporting software
We developed a JavaScript library as an open-source reference implementation that renders the Quest markup into HTML for display in a browser. The library follows the module logic found in the markup displaying the appropriate question based on current and past responses. The quest library can be inserted into a standard HTML page or progressive web application using a content delivery network that caches code on GitHub (e.g. https://cdn.jsdelivr.net/gh/episphere/quest/replace2.js ). Our implementation caches the entire module in the browser DOM, and participant responses are saved in the browser’s indexedDB, an asynchronous NoSQL persistent storage native to the modern browser [7]. Participants with spotty or intermittent internet capabilities can therefore complete modules even if they lose the internet connection. Finally, results are transmitted back to the study via a callback function executed upon completion of the module. To support different studies with different preferences for data backend, Quest itself does not specify how or where studies store results. That is instead defined by the JavaScript callback function, which receive as the input argument a JSON object populated by the responses to the questionnaire.
We also provide an application for developing and presenting the Quest markup, which provides the developer the same view of the questions as the participant. As mentioned in the Methods section, the markup development tool is available at https://episphere.github.io/quest.
Styling the appearance and user interaction is a major component of the Quest renderer, which we’ve approached by independently parameterizing a Cascade Style Sheet document (CSS). Naturally, if no style is defined, for example rendering the questionnaire in a web application, the styling will be that of the application itself. This mimetic design implies that a cohort study using Quest will render questionnaires with the appearance of being native to the overall presentation configured for the Web Application.