Last active
May 5, 2020 12:39
-
-
Save dcollien/3747293f5dc451d7c78ccdc2d6d081c8 to your computer and use it in GitHub Desktop.
xAPI iFrame Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<title>xAPI Form Example</title> | |
<!-- xAPI base functionality, from: https://github.com/RusticiSoftware/TinCanJS/blob/master/build/tincan-min.js --> | |
<script src="tincan-min.js"></script> | |
<!-- Setting up the xAPI connection from launch data --> | |
<script src="xapi-interface.js"></script> | |
<!-- Functionality for enabling form submission over xAPI --> | |
<script src="xapi-form-submit.js"></script> | |
</head> | |
<body> | |
<form id="dataform" > | |
<input type="text" name="testInput"/> | |
<input type="submit" value="Submit" id="submit-button"> | |
</div> | |
<divid="status-message"> | |
Form has been submitted. | |
</div> | |
</form> | |
<!-- Initialise functionality --> | |
<script> | |
// Find the status box labelled with the id "status" | |
var statusBox = document.getElementById("status-message"); | |
// Hide this box | |
statusBox.style.display = "none"; | |
// Find the form element labelled with the id "dataform" | |
var form = document.getElementById("dataform"); | |
// Find the submit button | |
var submitButton = document.getElementById("submit-button"); | |
// Function to run when the form is about to be submitted | |
var onSubmitStart = function(formData) { | |
// Hide the status box | |
statusBox.style.display = "none"; | |
// Disable the submit button | |
submitButton.disabled = true; | |
}; | |
// Function to run when the form has been submitted | |
var onSubmitComplete = function(error, formData, response) { | |
if (error) { | |
// Submission couldn't complete | |
// Show error message | |
alert("Unable to submit form. Try again later."); | |
console.log(error, formData, response); | |
} else { | |
// Submission succeeded | |
// Show the status box | |
statusBox.style.display = ""; | |
} | |
// Re-enable the submit button | |
submitButton.disabled = false; | |
}; | |
// Initialise the xAPI functionality and submit the data | |
// over xAPI when this form is submitted | |
initXApiForm(form, onSubmitStart, onSubmitComplete); | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var ADL_VERBS_ROOT = "http://adlnet.gov/expapi/verbs/"; | |
var OL_EXTENSIONS_ROOT = "https://xapi.openlearning.com/extensions/"; | |
var LRS_CONFIG = initLrs(); | |
function completedStatement(config, formData) { | |
var ol_extensions = {}; | |
ol_extensions[OL_EXTENSIONS_ROOT + "submission-data"] = formData; | |
return new TinCan.Statement({ | |
actor: config.actor, // the actor data sent by OpenLearning | |
object: { | |
id: config.activity_id, // the activity_id sent by OpenLearning | |
objectType: "Activity" | |
}, | |
context: { | |
registration: config.registration // the registration sent by OpenLearning | |
}, | |
verb: { | |
id: ADL_VERBS_ROOT + "completed", | |
display: { | |
"de-DE" : "beendete", | |
"en-US" : "completed", | |
"fr-FR" : "a terminé", | |
"es-ES" : "completó" | |
}, | |
}, | |
result: { | |
completion: true, | |
extensions: ol_extensions | |
} | |
}); | |
} | |
function formToObject(form) { | |
var formData = new FormData(form); | |
var object = {}; | |
formData.forEach(function(value, key) { | |
if (!object.hasOwnProperty(key)) { | |
object[key] = value; | |
return; | |
} | |
if (!Array.isArray(object[key])) { | |
object[key] = [object[key]]; | |
} | |
object[key].push(value); | |
}); | |
return object; | |
} | |
function submitFormObject(formObject) { | |
if (!LRS_CONFIG) { | |
return new Promise(function(resolve, reject) { | |
return reject({ | |
error: 'No LRS configured in the URL.', | |
xhr: null | |
}); | |
}); | |
} | |
var lrs = LRS_CONFIG.lrs; | |
var statement = completedStatement(LRS_CONFIG, formObject); | |
return saveStatement(lrs, statement); | |
} | |
function submitForm(form, startCallback, completeCallback) { | |
var formObject = formToObject(form); | |
startCallback(formObject); | |
submitFormObject(formObject).then( | |
function(xhr) { | |
completeCallback(null, formObject, xhr); | |
}, | |
function(errorResult) { | |
completeCallback(errorResult.error, formObject, errorResult.xhr); | |
} | |
); | |
} | |
function xApiFormSubmit(startCallback, completeCallback) { | |
return function(event) { | |
event.preventDefault(); | |
submitForm(event.currentTarget, startCallback, completeCallback); | |
}; | |
} | |
function initXApiForm(form, onSubmitStart, onSubmitComplete) { | |
form.addEventListener("submit", xApiFormSubmit(onSubmitStart, onSubmitComplete)); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function initLrs() { | |
// xAPI configuration is sent in the URL query string parameters | |
var urlParams = new URLSearchParams(window.location.search); | |
var endpoint = urlParams.get('endpoint'); | |
var auth = urlParams.get('auth'); | |
var actor = JSON.parse(urlParams.get('actor')); // this needs to be JSON decoded | |
var activity_id = urlParams.get('activity_id'); | |
var registration = urlParams.get('registration'); | |
if (!endpoint) { | |
return null; | |
} | |
var lrs = new TinCan.LRS({ | |
endpoint: endpoint, | |
auth: auth | |
}); | |
return { | |
"lrs": lrs, | |
"actor": actor, | |
"activity_id": activity_id, | |
"registration": registration | |
}; | |
} | |
function saveStatement(lrs, statement) { | |
return new Promise(function(resolve, reject) { | |
lrs.saveStatement(statement, { | |
callback: function(error, xhr) { | |
if (error) { | |
reject({ | |
error: error, | |
xhr: xhr | |
}); | |
} else { | |
resolve(xhr); | |
} | |
} | |
}); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment