h5p-course-presentation
h5p-course-presentation copied to clipboard
No result for simple Course Presentation
I'm using the WordPress plugin and I have created a 3 slide ‘Course Presentation’ with no quiz in them.
It seams that it will not send a finish statement when all slides are viewed.
I would expect a h5p_setFinished
action to be sent, but I only get h5p_contents_user_data
. I have installed “H5PxAPIkatchu” plugin to check for xapi calls. There are no ‘completed’ verbs registered for this simple course with no quiz. No summary page also.
test-22.zip - This is my course. It can't get more basic than this.
Not sure what to do in order to track completion of these courses.
Hi @Adrian-S did you manage to get this work? I am also looking for a solution to this.
Yes, but it's ugly. I had to add some JS that looks like this:
if(typeof H5P !== 'undefined') {
var $iframes = jQuery('iframe');
if($iframes.length > 0) {
var frameH5P = $iframes[0].contentWindow.H5P;
if(typeof frameH5P !== 'undefined') {
var hInst = frameH5P.instances[0];
hInst.on('changedSlide', function(e) {
// is this the last slide ?
if(hInst.currentSlideIndex == hInst.slides.length - 1) {
// finish it with score some score
frameH5P.setFinished(hInst.contentId, 1, 1, 0);
}
});
}
}
}
H5P exists on main window and inside the frame. But the main idea is to get the H5P and Instance that is running.
If you have multiple types of H5P moduled it might be whise to try and check what they are. For example: if( frameH5P.instances[0] instanceof frameH5P.QuestionSet ) {}
Some info here: https://h5p.org/node/2466#setFinished and here: https://h5p.org/documentation/api/H5P.html#.setFinished
Hope it helps, althow I still expect an official fix / response.
Hi @Adrian-S and @fmarc-mdsol I have a few comments, hope they are useful.
Using setFinished() 1
If you really require to invoke setFinished() with those parameters, you should use
hInst.trigger('finish', {
score: 1,
maxScore: 1,
time: 0
});
Calling setFinished() directly is not recommended.
Using setFinished() 2
If you just require setFinished to be called and can spare the time property - seems you set it to 0 anyway, you can just trigger the xAPI completed event which will result in setFinished to be called. This would achieve the same (except for time to be passed, but Course Presentation doesn't either) and not omit other things that are supposed to be triggered.
hInst.triggerXAPICompleted(1, 1);
Adding scripts to H5P content
If you want to add scripts to modyify H5P content, you should use the alter_scripts hook that H5P offers. Please see https://h5p.org/node/2692.
Not only will it spare you the hassle of finding your way inside the iframe, but you also won't have to deal with finding the correct Course Presentation instance or dealing with all of them one by one.
You can use the alter_scripts hook to filter for Course Presentation contents and then pass custom scripts only to those. This would leave you with something like this:
H5P.externalDispatcher.on('initialized', function() {
// Is always Course Presentation if filtered in alter_scripts
var instance = H5P.instances[0];
var done = false;
// This will trigger setFinished (not supposed to be called directly)
var triggerFinish = function() {
instance.triggerXAPICompleted(1, 1);
};
// setFinished will fire anyway when there's a summary slide
if (instance.summarySlideObject.$summarySlide) {
return;
}
if (instance.slides.length === 1) {
// Just one slide
triggerFinish();
}
else {
// Multiple slides, wait for last
H5P.on(instance, 'changedSlide', function() {
if (!done && instance.getCurrentSlideIndex() === instance.slides.length - 1) {
done = true; // Only trigger once (feels more correct than retriggering)
triggerFinish();
}
});
}
});
Hi @Adrian-S and @otacke , thanks for your prompt replies and suggestions. This is really useful!
Thanks @otacke!
We're using the H5P WordPress integration for LearnDash and ran into this exact same issue.
For those interested, you can inject the code displayed above by doing the following:
functions.php
Add this code block to your functions.php
/**
* This action allows us to enqueue our own JS files to be loaded whenever H5P content is being rendered.
*
* @param array &$scripts List of JavaScripts to be included.
* @param array $libraries The list of libraries that has the scripts.
* @param string $embed_type Possible values are: div, iframe, external, editor.
*/
add_action('h5p_alter_library_scripts', function (&$scripts, $libraries, $embed_type) {
$scripts[] = (object) [
'path' => get_stylesheet_directory_uri() . '/h5p-presentation-completion.js',
'version' => ''
];
}, 10, 3);
JS
Create a file in your theme folder called h5p-presentation-completion.js
and add the code block referenced above (included here for brevity)
H5P.externalDispatcher.on('initialized', function() {
// Is always Course Presentation if filtered in alter_scripts
var instance = H5P.instances[0];
var done = false;
// This will trigger setFinished (not supposed to be called directly)
var triggerFinish = function() {
instance.triggerXAPICompleted(1, 1);
};
// setFinished will fire anyway when there's a summary slide
if (instance.summarySlideObject.$summarySlide) {
return;
}
if (instance.slides.length === 1) {
// Just one slide
triggerFinish();
}
else {
// Multiple slides, wait for last
H5P.on(instance, 'changedSlide', function() {
if (!done && instance.getCurrentSlideIndex() === instance.slides.length - 1) {
done = true; // Only trigger once (feels more correct than retriggering)
triggerFinish();
}
});
}
});
That's it! The Course presentation H5P module should now send the 'completed' verb once you reach the end of the presentation.