* fix: eslint operator-linebreak issue * fix: eslint quotes issue * fix: react jsx indent and props issues * fix: eslint trailing spaces issues * fix: eslint line around directives issue * fix: eslint semi rule * fix: eslint newline per chain rule * fix: eslint space infix ops rule * fix: eslint space-in-parens issue * fix: eslint space before function paren issue * fix: eslint space before blocks issue * fix: eslint arrow body style issue * fix: eslint dot-location issue * fix: eslint quotes issue * fix: eslint quote props issue * fix: eslint operator assignment issue * fix: eslint new line after import issue * fix: indent issues * fix: operator assignment issue * fix: all autofixable eslint issues * fix: all react related fixable issues * fix: autofixable eslint issues * chore: remove all template literals * fix: remaining autofixable issues * chore: apply amnesty on all existing issues * fix: failing xss-lint issues * refactor: apply amnesty on remaining issues * refactor: apply amnesty on new issues * fix: remove file level suppressions * refactor: apply amnesty on new issues
89 lines
3.0 KiB
JavaScript
89 lines
3.0 KiB
JavaScript
/* Original Source: https://files.edx.org/custom-js-example/jsinput_example.js */
|
|
|
|
/* globals Channel */
|
|
|
|
(function() {
|
|
'use strict';
|
|
|
|
// state will be populated via initial_state via the `setState` method. Defining dummy values here
|
|
// to make the expected structure clear.
|
|
var state = {
|
|
availableChoices: [],
|
|
selectedChoice: ''
|
|
},
|
|
channel,
|
|
select = document.getElementsByClassName('choices')[0],
|
|
feedback = document.getElementsByClassName('feedback')[0];
|
|
|
|
function populateSelect() {
|
|
// Populate the select from `state.availableChoices`.
|
|
var i, option;
|
|
|
|
// Clear out any pre-existing options.
|
|
while (select.firstChild) {
|
|
select.removeChild(select.firstChild);
|
|
}
|
|
|
|
// Populate the select with the available choices.
|
|
for (i = 0; i < state.availableChoices.length; i++) {
|
|
option = document.createElement('option');
|
|
option.value = i;
|
|
option.innerHTML = state.availableChoices[i];
|
|
if (state.availableChoices[i] === state.selectedChoice) {
|
|
option.selected = true;
|
|
}
|
|
select.appendChild(option);
|
|
}
|
|
feedback.innerText = "The currently selected answer is '" + state.selectedChoice + "'.";
|
|
}
|
|
|
|
function getGrade() {
|
|
// The following return value may or may not be used to grade server-side.
|
|
// If getState and setState are used, then the Python grader also gets access
|
|
// to the return value of getState and can choose it instead to grade.
|
|
return JSON.stringify(state.selectedChoice);
|
|
}
|
|
|
|
function getState() {
|
|
// Returns the current state (which can be used for grading).
|
|
return JSON.stringify(state);
|
|
}
|
|
|
|
// This function will be called with 1 argument when JSChannel is not used,
|
|
// 2 otherwise. In the latter case, the first argument is a transaction
|
|
// object that will not be used here
|
|
// (see http://mozilla.github.io/jschannel/docs/)
|
|
function setState() {
|
|
var stateString = arguments.length === 1 ? arguments[0] : arguments[1];
|
|
state = JSON.parse(stateString);
|
|
populateSelect();
|
|
}
|
|
|
|
// Establish a channel only if this application is embedded in an iframe.
|
|
// This will let the parent window communicate with this application using
|
|
// RPC and bypass SOP restrictions.
|
|
if (window.parent !== window) {
|
|
channel = Channel.build({
|
|
window: window.parent,
|
|
origin: '*',
|
|
scope: 'JSInput'
|
|
});
|
|
|
|
channel.bind('getGrade', getGrade);
|
|
channel.bind('getState', getState);
|
|
channel.bind('setState', setState);
|
|
}
|
|
|
|
select.addEventListener('change', function() {
|
|
state.selectedChoice = select.options[select.selectedIndex].text;
|
|
feedback.innerText = "You have selected '" + state.selectedChoice
|
|
+ "'. Click Submit to grade your answer.";
|
|
});
|
|
|
|
return {
|
|
getState: getState,
|
|
setState: setState,
|
|
getGrade: getGrade
|
|
};
|
|
}());
|