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

Move custom widget to separate file

The goal is eventually to regroup custom widgets in their own repo to contribute to SurveyJS
parent 3018e1c5
Branches
No related tags found
No related merge requests found
/**
* Custom SurveyJS question type for a "fill-in-the-gaps" text,
* with a drop-down selection of choices for each
*/
export const gapfillSelectWidget = {
name: "gapfill-select",
title: "Gap-Fill Text (Select)",
/**
* 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-select"><select class="sd-input sd-dropdown inline-dropdown"><option selected/></select></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" with a few options to select (string arrays).
// We append these to build the text, turning strings into <span>s and
// gaps into <select> dropdowns
let nbGaps = 0;
const segmentElems = new DocumentFragment(); // a bit faster than mutating the DOM all the time
const selectTemplate = document.getElementById("template-select").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 if (segment instanceof Array) {
// It's a gap
// Create the <select> element
segmentElem = selectTemplate.cloneNode(true);
segmentElem.setAttribute("data-index", nbGaps); // The node knows its index
// Create and append options
for (const opt of segment) {
let optionElem = document.createElement("option");
optionElem.innerText = opt;
segmentElem.appendChild(optionElem);
}
// Add listener to update the question's value when the selector's value changes
segmentElem.addEventListener("change", (e) => {
// The select 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
/**
* Custom widget for "fill-in-the-gaps" question type
*/
let gapfillSelectWidget = {
name: "gapfill-select",
title: "Gap-Fill Text (Select)",
/**
* 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) {
console.log("isFit?", 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-select"><select class="sd-input sd-dropdown inline-dropdown"><option selected/></select></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" with a few options to select (string arrays).
// We append these to build the text, turning strings into <span>s and
// gaps into <select> dropdowns
let nbGaps = 0;
let segmentElems = new DocumentFragment(); // a bit faster than mutating the DOM all the time
let selectTemplate = document.getElementById("template-select").content.firstChild;
for (segment of question.jsonObj.segments) {
if (typeof segment === 'string' || segment instanceof String) {
segmentElem = document.createElement("span");
segmentElem.innerText = segment;
} else if (segment instanceof Array) {
// It's a gap
// Create the <select> element
segmentElem = selectTemplate.cloneNode(true);
segmentElem.setAttribute("data-index", nbGaps); // The node knows its index
// Create and append options
for (opt of segment) {
optionElem = document.createElement("option");
optionElem.innerText = opt;
segmentElem.appendChild(optionElem);
}
// Add listener to update the question's value when the selector's value changes
segmentElem.addEventListener("change", (e) => {
// The select 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);
}
question.value = new Array(nbGaps);
// Finally add everything to the DOM
el.appendChild(segmentElems);
},
};
function showCorrectIndic(correct) {
indic = document.getElementById("correct-indic");
if (correct === undefined) {
......@@ -85,7 +16,7 @@ $(function () {
Survey.CustomWidgetCollection.Instance.add(gapfillSelectWidget, gapfillSelectWidget.name);
// Load survey model from JSON
survey = new Survey.Model(jsonStatic);
const survey = new Survey.Model(jsonStatic);
// Add "Check answers" button
survey.addNavigationItem({
......
......@@ -14,8 +14,12 @@
<script defer type="text/javascript"
src="https://unpkg.com/survey-core/themes/default-light-panelless.min.js"></script>
{{- $quizjs := resources.Get "quiz.js" -}}
<script defer type="text/javascript" src="{{- $quizjs.RelPermalink -}}"></script>
{{- $quizjs := slice -}}
{{- $quizjs = $quizjs | append (resources.Get "quiz.js") -}}
{{- $quizjs = $quizjs | append (resources.Get "gapfill-select.js") -}}
{{- $quizjs = $quizjs | resources.Concat "quiz.bundle.js" -}}
{{/* {{- $quizjs = $quizjs | resources.Minify -}}*/}}
<script type="module" src="{{- $quizjs.RelPermalink -}}"></script>
{{ end }}
{{ end }}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment