- Notifications
You must be signed in to change notification settings - Fork131
Display H5P content without the need for an H5P server
License
tunapanda/h5p-standalone
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Display H5P content without the need for an H5P server.
This library can be installed and used in two main ways, depending on your project setup. After installation, ensure you have an H5P file (.h5p
) and its contents extracted into a folder in your project. For a guide on this, see theExtracting H5P section.
This approach is suitable for simpler projects or when you don't have a JavaScript build pipeline. You have two options: using a CDN or downloading files.
This is the quickest way to get started with manual installation. You can link to the player files directly from a CDN like jsDelivr.
Include these links in your HTML:
<!-- Replace @latest with a specific version, e.g., @3.9.0, for production --><linkrel="stylesheet"href="https://cdn.jsdelivr.net/npm/h5p-standalone@latest/dist/styles/h5p.css"><scriptsrc="https://cdn.jsdelivr.net/npm/h5p-standalone@latest/dist/main.bundle.js"charset="UTF-8"></script>
Note: While@latest
gets the newest version, it's recommended to pin to a specific version in production environments to avoid unexpected updates. For example, useh5p-standalone@3.9.0
instead ofh5p-standalone@latest
.
Example HTML page:
<html></head><body><divid="h5p-container"></div><scriptsrc="https://cdn.jsdelivr.net/npm/h5p-standalone@latest/dist/main.bundle.js"></script><script>document.addEventListener('DOMContentLoaded',function(){constoptions={h5pJsonPath:'/path/to/your/h5p-folder',// Path to your self-hosted H5P content directoryframeJs:'https://cdn.jsdelivr.net/npm/h5p-standalone@latest/dist/frame.bundle.js',frameCss:'https://cdn.jsdelivr.net/npm/h5p-standalone@latest/dist/styles/h5p.css',};constel=document.getElementById('h5p-container');// H5PStandalone is globally available when main.bundle.js is included via a script tagnewH5PStandalone.H5P(el,options);});</script></body></html>
Your H5P content (specified inh5pJsonPath
) still needs to be hosted on your own server or accessible path.
This method involves downloading the pre-built files from the releases page and hosting them yourself.
Installation Steps:
- Download the latest release source code (e.g.,
h5p-standalone-vX.X.X.zip
) from thereleases page. - Extract the downloaded zip file.
- Locate the
dist
folder within the extracted contents. Copy thisdist
folder into a suitable location in your project (e.g., rename it toh5p-player
and place it in anassets
directory likeassets/h5p-player
).
Usage Example (Self-Hosted):After placing the files from thedist
folder into your project:
Add an HTML
div
element where you want to display the H5P content. Thisdiv
must have a uniqueid
.<divid="h5p-container"></div>
Include the H5P standalone main script (
main.bundle.js
) in your HTML page. Modify thesrc
path according to where you placed thedist
folder's contents.<scripttype="text/javascript"src="assets/h5p-player/main.bundle.js"charset="UTF-8"></script>
Call the H5P player in a subsequent script tag, providing the
id
of yourdiv
and paths to the H5P content and the necessary player assets (frame.bundle.js
andh5p.css
from your self-hosteddist
folder contents).document.addEventListener('DOMContentLoaded',function(){constel=document.getElementById('h5p-container');constoptions={h5pJsonPath:'/path/to/your/h5p-folder',// Path to the extracted H5P contentframeJs:'assets/h5p-player/frame.bundle.js',// Path to player's frame.bundle.jsframeCss:'assets/h5p-player/styles/h5p.css',// Path to player's h5p.css};newH5PStandalone.H5P(el,options);});
This method is suitable for projects that utilize a JavaScript module bundler and a build process.
Install the player using your favorite package manager, for example:
# pnpmpnpm install h5p-standalone# yarnyarn add h5p-standalone# npmnpm install h5p-standalone
After installation via a package manager, you can import the player into your JavaScript modules.
Add an HTML element to your page where the H5P content will be rendered:
<divid="h5p-container"></div>
Then, initialize the player in your #"auto" data-snippet-clipboard-copy-content="import { H5P } from 'h5p-standalone'; // ES6 Import// const { H5P } = require('h5p-standalone'); // For CommonJS environments const el = document.getElementById('h5p-container');const options = { h5pJsonPath: '/path/to/your/h5p-folder', // Path to the extracted H5P content frameJs: '/assets/h5p-standalone/frame.bundle.js', // Adjust path as per your project structure frameCss: '/assets/h5p-standalone/styles/h5p.css', // Adjust path as per your project structure};new H5P(el, options);">
import{H5P}from'h5p-standalone';// ES6 Import// const { H5P } = require('h5p-standalone'); // For CommonJS environmentsconstel=document.getElementById('h5p-container');constoptions={h5pJsonPath:'/path/to/your/h5p-folder',// Path to the extracted H5P contentframeJs:'/assets/h5p-standalone/frame.bundle.js',// Adjust path as per your project structureframeCss:'/assets/h5p-standalone/styles/h5p.css',// Adjust path as per your project structure};newH5P(el,options);
Note onframeJs
andframeCss
paths: When using with a bundler, you'll need to ensure that theframe.bundle.js
andh5p.css
files (from thedist
folder of this package) are copied to a location accessible by your application (e.g., your publicassets
directory) during your build process. The paths in theoptions
object must then point to these served files.
A detailed description of all H5P player arguments, including advanced options for customization, xAPI, and state restoration, is provided in theAdvanced Usage section.
H5P files (with the.h5p
extension) are essentially zip archives. Before you can use them with this player, you need to extract their contents into a folder within your project.
Important Note on H5P Libraries:
Content exported directly from h5p.org might not include all the necessary H5P libraries required for the content to function correctly. This is because h5p.org optimizes exports by assuming the libraries are already present on the target platform.
If you encounter issues with missing libraries, you have a couple of options:
- Manually download libraries: You might need to identify the missing libraries and download them separately from h5p.org, then place them in the appropriate H5P content folder.
- Use bundled H5P content: Obtain your H5P content from a source that explicitly bundles all required libraries within the
.h5p
file.
The standalone H5P player constructornew H5PStandalone.H5P(el, options)
ornew H5P(el, options)
accepts two arguments:
- An HTML element where the H5P iframe will be embedded.
- A JSON object with the following options:
- Basic options
Option name | Required | Description |
---|---|---|
h5pJsonPath | Yes | String. Path to the H5P content folder. |
frameCss | Yes | String. URL to the standalone playerh5p.css . |
frameJs | Yes | String. URL to the standalone playerframe.bundle.js . |
id | No | String. Player unique identifier. Randomly generated by default. |
librariesPath | No | String. Path where the player should find the H5P content libraries. Defaults to theh5pJsonPath . |
contentJsonPath | No | String. Path where the player should find the H5Pcontent.json file. Defaults to{h5pJsonPath}/content . |
frame | No | Boolean. Whether to show the H5P player frame and buttons. Default isfalse . |
copyright | No | Boolean. Whether to display the copyright button. Default isfalse . |
export | No | Boolean. Whether to display a download button. Default isfalse . |
icon | No | Boolean. Whether to display the H5P icon. Default istrue . |
downloadUrl | No | String. A path or URL that provides the.h5p file for download. Used by theexport button. |
fullScreen | No | Boolean. Whether to enable the fullscreen button (if supported by the browser). Default isfalse . |
embed | No | Boolean. Whether to display the embed button. Default isfalse . (N.B. Setting this totrue requiresembedCode to be provided). |
embedCode | Yes, ifembed is true | String. Embed/iframe code that users can copy. Placeholders:w and:h will be replaced. SeeCaveats for Embed Code. |
customCss | No | String or Array of strings. Path(s) to custom CSS file(s). |
customJs | No | String or Array of strings. Path(s) to custom JavaScript file(s). Useful for adding external libraries. See theFrequently Asked Questions (FAQ) for detailed examples like MathJax integration. |
reportingIsEnabled | No | Boolean. Set totrue to enable the submit button, particularly for content like Interactive Book. Defaults tofalse . |
xAPIObjectIRI | No | String. An identifier for a single unique Activity, utilized when generating the xAPIobject field. Defaults to page host + pathname. |
- User state & data (refer to thePrevious State Restoration section for more details)
Option name | Required | Description |
---|---|---|
contentUserData | No | Array. Used to pass previously saved user state to the player. Expects an array of objects, e.g.,[{ dataType: 'state', previousState: 'JSON_STRING_OF_STATE', subContentId: '*' }] . |
saveFreq | Yes, ifcontentUserData orajax.* is set | Number. How often (in seconds) the current user engagement content state should be autosaved. Set tofalse to disable. |
postUserStatistics | No | Boolean. Indicates if H5P should post results upon a finish event. Default isfalse . (Requiresajax.setFinishedUrl to be set). |
ajax | No | Object. Required if you need H5P to manage a learner's state via AJAX calls. |
ajax.setFinishedUrl | No | String. URL where H5P should POST the results upon a finish event. (RequirespostUserStatistics to betrue ). |
ajax.contentUserDataUrl | No | String. Endpoint for H5P to GET and POST the current user state. (Requiresuser property to be set). |
user | No | Object. Current user data object. |
user.name | Yes, ifuser is provided | String. Name of the xAPI actor. |
user.mail | Yes, ifuser is provided | String. Email of the user, uniquely identifying the xAPI actor. |
Note:
- One can use absolute URL for
frameCss
,frameJs
, and for other path options(h5pJsonPath
,librariesPath
, &librariesPath
) - Any path that starts with a forward slash
/
is treated as relative to the site root. - Any path starting with a dot is treated to be in respect to the current page directory.
import{H5P}from'h5p-standalone';constel=document.getElementById('h5p-container');constoptions={id:'exercise-one',frameJs:'./assets/frame.bundle.js',// Relative path to player scriptframeCss:'./assets/styles/h5p.css',// Relative path to player stylesh5pJsonPath:'/path/to/h5p-folder',contentJsonPath:'/path/to/h5p-folder',// content.json is in the same folder as h5p.jsonlibrariesPath:'/path/to/shared/libraries',// Optional: shared libraries pathframe:true,//required to display copyright, embed, & export buttonscopyright:true,export:false,icon:true,downloadUrl:'/path/to/exercise-one.h5p',fullScreen:true,//enable fullscreen buttonembed:true,embedCode:'<iframe width=":w" height=":h" src="https://YOURSITE/h5p-embed/exercise-one" frameBorder="0" scrolling="no"></iframe>',customCss:['/path/to/custom-styles.css','/path/to/another-theme.css'],customJs:'/path/to/your-custom-script.js',// Can be a single string or an array of stringsreportingIsEnabled:true,// Enable submit button for content like Interactive Book};newH5P(el,options).then(()=>{// do stuff});
To render multiple H5Ps, your codemust be async aware.
import{H5P}from'h5p-standalone';constplayer1Options={h5pJsonPath:'/h5p/exercise-one',frameJs:'/assets/frame.bundle.js',frameCss:'/assets/styles/h5p.css',};constplayer2Options={h5pJsonPath:'/h5p/exercise-two',frameJs:'/assets/frame.bundle.js',frameCss:'/assets/styles/h5p.css',};constplayer1=newH5P(document.getElementById('h5p-container-1'),player1Options);//example using top level awaitawaitnewH5P(document.getElementById('h5p-container-1'),player1Options);awaitnewH5P(document.getElementById('h5p-container-2'),player2Options);
To listen forxAPI events emitted by the player, you must wait for the player to finish loading and initializing the required content libraries. You can find more info about xAPI events herehttps://h5p.org/documentation/x-api
constel=document.getElementById("h5p-container");constoptions={h5pJsonPath:"/h5p-folder",frameJs:"/assets/frame.bundle.js",frameCss:"/assets/styles/h5p.css",};newH5PStandalone.H5P(el,options).then(function(){H5P.externalDispatcher.on("xAPI",(event)=>{//do something useful with the eventconsole.log("xAPI event: ",event);});});
This section describes how to save and load a user's progress and interactions within an H5P content. This "user state" is distinct from xAPI events, which are typically used for reporting completion or scores to a Learning Record Store (LRS). Restoring user state allows learners to resume their work exactly where they left off.
There are two main approaches to manage user state with this player:
In this method, your application is responsible for saving and loading the H5P state in your preferred storage solution anywhere. You provide the previously saved state to the player via thecontentUserData
option and implement functions to retrieve and save the state as needed.
Note: The example below uses top-levelawait
. You'll need to use this script in an environment that supports it, such as a JavaScript module (<script type="module">
) or wrap the main logic in anasync
function. Also, ensureel
(the DOM element for H5P, typically<div></div>
) is defined in the scope where this script runs.
functionretrieveSavedContentState(contentId){// 👉 your implementation that returns the state for this content (and of course for this user)// return the content or null}functionsaveContentState(contentId){constcurrentState=window.H5PIntegration.contents[`cid-${contentId}`].contentUserData;//👉 you can call your logic to save this state somewhere}constCONTENT_ID='some-content-unique-id-xxxxx';constpreviousStateJSON=awaitretrieveSavedContentState(CONTENT_ID)constoptions={id:CONTENT_ID,//should be same ash5pJsonPath:'/content/course-presentation-one',frameJs:'/dist/frame.bundle.js',frameCss:'/dist/styles/h5p.css',saveFreq:100,//this is required.contentUserData:[{dataType:'state',previousState:previousStateJSON,//should be a json string.}]}awaitnewH5PStandalone(el,options);//init the h5p player.//call above function periodically, here we are using same time as this content H5P player saving frequency (multiplied by 1000 to convert into miliseconds)setInterval(()=>saveContentState(CONTENT_ID),options.saveFreq*1000);
ThesaveFreq
option in this manual setup is used to control thesetInterval
frequency; if you also haveajax.contentUserDataUrl
configured (for automated state management), H5P core might initiate its own save attempts at this frequency too.
This method relies on the H5P player automatically saving and loading the user state from a backend endpoint that you provide and implement. For this to work, several options must be correctly configured as shown in the example below, includingsaveFreq
,ajax.contentUserDataUrl
, and theuser
object withname
andmail
.
Example Configuration:
constoptions={h5pJsonPath:'/content/course-presentation-one',// Path to your H5P contentframeJs:'/dist/frame.bundle.js',// Path to player's frame.bundle.jsframeCss:'/dist/styles/h5p.css',// Path to player's h5p.csssaveFreq:100,// Time in seconds for autosaving stateajax:{// URL for loading (GET) and saving (POST) user state.// :contentId is a placeholder replaced by H5P with the actual content ID.// Other placeholders like :dataType and :subContentId can also be used if your backend expects them.contentUserDataUrl:'/api/v1/h5p/history/users/123/content/:contentId'},user:{// User object is required for automated state savingname:'John Doe',mail:'john@example.com'// Email is used by H5P core to uniquely identify the user},};
Backend Implementation:You are responsible for implementing the backend server logic at the specifiedcontentUserDataUrl
.
- GET Request: When H5P content loads, the player will make a GET request to this URL (with placeholders like
:contentId
replaced) to fetch the user's saved state. Your server should return the state as a JSON response, typically an array containing an object (e.g.,[{ "dataType": "state", "previousState": "{\"some\":\"json-string\"}" }]
). If no state exists for the given user and content, your endpoint should respond with an empty array ([]
). - POST Request: When H5P needs to save the state (triggered by
saveFreq
), it will make a POST request to thecontentUserDataUrl
. The body of the POST request will contain the user state data (typically a JSON string representing the H5P state). Your server should store this data, associating it with the user and content ID.
ThecontentUserDataUrl
can be structured flexibly to suit your backend routing and data model. H5P replaces known placeholders (like:contentId
,:dataType
,:subContentId
) in the URL string before making the request.
An.h5p
file is a zip archive. To use its contents with this player:
- Rename the H5P file extension from
.h5p
to.zip
. - Extract the renamed file's contents into a folder in your project (e.g.,
my-h5p-content
). This folder is what you'll point to with theh5pJsonPath
option.
Here are some common issues and how to resolve them:
Q: Why are some H5P elements missing or not working when I use content exported from h5p.org?
Exports from h5p.org are optimized and might not bundle all the necessary H5P libraries, as they assume the libraries might already exist on the target platform.To resolve this:
- Get libraries from the content type's
.h5p
: Download the.h5p
file for the specific content type directly from h5p.org (e.g., from the content type's example page). These files usually contain all required libraries. Extract this.h5p
file and copy the necessary library folders (e.g.,H5P.ExampleLibrary-1.0
) into your H5P content'slibraries
folder (the one you are using forh5pJsonPath
). - Use fully bundled content: Obtain your H5P content from a source that explicitly bundles all required libraries within the
.h5p
file.Refer to theWorking with H5P Content section for more background.
Q: How do I get the 'Submit' button to show up in Interactive Books (or other content types)?
The 'Submit' button visibility on interactive book is controlled by settingreportingIsEnabled: true
in the player options. See thereportingIsEnabled
description in theAdvanced Usage section for more details.
Q: How can I display mathematical formulas or equations?
To display mathematical formulas as described onhttps://h5p.org/mathematical-expressions, you'll likely need an external library like MathJax. You can load such libraries using thecustomJs
option in the player configuration.Here's how you can configurecustomJs
in the player options to load MathJax:
// Within your player options:customJs:'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js',// Option 1: Using a CDN// customJs: './path/to/your/local/mathjax/tex-mml-chtml.js', // Option 2: Using a local file// customJs accepts array if you already have multiple custom scripts, i.e.:// customJs: [// './scripts/my-first-custom-script.js',// 'https://example.com/another-script.js',// 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js' // or your local path// ],
Refer to thecustomJs
description in theH5P Options table for more details on the option itself. Remember that the path to local scripts should be relative to your HTML file or an absolute URL.
Q: How resizer for embed code works
- This library includes an H5P resizer by default. However, to ensure the iframe width resizes promptly with the parent page, add a CSS style setting
width: 100%
to the iframe tag itself. - If you want to allow users to resize the iframe's width and height using H5P's resize handles, set them using the placeholders
:w
and:h
in thewidth
andheight
attributes of the iframe.
An example combining these points:
<iframewidth=":w"height=":h"src="https://app.wikonnect.org/embed/YOUR-CONTENT-ID"frameBorder="0"scrolling="no"style="width:100%"></iframe>
After cloning the repository and installing dependencies withyarn install
, you can modify the project.To build the distributable files:
yarn build
To run availableCypress tests:
yarntest
About
Display H5P content without the need for an H5P server
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Contributors14
Uh oh!
There was an error while loading.Please reload this page.