{"id":22191855,"url":"https://github.com/bigbluebutton/h5p-standalone","last_synced_at":"2026-01-05T01:32:12.152Z","repository":{"id":250002510,"uuid":"778979473","full_name":"bigbluebutton/h5p-standalone","owner":"bigbluebutton","description":"Library needed to render the H5P activity (see BBB's plugin-h5p repository -- Forked from https://github.com/tunapanda/h5p-standalone","archived":false,"fork":false,"pushed_at":"2024-07-25T13:05:56.000Z","size":4188,"stargazers_count":0,"open_issues_count":2,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-01-27T18:49:05.888Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bigbluebutton.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-03-28T19:44:18.000Z","updated_at":"2024-07-24T14:55:18.000Z","dependencies_parsed_at":"2024-07-24T17:17:55.039Z","dependency_job_id":"518f8734-6db4-4084-a556-3f1eb0e3087d","html_url":"https://github.com/bigbluebutton/h5p-standalone","commit_stats":null,"previous_names":["bigbluebutton/h5p-standalone"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bigbluebutton%2Fh5p-standalone","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bigbluebutton%2Fh5p-standalone/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bigbluebutton%2Fh5p-standalone/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bigbluebutton%2Fh5p-standalone/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bigbluebutton","download_url":"https://codeload.github.com/bigbluebutton/h5p-standalone/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244985908,"owners_count":20542909,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-02T12:18:01.777Z","updated_at":"2026-01-05T01:32:12.127Z","avatar_url":"https://github.com/bigbluebutton.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# H5P Standalone Player 3.x [![CircleCI](https://circleci.com/gh/tunapanda/h5p-standalone.svg?style=svg)](https://circleci.com/gh/tunapanda/h5p-standalone)\nDisplay H5P content without the need for an H5P server\n\n## Installation\n\n**Source**|**Info**\n-----|-----\nyarn | `yarn add h5p-standalone`\nRelease | [Download latest version here](https://github.com/tunapanda/h5p-standalone/releases/latest)\n\n## Basic Usage\nEnsure you have an extracted H5P zip file in your workspace folder first. A simple guide on how to extract an H5P zip file is provided  [here ](#extracting-h5p)\n\n\nThe player can be set up either by directly calling the already built scripts and styles in your `HTML` page or using `ES6` syntax.\n\n### Direct use\n1.  Download the project latest release zipped source code from [here](https://github.com/tunapanda/h5p-standalone/releases/latest)\n2. Extract the downloaded zipped code in step 1 above\n3. Copy the contents of the `dist` folder into your workspace static `assets` folder ( _The folder name does not matter. Remember the location for the next step_ )\n4. Add a  `div` element in your HTML page where you want to display the H5P content. The `div` element should have a unique `id` attribute as compared to all other elements on the same page.\n    ```html\n    \u003cdiv id='h5p-container'\u003e\u003c/div\u003e\n    ```\n\n5. Include the H5P standalone main script in your HTML page (_modify the path location if the files are not in the assets folder_)\n    ```html\n    \u003cscript type=\"text/javascript\" src=\"assets/main.bundle.js\"\u003e\u003c/script\u003e\n    ```\n6. Call the H5P player by providing arguments on where to find a `div` element and the location of the H5P content.\n    ```javascript\n\n    const el = document.getElementById('h5p-container');\n    const options = {\n      h5pJsonPath:  '/h5p-folder',\n      frameJs: '/assets/frame.bundle.js',\n      frameCss: '/assets/styles/h5p.css',\n    }\n   new H5PStandalone.H5P(el, options);\n\n    ```\n    A detailed description of the H5P player arguments are provided  under the [advance section](#advanced-usage)\n    Simple instruction on how to extract H5P zipped file provided [here](#extracting-h5p)\n\n### Using ES6\nInstall the player using yarn\n\n```\nyarn add h5p-standalone\n```\n\nAdd an element to attach the player\n```html\n\u003cdiv id='h5p-container'\u003e\u003c/div\u003e\n```\ninitialize the H5P\n```javascript\nimport { H5P } from 'h5p-standalone'; // ES6\n// const { H5P } = require('h5p-standalone'); AMD\n// const { H5P } = 'H5PStandalone'; // object destructuring\n\nconst el = document.getElementById('h5p-container');\nconst options = {\n    h5pJsonPath: '/h5p-folder',\n    frameJs: '/assets/frame.bundle.js',\n    frameCss: '/assets/styles/h5p.css',\n};\n\nnew H5P(el, options);\n```\n   A detailed description of the H5P player arguments are provided under the [advance section](#advanced-usage)\n## Advanced Usage\nThe standalone H5P player constructor accepts two arguments.\n1. A HTML element where the H5P iframe will be embedded as the first argument.\n2. JSON object with the following options :\n### H5P Options\n1) Basic options\n\n**Option name**|**Required**|**Description**\n-----|-----|----\n`h5pJsonPath`   | Yes | Path to the H5P content folder\n`frameCss`  | Yes | URL to the standalone player `h5p.css`\n`frameJs`   |Yes | URL to the standalone player `frame.bundle.js`\n`id`    | No | Player unique identifier. Randomly generated by default\n`librariesPath` | No| Path where the player should find the H5P content libraries. Defaults to same as `h5pJsonPath`\n`contentJsonPath`|No | Path where the player should find the H5P `content.json` file. Defaults to  `{h5pJsonPath}/content/`,\n`frame` |No| A boolean on whether to show H5P player frame and buttons \n`copyright` |No| A boolean on whether display copyright button\n`export` |No|  A boolean on whether display a download button.\n`icon`  |No|   A boolean on whether display H5P icon\n`downloadUrl` |No| A path or a url that returns zipped h5p for download. The link is used by H5P `export` button\n`fullScreen` |No| A boolean on whether to enable the fullscreen button if the browser supports the feature. Default is `false`|\n`embed` |No| A boolean on whether display embed button. Default is `false`.  N.B. Setting this option to `true` will require an `embedCode` below.\n`embedCode` |unless `embed` is true| Embed/Iframe code that user can insert on their site to view the same content. Check some caveats to consider [below](#caveats-while-adding-embed-code)\n`customCss` | No | Path(s) to custom stylesheet file(s)\n`customJs` | No | Path(s) to custom script file(s)\n`xAPIObjectIRI`|No| An identifier for a single unique Activity ~ utilized when generating xAPI [object](https://github.com/adlnet/xAPI-Spec/blob/master/xAPI-Data.md#acturi) field. Default is page host+pathname\n\n2) User state \u0026 data _(kindly refer to [this section](#previous-state-restoration))_\n\n**Option name**|**Required**|**Description**\n-----|-----|----\n`contentUserData`| No| User previous content interaction state data. The data should be in JSON string format\n`saveFreq` |if `contentUserData` or `ajax.*` is set| How often current user engagement content state should be autosaved (in seconds). Default is `false`. \n`postUserStatistics` | No | Indicates if H5P should post the results once a finish event is triggered. Default is `false`. **** _Requires `ajax.setFinishedUrl` property to be set_\n`ajax` | No | Object required if you need H5P to manage a learner's state \n`ajax.setFinishedUrl`| No | Url where H5P should post the results once a finish event is triggered. **** _Requires `postUserStatistics` to be set to true_.\n`ajax.contentUserDataUrl`| No | Endpoint where H5P can manage current user state.  ****  _Requires `user` property to be set_|\n`user` | No | Current user data object.\n`user.name` | Yes | Used as xAPI actor's name\n`user.mail` | Yes | User email. Uniquely identifies the xAPI actor\n\n\n**Note:**\n- One can use absolute URL for `frameCss`, `frameJs`, and for other path options(`h5pJsonPath`,`librariesPath`, \u0026 `librariesPath`)\n- Any path that starts with a forward slash `/` is treated as relative to the site root.\n- Any path starting with a dot is treated to be in respect to the current page directory.\n----\n#### Example with advance options\n```javascript\nimport { H5P } from 'h5p-standalone';\n\nconst el = document.getElementById('h5p-container');\n\nconst options = {\n    id: 'exercise-one',\n    frameJs: './frame.bundle.js',\n    frameCss: './styles/h5p.css',\n    h5pJsonPath: '/path/to/h5p-folder',\n    contentJsonPath: '/path/to/h5p-folder', //content is on same folder level as h5p.json\n    librariesPath: '/path/to/shared/libaries', //shared libraries path\n    frame: true, //required to display copyright,  embed, \u0026 export buttons\n    copyright: true,\n    export: false,\n    icon: true,\n    downloadUrl: '/path/to/exercise-one.h5p',\n    fullScreen: true, //enable fullscreen button\n    embed: true,\n    embedCode:'\u003ciframe width=\":w\" height=\":h\" src=\"https://replacethiswithyoururl.io\" frameBorder=\"0\" scrolling=\"no\" styles=\"width:100%\"\u003e\u003c/iframe\u003e',\n    customCss: ['/path/to/some-css.css', '/path/to/some-other-css.css'], // custom stylesheets\n    customJs: '/path/to/custom-script.js' // custom script\n  };\n\n\nnew H5P(el,options)\n.then(() =\u003e {\n  // do stuff\n});\n\n// Or using the async-await syntax (async wrapper function removed for readability) :\n await new H5P(el, options);\n\n```\n\n### Multiple H5P players on the same page\nTo render multiple H5Ps, your code **must** be async aware.\n\n```javascript\nimport { H5P } from 'h5p-standalone';\nconst player1Options = {\n    h5pJsonPath: '/h5p/exercise-one',\n    frameJs: '/assets/frame.bundle.js',\n    frameCss: '/assets/styles/h5p.css',\n};\n\nconst player2Options = {\n    h5pJsonPath: '/h5p/exercise-two',\n    frameJs: '/assets/frame.bundle.js',\n    frameCss: '/assets/styles/h5p.css',\n};\n\nconst player1 = new H5P(document.getElementById('h5p-container-1'), player1Options);\n\nplayer1.then(() =\u003e {\n  return new H5P(document.getElementById('h5p-container-2'), player2Options);\n}).then(() =\u003e {\n  // do stuff\n});\n\n\n// OR (async wrapper function removed for readability)\nawait new H5P(document.getElementById('h5p-container-1'), player1Options);\nawait new H5P(document.getElementById('h5p-container-2'), player2Options);\n\n\n```\n\n## Listening to xAPI events\nTo listen for [xAPI events](https://h5p.org/documentation/api/H5P.XAPIEvent.html) 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 here https://h5p.org/documentation/x-api\n1) Using `then()` method\n```js\n\nconst el = document.getElementById(\"h5p-container\");\nconst options = {\n  h5pJsonPath: \"/h5p-folder\",\n  frameJs: \"/assets/frame.bundle.js\",\n  frameCss: \"/assets/styles/h5p.css\",\n};\n\nnew H5PStandalone.H5P(el, options).then(function () {\n  H5P.externalDispatcher.on(\"xAPI\", (event) =\u003e {\n    //do something useful with the event\n    console.log(\"xAPI event: \", event);\n  });\n});\n\n```\n2) Using `async` function\n```js\nimport { H5P as H5PStandalone } from 'h5p-standalone'; //you need you an alias due to conflict\n\nasync function myAwesomePlayer() {\n  const el = document.getElementById(\"h5p-container\");\n  const options = {\n    h5pJsonPath: \"/h5p-folder\",\n    frameJs: \"/assets/frame.bundle.js\",\n    frameCss: \"/assets/styles/h5p.css\",\n  };\n\n  await new H5PStandalone(el, options);\n\n  H5P.externalDispatcher.on(\"xAPI\", (event) =\u003e {\n    //do something useful with the event\n    console.log(\"xAPI event: \", event);\n  });\n}\n\n//don't forget to call the function\nmyAwesomePlayer();\n\n```\n\n##  Previous state restoration.\nH5P provides two approaches for restoring a user's previous interaction state:\n1) using data provided with `contentUserData` option.\n2) automatically fetching the data if `ajax.contentUserDataUrl` is provided\n\n**For both cases, the `saveFreq` option must be set**.\n\nA summary of the previous state restoration process:\n\n1) If the `contentUserData` option is available, skip to the 3rd step.\n2) If `contentUserData` is not available but `user.*` and `ajax.contentUserDataUrl` options were provided, request the data from `ajax.contentUserDataUrl` endpoint.\n3) Process the previous state `data` as follows:\n    - where `data[0].state` equals `RESET`, any previous state will be deleted\n    - else, parse `data[0].state` string and pass it to the H5P player instance.\n    \n `ajax.contentUserDataUrl` may include (contentId,dataType,subContentId) placeholders that will be replaced with respective data _automagically_. Placeholders are prefixed with `:`\n Placeholders are effective when you need to query only current content user data.\n \n `ajax.contentUserDataUrl` example:\n `/api/users/123/h5p/:contentId?data_type=:dataType\u0026subContentId=:subContentId`\n\n### Caveats while adding embed code\n- This library includes an H5P resizer by default in `main.bundle.js` at the moment. But, to allow the iframe width to resize promptly, add CSS style setting the width to 100% i.e. `style=\"width:100%;\"`\n- If you want to allow users to resize the iframe width and height, set them using placeholders provided by H5P i.e., `width=\":w\"` and `height=\":h\"`\n\nAn example that combines the above points:\n\n```js\n\u003ciframe width=\":w\" height=\":h\"\nsrc=\"https://app.wikonnect.org/embed/JJuzs-OAACU\"  //replace this with your URL\nframeBorder=\"0\" scrolling=\"no\" styles=\"width:100%\"\u003e\u003c/iframe\u003e\n```\n\n\n### Extracting H5P\n1. Rename the H5P file extension from `.h5p` file to `.zip`\n2. Extract the renamed file contents into your workspace `h5p-folder` folder\n\n## Testing during development\n After modifying the project, build the files:\n `` yarn build``\n to run available [Cypress](https://www.cypress.io/) tests:\n`` yarn test``\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbigbluebutton%2Fh5p-standalone","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbigbluebutton%2Fh5p-standalone","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbigbluebutton%2Fh5p-standalone/lists"}