Skip to content
Snippets Groups Projects
Commit 6677057d authored by Eliott Sammier's avatar Eliott Sammier
Browse files

Add open gap-fill type, with example

parent 7cb614e4
No related branches found
No related tags found
No related merge requests found
/**
* Custom SurveyJS question type for a "fill-in-the-gaps" text,
* with an open-ended text input for each gap
*/
export const gapfillOpenWidget = {
name: "gapfill-open",
title: "Gap-Fill Text (Open)",
/**
* This function should return true when the widget and all needed resources
* are loaded
*/
widgetIsLoaded: function () {
return true;
},
/**
* This function should return true if the widget should be applied to the question */
isFit: function (question) {
return question.getType() === this.name;
},
init() {
//Register a new type using the empty question as the base.
Survey.Serializer.addClass(this.name, [], null, "empty");
},
/** Static HTML template rendered by SurveyJS */
htmlTemplate: '<p id="gapfill-container"><template id="template-gap"><input type="text" class="sd-input inline-input"/></template></p>',
/**
* Function called after the HTML template is rendered. This time we actually have the `question` object
* and the `el` element, to build the question according to the JSON
*/
afterRender: function (question, el) {
// The gap-fill text is made of segments, which are either plain pieces
// of text (strings) or "gaps" (objects).
// We append these to build the text, turning strings into <span>s and
// gaps into <input> text fields
let nbGaps = 0;
const segmentElems = new DocumentFragment(); // a bit faster than mutating the DOM all the time
const gapTemplate = document.getElementById("template-gap").content.firstChild;
for (const segment of question.jsonObj.segments) {
let segmentElem;
if (typeof segment === 'string' || segment instanceof String) {
segmentElem = document.createElement("span");
segmentElem.innerText = segment;
} else {
// It's a gap
// Create the <input> element
segmentElem = gapTemplate.cloneNode(true);
segmentElem.setAttribute("data-index", nbGaps); // The node knows its index
// Add listener to update the question's value when the input value changes
segmentElem.addEventListener("change", (e) => {
// The input node knows its index, therefore is able to update the question value at the correct index
question.value[parseInt(e.target.getAttribute("data-index"))] = e.target.value;
});
nbGaps++;
}
// Add segment
segmentElems.appendChild(segmentElem);
}
// Initialize question value array
question.value = new Array(nbGaps);
// Finally add everything to the DOM
el.appendChild(segmentElems);
},
};
\ No newline at end of file
import {json} from "./json.js"
import {gapfillSelectWidget} from "./gapfill-select.js";
import {gapfillOpenWidget} from "./gapfill-open.js";
window.addEventListener('load', main)
function main() {
// Register our custom question types
Survey.CustomWidgetCollection.Instance.add(gapfillSelectWidget, gapfillSelectWidget.name);
Survey.CustomWidgetCollection.Instance.add(gapfillOpenWidget, gapfillOpenWidget.name);
let survey = new Survey.Model(json);
......
......@@ -2,7 +2,7 @@ export const json = {
elements: [
{
type: "gapfill-select",
name: "pg20",
name: "q1",
title: "The greatest song in the world",
segments: [
"🎶\nWe're no strangers to ",
......@@ -37,6 +37,16 @@ export const json = {
"run around",
"desert"
]
},
{
type: "gapfill-open",
name: "q2",
title: "Open-ended gapfill",
segments: [
"Lorem ",
{},
" dolor sit amet [...]"
], correctAnswer: ["ipsum"]
}
]
};
\ No newline at end of file
......@@ -8,7 +8,7 @@ p#gapfill-container {
white-space: pre-wrap;
line-height: 3em;
}
select.sd-dropdown.inline-dropdown {
select.sd-dropdown.inline-dropdown, input.sd-input.inline-input {
display: inline-block;
width: fit-content;
padding: 8px;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment