Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: sr258/scorm-h5p-wrapper
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: CoorpAcademy/scorm-h5p-wrapper
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Able to merge. These branches can be automatically merged.
  • 6 commits
  • 8 files changed
  • 2 contributors

Commits on Oct 7, 2020

  1. Copy the full SHA
    c9e70f1 View commit details

Commits on Oct 12, 2020

  1. Merge pull request #1 from CoorpAcademy/include-coorpacademy-specific…

    …ations
    
    include coorpacademy specifications
    esa-coorp authored Oct 12, 2020
    Copy the full SHA
    8f2a641 View commit details

Commits on Oct 14, 2020

  1. Add ie11 polyfills

    esa-coorp committed Oct 14, 2020
    Copy the full SHA
    3f32e1d View commit details
  2. Merge pull request #2 from CoorpAcademy/add-ie11-polyfills

    Add ie11 polyfills
    jomaora authored Oct 14, 2020
    Copy the full SHA
    e38b3b3 View commit details

Commits on Oct 23, 2020

  1. Fix safari

    esa-coorp committed Oct 23, 2020
    Copy the full SHA
    323d89e View commit details
  2. Merge pull request #3 from CoorpAcademy/fix-safari

    Fix safari
    jomaora authored Oct 23, 2020
    Copy the full SHA
    22d31da View commit details
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
"main": "src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"copy-h5p-standalone": "cp -R node_modules/h5p-standalone/dist/* src/template",
"copy-h5p-standalone": "cp -R node_modules/h5p-standalone/dist/* src/template && sed -i '' 's/externalEmbed = false;/externalEmbed = true;/g' src/template/frame.bundle.js && sed -i '' 's/externalEmbed = false;/externalEmbed = true;/g' src/template/main.bundle.js && more static/h5p-coorp.css >> src/template/styles/h5p.css",
"start": "node ./src/index.js"
},
"repository": {
4 changes: 2 additions & 2 deletions src/creator.js
Original file line number Diff line number Diff line change
@@ -17,12 +17,12 @@ var creator = async (outputDir, h5pContentDir, tempDir, masteryScore) => {
masteryScore = 100;
}
await fs.remove(tempDir);
await fs.copy(templateDir, tempDir, {
await fs.copy(h5pContentDir, tempDir + "/workspace", {
errorOnExist: false,
overwrite: true,
recursive: true
});
await fs.copy(h5pContentDir, tempDir + "/workspace", {
await fs.copy(templateDir, tempDir, {
errorOnExist: false,
overwrite: true,
recursive: true
2 changes: 1 addition & 1 deletion src/template/SCORM_API_wrapper.js
Original file line number Diff line number Diff line change
@@ -46,7 +46,7 @@ further modified by Philip Hutchison

var pipwerks = {}; //pipwerks 'namespace' helps ensure no conflicts with possible other "SCORM" variables
pipwerks.UTILS = {}; //For holding UTILS functions
pipwerks.debug = { isActive: true }; //Enable (true) or disable (false) for debug mode
pipwerks.debug = { isActive: false }; //Enable (true) or disable (false) for debug mode

pipwerks.SCORM = { //Define the SCORM object
version: null, //Store SCORM version.
3 changes: 2 additions & 1 deletion src/template/h5p-adaptor.js
Original file line number Diff line number Diff line change
@@ -63,7 +63,8 @@ var onCompleted = function (result) {
}

H5P.externalDispatcher.on('xAPI', function (event) {
console.log('xAPI event: ' + JSON.stringify(event));
console.log('xAPI event: ' + JSON.stringify(event, null, 2));
H5P.jQuery(window).trigger('resize');
if (event.data.statement.result) {
onCompleted(event.data.statement.result);
}
7 changes: 7 additions & 0 deletions src/template/index.html
Original file line number Diff line number Diff line change
@@ -11,6 +11,12 @@
}
</style>
<meta charset="utf-8" />
<meta name="referrer" content="no-referrer-when-downgrade">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=es6"></script>
<script src="https://cdn.jsdelivr.net/bluebird/3.5.0/bluebird.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/2.0.3/fetch.js"></script>
<script src="https://cdn.jsdelivr.net/npm/matches-selector-polyfill@1.0.0/dist/matches-selector.min.js"></script>
<script
type="text/javascript"
src="main.bundle.js"
@@ -24,5 +30,6 @@
var element = document.getElementById("h5p-container");
const h5p = new H5PStandalone.H5P(element, "workspace");
</script>
<script src="https://static.coorpacademy.com/h5p/h5p-resizer.js"></script>
</body>
</html>
315 changes: 315 additions & 0 deletions src/template/workspace/H5P.BranchingQuestion-1.0/branchingQuestion.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,315 @@
H5P.BranchingQuestion = (function () {

function BranchingQuestion(parameters) {
var self = this;
self.firstFocusable;
self.lastFocusable;
H5P.EventDispatcher.call(self);
this.container = null;
let answered;

/**
* Get closest ancestor of DOM element that matches selector.
*
* Mimics Element.closest(), workaround for IE11.
*
* @param {Element} element DOM element.
* @param {string} selector CSS selector.
* @return {Element|null} Element, if found. Else null.
*/
const getClosestParent = function (element, selector) {
if (!document.documentElement.contains(element)) {
return null;
}
if (!Element.prototype.matches) {
Element.prototype.matches =
Element.prototype.matchesSelector ||
Element.prototype.mozMatchesSelector ||
Element.prototype.msMatchesSelector ||
Element.prototype.oMatchesSelector ||
Element.prototype.webkitMatchesSelector
}

do {
if (element.matches(selector)) {
return element;
}
element = element.parentElement || element.parentNode;
}
while (element !== null && element.nodeType === 1);
return null;
};

var createWrapper = function () {
var wrapper = document.createElement('div');
wrapper.classList.add('h5p-branching-question');

var icon = document.createElement('img');
icon.classList.add('h5p-branching-question-icon');
icon.src = self.getLibraryFilePath('branching-question-icon.svg');

wrapper.appendChild(icon);

return wrapper;
};

var appendMultiChoiceSection = function (parameters, wrapper) {
var questionWrapper = document.createElement('div');
questionWrapper.classList.add('h5p-multichoice-wrapper');

var title = document.createElement('div');
title.classList.add('h5p-branching-question-title');
title.innerHTML = parameters.branchingQuestion.question;

questionWrapper.appendChild(title);

const alternatives = parameters.branchingQuestion.alternatives || [] ;
alternatives.forEach(function (altParams, index, array) {
const alternative = createAlternativeContainer(altParams.text);

if (index === 0) {
self.firstFocusable = alternative;
}

if (index === array.length - 1) {
self.lastFocusable = alternative;
}

alternative.nextContentId = altParams.nextContentId;

// Create feedback screen if it exists
const hasFeedback = altParams.feedback && !!(
altParams.feedback.title && altParams.feedback.title.trim() ||
altParams.feedback.subtitle && altParams.feedback.subtitle.trim() ||
altParams.feedback.image
);
if (hasFeedback && altParams.nextContentId !== -1) {
alternative.feedbackScreen = createFeedbackScreen(
altParams.feedback,
alternative.nextContentId,
index
);
alternative.proceedButton = alternative.feedbackScreen.querySelectorAll('button')[0];
}
alternative.hasFeedback = altParams.feedback && !!(hasFeedback || altParams.feedback.endScreenScore !== undefined);
alternative.feedback = altParams.feedback;

alternative.addEventListener('keyup', function (event) {
if (event.which == 13 || event.which == 32) {
this.click();
}
});

alternative.onclick = function (e) {
if (this.feedbackScreen !== undefined) {
if (self.container) {
self.container.classList.add('h5p-branching-scenario-feedback-dialog');
}
wrapper.innerHTML = '';
wrapper.appendChild(this.feedbackScreen);
answered = index;
this.proceedButton.focus();
self.triggerXAPI('interacted');
}
else {

var currentAlt = e.target.classList.contains('.h5p-branching-question-alternative') ?
e.target : getClosestParent(e.target, '.h5p-branching-question-alternative');
var alts = questionWrapper.querySelectorAll('.h5p-branching-question-alternative');
var index2;
for (var i = 0; i < alts.length; i++) {
if (alts[i] === currentAlt) {
index2 = i;
break;
}
}
answered = index2;

var nextScreen = {
nextContentId: this.nextContentId,
chosenAlternative: index2,
};

const currentAltParams = parameters.branchingQuestion.alternatives[index2];
const currentAltHasFeedback = !!(currentAltParams.feedback.title
|| currentAltParams.feedback.subtitle
|| currentAltParams.feedback.image
|| currentAltParams.feedback.endScreenScore !== undefined
);

if (index2 >= 0 && currentAltHasFeedback) {
nextScreen.feedback = currentAltParams.feedback;
}
self.trigger('navigated', nextScreen);
}
};
questionWrapper.appendChild(alternative);
});

wrapper.appendChild(questionWrapper);
return wrapper;
};

var createAlternativeContainer = function (text) {
var wrapper = document.createElement('div');
wrapper.classList.add('h5p-branching-question-alternative');
wrapper.tabIndex = 0;

var alternativeText = document.createElement('p');
alternativeText.innerHTML = text;

wrapper.appendChild(alternativeText);
return wrapper;
};

var createFeedbackScreen = function (feedback, nextContentId, chosenAlternativeIndex) {

var wrapper = document.createElement('div');
wrapper.classList.add('h5p-branching-question');
wrapper.classList.add(feedback.image !== undefined ? 'h5p-feedback-has-image' : 'h5p-feedback-default');

if (feedback.image !== undefined && feedback.image.path !== undefined) {
var imageContainer = document.createElement('div');
imageContainer.classList.add('h5p-branching-question');
imageContainer.classList.add('h5p-feedback-image');
var image = document.createElement('img');
image.src = H5P.getPath(feedback.image.path, self.contentId);
imageContainer.appendChild(image);
wrapper.appendChild(imageContainer);
}

var feedbackContent = document.createElement('div');
feedbackContent.classList.add('h5p-branching-question');
feedbackContent.classList.add('h5p-feedback-content');

var feedbackText = document.createElement('div');
feedbackText.classList.add('h5p-feedback-content-content');
feedbackContent.appendChild(feedbackText);

var title = document.createElement('h1');
title.innerHTML = feedback.title || '';
feedbackText.appendChild(title);

if (feedback.subtitle) {
var subtitle = document.createElement('div');
subtitle.innerHTML = feedback.subtitle || '';
feedbackText.appendChild(subtitle);
}

var navButton = document.createElement('button');
navButton.onclick = function () {
self.trigger('navigated', {
nextContentId: nextContentId,
chosenAlternative: chosenAlternativeIndex
});
};

var text = document.createTextNode(parameters.proceedButtonText);
navButton.appendChild(text);

feedbackContent.appendChild(navButton);

var KEYCODE_TAB = 9;
feedbackContent.addEventListener('keydown', function (e) {
var isTabPressed = (e.key === 'Tab' || e.keyCode === KEYCODE_TAB);
if (isTabPressed) {
e.preventDefault();
return;
}
});

wrapper.appendChild(feedbackContent);

return wrapper;
};

//https://hiddedevries.nl/en/blog/2017-01-29-using-javascript-to-trap-focus-in-an-element
var trapFocus = function (element) {
var KEYCODE_TAB = 9;
element.addEventListener('keydown', function (e) {
var isTabPressed = (e.key === 'Tab' || e.keyCode === KEYCODE_TAB);

if (!isTabPressed) {
return;
}

if (e.shiftKey && document.activeElement === self.firstFocusable) /* shift + tab */ {
self.lastFocusable.focus();
e.preventDefault();
}
else if (document.activeElement === self.lastFocusable) { /* tab */
self.firstFocusable.focus();
e.preventDefault();
}
});
};

/**
* Get xAPI data.
* Contract used by report rendering engine.
*
* @see contract at {@link https://h5p.org/documentation/developers/contracts#guides-header-6}
*/
self.getXAPIData = function () {
var xAPIEvent = this.createXAPIEventTemplate('answered');
addQuestionToXAPI(xAPIEvent);
xAPIEvent.setScoredResult(undefined, undefined, self, true);
xAPIEvent.data.statement.result.response = answered;
return {
statement: xAPIEvent.data.statement
};
};

/**
* Add the question to the given xAPIEvent
*
* @param {H5P.XAPIEvent} xAPIEvent
*/
var addQuestionToXAPI = function (xAPIEvent) {
const converter = document.createElement('div');

var definition = xAPIEvent.getVerifiedStatementValue(['object', 'definition']);
converter.innerHTML = parameters.branchingQuestion.question
definition.description = {
'en-US': converter.innerText
};
definition.type = 'http://adlnet.gov/expapi/activities/cmi.interaction';
definition.interactionType = 'choice';
definition.correctResponsesPattern = [];
definition.choices = [];
definition.extensions = {
'https://h5p.org/x-api/no-correct-answer': 1
};

const alternatives = parameters.branchingQuestion.alternatives;
for (let i = 0; i < alternatives.length; i++) {
converter.innerHTML = alternatives[i].text
definition.choices[i] = {
'id': i + '',
'description': {
'en-US': converter.innerText
}
};
}
};

/**
* TODO
*/
self.attach = function ($container) {
var questionContainer = document.createElement('div');
questionContainer.classList.add('h5p-branching-question-container');

var branchingQuestion = createWrapper(parameters);
branchingQuestion = appendMultiChoiceSection(parameters, branchingQuestion);
trapFocus(branchingQuestion);

questionContainer.appendChild(branchingQuestion);
$container.append(questionContainer);
this.container = $container[0];
};
}

return BranchingQuestion;

})();
Loading