87 lines
3.0 KiB
JavaScript
87 lines
3.0 KiB
JavaScript
/* 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
|
|
};
|
|
}());
|