Compare commits

..

1114 Commits

Author SHA1 Message Date
Ravi Majithia c79f97a16f
JI-2872 Fix h5p content font size in safari ios devices (#114) 2022-01-05 09:24:39 +01:00
Oliver Tacke d3d003e978
HFP-3465 Fix line breaks breaking metadata field validation (#109)
* Fix linebreaks breaking metadata field validation
* HFP-3465 Use "single line" flag for regexp
2021-12-21 23:45:32 +01:00
Ravi Majithia 22115c0aea
JI-2899 Add aria label to width and height for embed popup (#110) 2021-11-10 12:47:39 +01:00
Erik Langhaug aaf26d584b Merge branch 'master' into JI-2176-tutorial-example-links-new-design 2021-07-01 10:40:04 +02:00
Frode Petterson eeefc1228b
Merge pull request #85 from otacke/add-gltf-file-format
Add gltf to list of allowed file extensions
2021-06-17 13:07:56 +02:00
Erik Langhaug 13ba87ed58 JI-2176 Fix incorrect paths to h5p font files 2021-06-02 09:36:31 +02:00
Erik Langhaug f9a20e908f JI-2176 Add new icons for tutorial and example links 2021-05-31 15:29:14 +02:00
Thomas Marstrander 4599291d7c Fix using undefined $ function 2021-05-12 12:27:57 +02:00
Frode Petterson 1c12b7bbf7
Fix check/use of incorrect API function
This will solve fullscreen issues in Firefox
2021-05-12 12:10:51 +02:00
Frode Petterson 588f096afe
Fix iframe for back button in Edge Chromium
When navigating to the previous page in Edge Chromium the H5P would often break due to it not being loaded when the page is ready. This fix will force a reload of the iframe if it is broken on initialization.
2021-04-29 22:00:15 +02:00
Frode Petterson affaa83b51 Merge branch 'fix-improved-attribute-filtering' 2021-04-22 11:31:08 +02:00
Frode Petterson db3da7a144 Fix renaming of variables 2021-04-22 11:30:45 +02:00
Frode Petterson 17e97d48db Merge branch 'fix-improved-attribute-filtering' 2021-04-22 10:19:26 +02:00
Frode Petterson efd98a719d Fix prevent unnecessary looping 2021-04-22 10:18:43 +02:00
Frode Petterson 0eca5935c0 Fix improved filtering of attributes 2021-04-22 10:05:51 +02:00
Thomas Marstrander f6fef74651 Update keywords description text
Fixes issue 5 from Hub review april
2021-04-14 16:52:43 +02:00
Thomas Marstrander cc5a0b2e57 Update hub sharing 2021-04-14 16:11:48 +02:00
Thomas Marstrander fe3f4a504d Update to use production content hub api 2021-04-07 15:45:36 +02:00
Thomas Marstrander d2522e3800 JI-2366 Update hub sharing UI 2021-04-06 18:36:27 +02:00
Thomas Marstrander 4c543f3214 JI-2359 Update sharing UI 2021-04-06 16:27:22 +02:00
Thomas Marstrander 1d8f0e8dac JI-2366 Update sharing UI 2021-04-06 10:56:34 +02:00
Thomas Marstrander a0f1e1a527 Merge branch 'master' into release 2021-03-23 10:56:38 +01:00
Thomas Marstrander 0308e3a888 Update hub sharing ui 2021-03-23 10:54:51 +01:00
Thomas Marstrander 8ba1611575 Update sharing ui 2021-03-19 11:05:40 +01:00
Thomas Marstrander 951912d7c1 Merge branch 'content-hub' of https://github.com/h5p/h5p-php-library into content-hub 2021-03-17 15:11:51 +01:00
Thomas Marstrander 0c40e081e7 HFP-3234 Adjust notification text when content is shared 2021-03-17 15:11:34 +01:00
Hannaes 982d07f137 HFP-3233 Add hub sharing ui keyword tip strings 2021-03-15 17:13:56 +01:00
Hannaes 96d5b63b2e HFP-3232 Change placeholder text for disciplines selector 2021-03-12 16:31:18 +01:00
Thomas Marstrander 16e51c06f5 JI-2271 Update hub sharing ui 2021-02-22 12:23:36 +01:00
Thomas Marstrander 09e7a7cb0d JI-2271 Add translations for the content hub 2021-02-11 12:28:46 +01:00
Thomas Marstrander 9aacfa1780 Update hub sharing ui 2021-02-10 12:27:56 +01:00
Frode Petterson f1ddd3b3f5 HFP-3089 Update registration UI + translations 2020-12-10 15:13:48 +01:00
Frode Petterson 90835b7345 Update Core font to include hub molecule icon 2020-12-03 10:56:17 +01:00
Thomas Marstrander 1831312d41
JI-2081 Add translations
Move token verification to the individual integrations
Add error message to UI if logo validation fails
2020-12-01 10:40:33 +01:00
Frode Petterson 47d4499377 Update Hub Sharing + Registration clients 2020-11-26 16:22:53 +01:00
Frode Petterson fdd2a618bc Remove token validation from Core
Causes issues for other platforms.
2020-11-12 16:01:37 +01:00
Frode Petterson 8a29796cab Remove token validation from Core
Causes issues for other platforms.
2020-11-12 15:04:10 +01:00
Frode Petterson aa6c909572 Add support for 404 when trying to update content 2020-11-10 14:10:22 +01:00
Frode Petterson 0ba2496c11 Update Sharing UI 2020-11-09 16:12:36 +01:00
Frode Petterson dab4e5120d Update sharing UI 2020-11-05 13:50:06 +01:00
Frode Petterson d5be0158a4 Revert "Fix using Core language"
This reverts commit 4d7dccad3d.
2020-11-04 13:23:56 +01:00
Frode Petterson 4d7dccad3d Fix using Core language 2020-11-04 11:50:54 +01:00
Frode Petterson 160b86e9ae Fix cleanup after reverting revert 2020-11-04 10:42:52 +01:00
Frode Petterson aa5abe786e Revert "Reverts content hub interface change"
This reverts commit 16c71b444b.
2020-11-04 10:25:27 +01:00
Frode Petterson 48c961b661 Merge branch 'master' into content-hub 2020-11-04 10:08:12 +01:00
Frode Petterson d1450fc1bb Update to latest version of registration/sharing UI 2020-10-26 15:52:31 +01:00
Erik Langhaug 96a2c1ff91 Fix syntax error 2020-10-05 14:36:39 +02:00
Hannaes 4b76c7ff8f JI-1958 Add UI string needed 2020-10-02 15:41:36 +02:00
Erik Langhaug 720e6b29a2 HFP-3120 Add UI string for content hub disciplines 2020-09-23 12:48:09 +02:00
Paal Joergensen a5c3dd6c4e JI-1923 Rename 'Hub' -> 'H5P Hub' 2020-09-18 11:07:31 +02:00
Hannaes 832707dcaf JI-1923 Change title text of registration ui 2020-09-18 09:50:41 +02:00
Erik Langhaug ba98139ccb HFP-3049 Add UI strings for cancel publish dialog 2020-09-17 11:50:01 +02:00
Thomas Marstrander ae7b82a34a
HFP-3109 Update hub sharing ui 2020-09-16 15:28:32 +02:00
Erik Langhaug 25deeac560 HFP-3107 Add UI strings for remove and removeImage 2020-09-16 14:14:05 +02:00
Thomas Marstrander 7538202500
HFP-3108 Adjust translations
Removed duplicate strings
2020-09-14 12:31:29 +02:00
Thomas Marstrander 0d7abe0e51
HFP-3102 Add error handling for the content hub 2020-09-10 17:08:14 +02:00
Thomas Marstrander 14bad68d70
HFP-3095 Throw error if retrieving content from hub failed 2020-09-09 14:48:19 +02:00
Thomas Marstrander 917a9b6ccb
HFP-3095 Add error message if unable to contact hub
Fix translation
Update hub registration ui
2020-09-09 13:26:46 +02:00
Thomas Marstrander 67bce48842
HFP-3092 Update sharing ui 2020-09-09 11:24:18 +02:00
Frode Petterson d90accc55e Update sharing UI 2020-09-04 12:54:16 +02:00
Frode Petterson a7f2054101 Update translations and sharing UI 2020-09-04 11:19:34 +02:00
Frode Petterson 03fe25df5a Merge branch 'content-hub' of github.com:h5p/h5p-php-library into content-hub 2020-09-03 15:39:27 +02:00
Frode Petterson 7cb4419eb0 Add separate trigger to trigger content sync 2020-09-03 15:38:45 +02:00
Thomas Marstrander 645058f03e
Merge branch 'content-hub' of github.com:h5p/h5p-php-library into content-hub 2020-09-03 15:02:50 +02:00
Thomas Marstrander b47ae6de6e
HFP-3040 Move account registration logic into core 2020-09-03 15:02:23 +02:00
Frode Petterson e65b22f0d1 HFP-3048 Add support for updating existing content 2020-09-03 14:28:11 +02:00
Frode Petterson 8b317fa5fe HFP-3048 Add UI for getting content data
+ Update sharing UI
2020-09-02 16:22:06 +02:00
Thomas Marstrander 1a644dda11
HFP-3008 Add content language to iframe document 2020-08-28 16:54:16 +02:00
Thomas Marstrander 16c71b444b
Reverts content hub interface change
Moved content hub changes to its own feature branch until it is ready to be implemented for all plugins
2020-08-28 15:26:10 +02:00
Thomas Marstrander eb52ec25a0
Fix missing merge from Drupal git 2020-08-28 11:17:19 +02:00
Thomas Marstrander 3a2232e690
Remove unused font 2020-08-28 10:49:13 +02:00
Thomas Marstrander fb6278744c
Add content hub and a11y changes from Drupal git
See Drupal 7 git for git history for these commits.
2020-08-28 10:30:06 +02:00
Thomas Marstrander 35eb39c469
HFP-3006 Change contrast for iframe action buttons 2020-08-26 13:35:01 +02:00
Thomas Marstrander 555442d37e
Change fallback to original jquery .load() if first arg is not a function 2020-08-05 11:44:23 +02:00
Thomas Marstrander c472d5172d
Add backwards compatibility for old libraries using jQuery's .load() 2020-08-05 11:09:38 +02:00
Oliver Tacke a80773e8d6
Add binary variant of glTF files
glTF files can also be compressed making them smaller
2020-05-30 12:50:37 +02:00
Oliver Tacke ce373203b0 Add gltf to list of allowed file extensions 2020-05-23 17:27:56 +02:00
Frode Petterson 196888bf3e Add jQuery 3.5.1 2020-05-18 11:27:47 +02:00
Pål Jørgensen 743147698f
Merge pull request #74 from andrewnicols/libraryPathSubClassA2
Allow the dependency path to be overridden by child classes
2019-12-18 09:13:46 +01:00
Pål Jørgensen 3b2990f9b8
Merge pull request #76 from andrewnicols/travisfix
Change lint check to report fails correctly
2019-12-18 09:09:51 +01:00
Andrew Nicols 2cb43ad147 Remove type-hint from h5p.classes 2019-12-18 08:44:25 +08:00
Andrew Nicols acec5b0b33 Change lint check to report fails correctly 2019-12-18 08:41:25 +08:00
Paal Joergensen df9d25a5b3 JI-1497 Add audio icon to H5P core font 2019-12-17 10:16:51 +01:00
Paal Joergensen bea974e597 Remove incompatible code 2019-12-17 09:55:54 +01:00
Paal Joergensen 866f94ea47 Revert "Revert "Allow the dependency path to be overridden by child classes""
This reverts commit 87f6f3c970.
2019-12-11 08:56:26 +01:00
Pål Jørgensen 8432a88386
Merge pull request #75 from andrewnicols/travis
Add Travis for all supported PHP versions
2019-12-11 08:49:46 +01:00
Andrew Nicols d392737f45 Add Travis for all supported PHP versions 2019-12-11 08:35:14 +08:00
Andrew Nicols 668233fb95 Allow the dependency path to be overridden by child classes
This allows an implementor to choose how the library is served.
2019-12-11 08:22:19 +08:00
Pål Jørgensen 4c973c3088
Merge pull request #70 from h5p/revert-68-libraryPathSubclass
Revert "Allow the dependency path to be overridden by child classes"
2019-11-12 16:05:14 +01:00
Pål Jørgensen 87f6f3c970
Revert "Allow the dependency path to be overridden by child classes" 2019-11-12 16:04:50 +01:00
Thomas 42568106fc
Merge pull request #68 from andrewnicols/libraryPathSubclass
Allow the dependency path to be overridden by child classes
2019-10-31 16:30:56 +01:00
Frode Petterson 541f6d8415
Merge pull request #69 from stronk7/php74_curly_array_string_offset
Fix PHP 7.4 don't use curly braces for array/string offset
2019-10-30 12:48:13 +01:00
Frode Petterson 143a44cef5 Merge branch 'release' 2019-10-30 11:48:24 +01:00
Frode Petterson 55b04018d7 Adjust icons 2019-10-30 11:42:15 +01:00
Eloy Lafuente (stronk7) f6f6d0fb56 PHP 7.4 fix, don't use curly braces for array/string offset
The array and string offset access syntax using curly braces is deprecated.
Use $str[$idx] instead of $str{$idx}.
RFC: https://wiki.php.net/rfc/deprecate_curly_braces_array_access
2019-10-30 11:28:54 +01:00
Frode Petterson f37231eb3a Merge branch 'release' 2019-10-29 15:14:07 +01:00
Frode Petterson 128fbbc532 Fix de-centered fonts 2019-10-29 15:13:47 +01:00
Frode Petterson 8bf43081dd HFP-2860 Fix white-space style 2019-10-25 13:04:37 +02:00
Frode Petterson ec518a6f67 HFP-2860 Fix BG color 2019-10-25 10:22:14 +02:00
Frode Petterson e635d33169 HFP-2860 Fix BG color + overflow 2019-10-24 16:29:22 +02:00
Frode Petterson 43605b14d6 HFP-2860 Add styling for code tag 2019-10-24 14:39:07 +02:00
Frode Petterson f08655cfb0 Fix dialog accessibility 2019-10-17 15:01:22 +02:00
Frode Petterson 0293d2cdfb Fix space key scrolling page on button expand 2019-10-17 13:02:36 +02:00
Andrew Nicols 34bc10184d Allow the dependency path to be overridden by child classes
This allows an implementor to choose how the library is served.
2019-10-11 20:38:01 +08:00
Thomas Marstrander 9a658ba387
JI-1352 Add event when h5p has finished initializing
This is useful if you want to hook into H5P functionality after the
init function has run, e.g. 'resize' event in instances
2019-10-10 10:34:57 +02:00
Frode Petterson 159f83f1b8 JI-1282 Bump core 2019-10-03 14:01:27 +02:00
Frode Petterson 117668d0e5 JI-1282 Update icons 2019-10-03 09:32:54 +02:00
Oliver Tacke bf10430671 Add toggler view others contents (#65)
* Add toggler to show/hide content of others in data view

Will try to retrieve user.id, user.name and
user.canToggleViewOthersH5PContents from H5PIntegration. If set,
allows to show/hide contents of other users using a checkbox that
uses the user parameters to set a facet on the author column.

* Add toggler to show/hide content of others in data view

Will try to retrieve user.id, user.name and
user.canToggleViewOthersH5PContents from H5PIntegration. If set,
allows to show/hide contents of other users using a checkbox that
uses the user parameters to set a facet on the author column.

* Adjust stylesheet to better match WordPress look
2019-09-30 10:36:42 +02:00
Sjoerd Zonneveld 7d7b420b45 Replaced DIRECTORY_SEPARATOR (#63)
Replace DIRECTORY_SEPARATOR with slash
2019-09-27 11:15:10 +02:00
Paal Joergensen e6fa3d7e54 HFP-1763 Simplify logic 2019-09-26 12:58:15 +02:00
Thomas Marstrander 4d061aef7a
Merge branch 'master' of github.com:h5p/h5p-php-library 2019-09-23 10:58:56 +02:00
Thomas Marstrander 058a9f0a71
HFP-1763 Add focus effect back for textarea 2019-09-23 10:58:28 +02:00
Frode Petterson 9577c57f95 Update H5P font file to include throbber 2019-09-19 11:29:46 +02:00
Thomas Marstrander 8cfd2f0519
HFP-1763 Remove focus effect when using mouse 2019-09-18 13:45:37 +02:00
Paal Joergensen 0922db6fab JI-1285 Add comment 2019-09-10 14:15:28 +02:00
Thomas Marstrander 7a8f894c85 JI-1285 Set empty XAPIEvent object when instance has no contentId
Content types view always expect to have a contentId when they are displayed. This is no the case if they are displayed in the editor as part of a preview. The fix is to set an empty object with definition for the xAPI event, so all the content types that rely on this does not have to be rewritten. This means that content types that are being previewed will send xAPI completed events, but since there are no scripts that catch these events in the editor, this is not a problem.
2019-09-10 14:15:17 +02:00
Paal Joergensen 7bc8666f30 Don't invoke clearFilteredParameters for empty array 2019-08-15 21:15:55 +02:00
Paal Joergensen 8ceb77e881 Bump core api version 2019-08-15 13:26:32 +02:00
Thomas Marstrander 064391236a
Fix keeping metadata when upgrading content 2019-08-15 11:15:47 +02:00
Frode Petterson 4a9ea77d47 HFP-2796 Fix confirm dialog in editor semi-fullsreen mode 2019-08-01 16:21:34 +02:00
Frode Petterson 03794f36dd HFP-2323 Fix clearing all the content caches at the same time 2019-07-12 16:39:46 +02:00
Frode Petterson 9e749eda92 HFP-2766 Allow setting bitrate for video files 2019-06-20 16:10:18 +02:00
Frode Petterson 2c15047e50 JI-1192 Add support for additional query parameter 2019-06-19 10:58:47 +02:00
Frode Petterson fec8953ba8 JI-1192 Fix crossOrigin policy only set for local sources 2019-06-18 14:43:34 +02:00
Frode Petterson 3570441801 Add two new allowed verbs to the xAPI events 2019-06-11 15:03:33 +02:00
Frode Petterson b9a1e5f404 Fix trying to copy URLs upon saving 2019-05-08 14:16:22 +02:00
Paal Joergensen 5d7b480c3b Fix code format 2019-04-08 11:19:38 +02:00
Thomas Marstrander 665e5d424a JI-1059 Move online/offline logic to offline request queue
Fix only queue requests if we are offline
Fix always assume offline request queue is defined
2019-04-08 10:23:20 +02:00
Thomas Marstrander 3b685a5520 JI-1059 Fix offline dialog always showing at the top of the instance
This is needed because we can't determine where the user was on the page
when the request failed
Avoid restoring focus to prevent the screen from jumping around
2019-04-05 16:11:19 +02:00
Thomas Marstrander 38fc962625 JI-1059 Position offline dialog elements on top of last focused element 2019-04-05 14:50:43 +02:00
Frode Petterson 70278d15f4 HFP-2683 Fix empty arrays instead of groups when uploading 2019-04-05 10:15:52 +02:00
Thomas Marstrander 0b1aadbbca JI-1059 Add resizing of offline request dialog for small content
Fix height calculation of confirmation dialog when not provided
2019-04-03 16:12:27 +02:00
Thomas Marstrander 687f886e3d JI-1059 Add offline request queue only if frame contains H5P
Add logic for queueing requests that failed outside the H5P frame
Fix showing throbber when retrying because connection was reestablished
2019-04-03 13:09:18 +02:00
Thomas Marstrander 39d27ab9bb JI-1059 Add offline request queue with retry dialog
Add logic for adding extra class and hiding buttons in conf dialog
Update font files with throbber
2019-04-03 09:43:09 +02:00
Thomas Marstrander ada2f4009d JI-1059 Fix not showing toast if it is disabled 2019-04-01 15:10:37 +02:00
Thomas Marstrander 75453e872c JI-1059 Fix setting item name in request queue 2019-04-01 14:46:29 +02:00
Thomas Marstrander 49c48e29b3 JI-1059 Fix no options in request queue 2019-04-01 14:42:53 +02:00
Thomas Marstrander a934d5b3ec Merge branch 'master' of github.com:h5p/h5p-php-library 2019-04-01 12:06:07 +02:00
Thomas Marstrander e0eb03026a JI-1059 Add request queue events
Add dialog texts
2019-04-01 12:06:00 +02:00
Frode Petterson 052ad0ea81 Fix use filtered instead of params in .h5p files 2019-03-26 16:49:21 +01:00
Frode Petterson 7a85c115db HFP-2693 Fix dialog size on resize 2019-03-26 14:51:38 +01:00
Frode Petterson cdb53c5cfd Merge branch 'master' of github.com:h5p/h5p-php-library 2019-03-25 14:04:25 +01:00
Frode Petterson ac5dba1e19 Fix validation of old libraries before running content upgrade 2019-03-25 14:03:43 +01:00
Thomas Horn Sivertsen 4525d6383f Incorrect json (#58)
Default language is of type text and should therefore add quotes around the value like source, license and license_version do.
2019-03-21 10:30:09 +01:00
Thomas Marstrander d4931ec20a JI-1059 Add support for storing and resubmitting offline results
(cherry picked from commit cd869f8400)
2019-03-19 09:24:38 +01:00
Thomas Marstrander 8f7742ab0b Revert "JI-1059 Add support for storing and resubmitting offline results"
This reverts commit cd869f8400.
2019-03-18 11:02:42 +01:00
Thomas Marstrander cd869f8400 JI-1059 Add support for storing and resubmitting offline results 2019-03-18 10:58:13 +01:00
Frode Petterson 60fb6c96ca JI-1062 Remove unused code 2019-03-15 13:04:34 +01:00
Frode Petterson 366d8f2a0b JI-1062 Add interface function for saving files from .h5p
Make it easier for plugins to override the unpacking of the
package files.
2019-03-15 12:52:54 +01:00
Frode Petterson d38b3b1e8a JI-1062 Add option for max file size + total size limits 2019-03-14 14:53:25 +01:00
Frode Petterson bf9250d80b Bump Core API 2019-03-14 11:53:53 +01:00
Frode Petterson d05bc94d92 Add back custom libraries URL (Needed for Moodle) 2019-03-12 12:47:31 +01:00
Frode Petterson 71038f89ea Merge branch 'master' into release 2019-03-08 10:00:53 +01:00
Thomas Marstrander 1a09b1a30e Fix flickering for embedded content on iPads
see https://github.com/h5p/h5p-moodle-plugin/issues/237
2019-03-07 15:48:21 +01:00
Frode Petterson 7b7b35ea39 Merge branch 'master' of github.com:h5p/h5p-php-library 2019-03-07 15:02:13 +01:00
Frode Petterson 68e56dd8fd Fix reuse dialog not 100% visible on iPhone 2019-03-07 15:01:49 +01:00
Frode Petterson e9d08b973a Remove old libraryUrl due to conflict with Content Upgrade 2019-03-07 14:33:01 +01:00
Frode Petterson 53adda67c2 JI-1010 Add disable fullscreen feature for embeds 2019-03-07 12:57:45 +01:00
Frode Petterson fc044630bc JI-853 Add option to disable fullscreen on load 2019-03-07 12:02:02 +01:00
Frode Petterson 840f5dcb12 HFP-2541 Fix UX improvements when reusing content
(Moved Toast from Editor to Core)
2019-03-01 15:24:46 +01:00
Frode Petterson a5f1b49f6b HFP-2541 Fix small dialogs larger 2019-02-27 16:21:11 +01:00
Frode Petterson b64292af09 HFP-2541 Fix Dialog scrollbar on small dialogs 2019-02-27 16:04:37 +01:00
Frode Petterson 47d049afb2 HFP-2541 Add reuse dialog instead of download button 2019-02-27 15:03:58 +01:00
Frode Petterson 01550e7f11 HFP-2650 Add new fonts! 2019-02-22 15:12:43 +01:00
Frode Petterson d3b5b07669 Merge branch 'language-switcher' 2019-02-22 09:36:56 +01:00
Thomas Marstrander 801f3f33c3 HFP-2654 Add defaultLanguage to exported fields 2019-02-21 15:28:04 +01:00
Thomas Marstrander 32b0840ca6 HFP-2654 Add default language as part of metadata 2019-02-21 13:42:00 +01:00
Frode Petterson 7ee0c3372b Fix closing of aria-attribute 2019-02-18 15:12:13 +01:00
Frode Petterson 2b2184fa30
Fix closing of aria-attribute 2019-02-11 16:18:57 +01:00
Frode Petterson 415e101064 JI-942 Add extra check for library upload 2019-02-05 17:14:34 +01:00
Frode Petterson d1dd47be6f JI-942 Fix auto content upgrade to work with Drupal module 2019-02-05 13:15:50 +01:00
Frode Petterson aa723bcb40 Merge branch 'content-upgrade-on-upload' 2019-02-04 13:25:56 +01:00
Frode Petterson 741cd04d34 Merge branch 'release' 2019-02-04 13:22:28 +01:00
Frode Petterson e7a256da05 Merge branch 'master' into release 2019-02-04 13:22:15 +01:00
Frode Petterson f96d04cc27 JI-942 Add missing library error message 2019-02-01 13:03:27 +01:00
Frode Petterson c9e1ac9347 JI-942 Add better error handling for Content Upgrade 2019-01-28 16:01:08 +01:00
Frode Petterson 9cf3f4aa7f JI-942 Add restict save when a higher version is available 2019-01-22 15:27:27 +01:00
Frode Petterson bee7c550d9 Merge branch 'release' of github.com:h5p/h5p-php-library into release 2019-01-14 15:28:56 +01:00
Frode Petterson b6080a1a00 Update FS comment 2019-01-14 15:26:27 +01:00
Oliver Tacke bfb7b5600c Fix missing closing div for close button 2019-01-11 14:52:10 +01:00
Oliver Tacke c2d7b987cc Fix missing closing div for close button 2019-01-11 14:09:56 +01:00
Frode Petterson 8d30949969 Revert "Make eslint happy"
This reverts commit 132f25e14a.
2019-01-09 11:51:17 +01:00
Frode Petterson 9a7a343844 HFP-2508 Remove caching of pasted content
Objects can not be referenced by multiple widgets when used in the editor
2019-01-03 12:50:44 +01:00
Frode Petterson f19ca76461 HFP-2508 Fix reset of all subContentIds on Copy/Paste 2019-01-03 12:46:16 +01:00
Frode Petterson 4a9c3c7881 Merge branch 'master' of github.com:h5p/h5p-php-library 2018-12-20 16:17:58 +01:00
Frode Petterson 6f4c4d9cc3 HFP-1145 Bump Core API version due to improvements 2018-12-20 16:17:27 +01:00
Frode Petterson 2b474699b2 HFP-1145 Remove base64 data decoding since we now use Blob 2018-12-20 16:17:14 +01:00
thomasmars b43051c785 HFP-15474 Fix xAPI errors when previewing content 2018-12-20 15:07:40 +01:00
Frode Petterson 96694e4c70 Merge branch 'master' of github.com:h5p/h5p-php-library 2018-12-17 10:20:58 +01:00
Frode Petterson 57570db8d6 Merge branch 'semi-fullscreen' 2018-12-17 10:20:47 +01:00
Oliver Tacke 0678126f82 HFP-2398 Add aria-label to fullscreen buttons 2018-11-23 16:40:18 +01:00
Frode Petterson 152dfc0fb2 HFP-2433 Add CSS needed for Editor semi-fullscreen 2018-11-23 15:47:26 +01:00
Oliver Tacke 48f3805f94 HFP-2398 Remove aria-label in action bar
WAIA states it is *not* supposed to be used if there's a visible label
2018-11-23 15:13:41 +01:00
Oliver Tacke 2be06b2eb9 HFP-2396 Add aria-label to elements with role button 2018-11-23 13:10:07 +01:00
Oliver Tacke 132f25e14a Make eslint happy 2018-11-23 13:05:23 +01:00
Frode Petterson f2a9801879 Merge branch 'master' into release 2018-11-22 10:17:29 +01:00
Frode Petterson c438f9136e Merge branch 'release' 2018-11-22 10:16:37 +01:00
Frode Petterson 1cd7b67010 Merge branch 'master' of github.com:h5p/h5p-php-library 2018-11-16 12:41:24 +01:00
Frode Petterson ec9127d245 JI-915 Fix embed resizing issue with Chrome 2018-11-16 12:39:57 +01:00
Frode Petterson f7f2479b2a Fix new style array into old style array 2018-11-08 12:36:30 +01:00
Paal Joergensen a0e7bcd2af Merge branch 'stable' 2018-11-05 10:21:54 +01:00
Frode Petterson 85b278bd52 Fix variable $ 2018-11-02 10:25:35 +01:00
Frode Petterson c8ddb305ab Merge branch 'release' of github.com:h5p/h5p-php-library into release 2018-11-02 10:15:14 +01:00
Frode Petterson 39fc577fd5 Add prefilter that improves jQuery AJAX 2018-11-02 10:14:35 +01:00
Paal Joergensen 512a0de321 Merge branch 'release' of github.com:h5p/h5p-php-library into release 2018-11-02 10:04:10 +01:00
Paal Joergensen 898d975921 Avoid getting 'Invalid selected option in select' for existing content 2018-11-02 10:03:58 +01:00
Frode Petterson 6b3b3db575 Merge branch 'release' of github.com:h5p/h5p-php-library into release 2018-11-02 09:54:57 +01:00
Frode Petterson db022830a6 Add m4a extension to content files whitelist 2018-11-02 09:54:23 +01:00
Paal Joergensen d9940b81e2 Merge branch 'release' 2018-11-01 14:50:46 +01:00
Paal Joergensen 715fa6f803 HFP-2378 Add option to overwrite unset metadata fields 2018-11-01 14:42:12 +01:00
Frode Petterson e15f6d6678 Merge branch 'release' of github.com:h5p/h5p-php-library into release 2018-10-29 11:01:39 +01:00
Oliver Tacke 37c0593ff4 Merge remote-tracking branch 'origin/release'
Keep simpler version of simultaneous fixes
2018-10-26 14:58:22 +02:00
Oliver Tacke 066ea94b11 Fix warning in toDBArray()
Prevent accessing keys of metadata that don't exist
2018-10-26 09:35:24 +02:00
Paal Joergensen fd2ac997ef HFP-2328 Fix bug 2018-10-26 08:45:20 +02:00
Paal Joergensen 2e305ded71 HFP-2328 Reset metadata fields if needed 2018-10-23 14:59:50 +02:00
Paal Joergensen f661248b5a HFP-2329 Skip emty metadata fields for h5p.json 2018-10-23 13:15:55 +02:00
Paal Joergensen 82b50fc2f1 Fix code style 2018-10-23 11:25:46 +02:00
Paal Joergensen e316eff18d Don't display empty metadata fields in copyright popup 2018-10-23 11:10:06 +02:00
Paal Joergensen 85d2e2eb75 Don't filter params if library or params is not set 2018-10-23 10:56:44 +02:00
Paal Joergensen c4e52f4f29 Fixed bug for saving metadata settings 2018-10-17 13:53:38 +02:00
Paal Joergensen 8dafa5db91 Rename 'Change Log' to 'Changelog' 2018-10-16 09:53:11 +02:00
Frode Petterson 06985cca7c Fix h5p.json title field htmlencoded 2018-10-05 15:14:47 +02:00
Paal Joergensen 9081ca3128 JI-857 Validate metadata properly 2018-10-04 16:02:05 +02:00
Paal Joergensen e75745f0db metadataSettings returned as JSON, not string 2018-09-26 10:30:50 +02:00
Frode Petterson 7762f903c8 Add storing of content type title in metadata 2018-09-24 11:03:10 +02:00
Frode Petterson cb2acb21c8 Merge branch 'master' of github.com:h5p/h5p-php-library 2018-09-24 10:18:40 +02:00
Frode Petterson 64c8090d13 Add storing of content type title in metadata 2018-09-24 10:18:13 +02:00
Paal Joergensen 73f41e2dbd library.json: metadata -> metadataSettings 2018-09-21 15:09:31 +02:00
Frode Petterson d6e9c4ec09 Fix const not allowed in abstract class for PHP 5.3 2018-09-21 13:08:11 +02:00
Frode Petterson cfd15d8265 Merge branch 'master' of github.com:h5p/h5p-php-library 2018-09-21 10:12:59 +02:00
Frode Petterson 841d24cab8 Capitalize metadata titles 2018-09-21 10:05:00 +02:00
Paal Joergensen e2c8d6459a Numbers use format '%d' - only relevant for WordPress 2018-09-20 11:14:50 +02:00
Paal Joergensen 3566ac4141 HFP-2183 Default library.metadata property shall be 1 2018-09-18 15:02:12 +02:00
Paal Joergensen d391d486c9 HFP-2187 Only allow new license IDs 2018-09-18 14:26:36 +02:00
Paal Joergensen c9cb23e06c Add generic function for generating metadata JSON 2018-09-17 13:44:42 +02:00
Paal Joergensen 2bf38c5b00 Support title in metadata 2018-09-17 12:54:21 +02:00
Paal Joergensen 3d1c1cbe38 Autoload metadata class 2018-09-17 12:53:09 +02:00
Paal Joergensen eb766b0081 HFP-2184 Add utility class for handling metadata 2018-09-17 11:47:05 +02:00
Paal Joergensen 4fe8eca0f2 JI-857 Validate metadata 2018-09-17 08:58:38 +02:00
Paal Joergensen 74f9a84034 JI-857 Make metadata semantics describe the actual data structure 2018-09-17 08:45:18 +02:00
Paal Joergensen 8067277e63 JI-857 Add support for optgroup type in semantics 2018-09-17 08:41:31 +02:00
Paal Joergensen 425aac5d33 HFP-2183 Set metadata when saving library 2018-09-11 11:50:51 +02:00
Paal Joergensen 9e4db6cdd9 Merge branch 'master' of github.com:h5p/h5p-php-library 2018-09-10 11:31:40 +02:00
Paal Joergensen e257e5ecff HFP-2185 Treat major & minor version as int (not string) 2018-09-10 11:30:57 +02:00
Frode Petterson 394a4aace3 Merge branch 'master' of github.com:h5p/h5p-php-library 2018-08-31 17:29:54 +02:00
Frode Petterson 97eab5c3ce JI-848 Add changing main content metadata in upgrade
(except for title!)
2018-08-31 17:29:11 +02:00
Oliver Tacke 2d3fe61371 Merge branch 'master' of https://github.com/h5p/h5p-php-library 2018-08-31 09:44:18 +02:00
Oliver Tacke 775b45ab6c HFP-2094 Add metadata property to validation of library.json 2018-08-31 09:32:23 +02:00
Paal Joergensen 43b9703fc9 Merge branch 'master' of github.com:h5p/h5p-php-library 2018-08-30 12:35:56 +02:00
Paal Joergensen e74fb6009a Use title from metadata object when creating xAPI stmt 2018-08-30 12:35:46 +02:00
Frode Petterson e094da76fa HFP-1900 Remove metadata/extras from upgrade for main content 2018-08-30 12:33:24 +02:00
Frode Petterson 768eb2a64b
Remove unkown todo comment 2018-08-29 14:30:31 +02:00
Paal Joergensen 8c374be79d HFP-1871 Improve addon feature 2018-08-28 08:08:56 +02:00
Paal Joergensen 6959f65022 HFP-1871 Add library config as a generic feature 2018-08-27 14:53:17 +02:00
Paal Joergensen bbe99e4db8 Merge branch 'HFP-1871-math-display' 2018-08-27 13:53:10 +02:00
Paal Joergensen ee0e97e17b HFP-1871 Skip loading semantics for addons 2018-08-27 13:52:33 +02:00
Paal Joergensen 0c7df179a7 Fix content upgrade bug 2018-08-24 12:55:42 +02:00
Paal Joergensen 6c4f904079 Generalize addons 2018-08-23 10:24:20 +02:00
Pål Jørgensen b1db442554
Merge pull request #53 from beheist/dev-bh-fix-header-case
BUGFIX: Fix capitalization of the "Content-Type" HTTP header
2018-08-06 14:15:32 +02:00
Bastian Heist 3a8847424c BUGFIX: Fix capitalization of the "Content-Type" HTTP header 2018-08-04 13:46:52 +02:00
Oliver Tacke 6d50bae108 HFP-1905 Complete validation for h5p.json 2018-08-01 17:30:30 +02:00
Oliver Tacke 64e5ab4424
HFP-1871 Fix missing variables 2018-08-01 10:55:13 +02:00
Oliver Tacke d068b82ff5 HFP-1871 Fix sanitization of containsMath 2018-07-30 14:52:36 +02:00
thomasmars 5be4ba1222 JI-781 Support regex in core for when CORS attributes is set 2018-07-30 14:28:02 +02:00
Oliver Tacke 9314c55994 HFP-1871 Clean code 2018-07-26 19:34:46 +02:00
Oliver Tacke 942fd922bc HFP-1871 Add general function to get values from library json config 2018-07-26 10:37:16 +02:00
Oliver Tacke 62b6345c49 HFP-1871 Use param from MathDisplay library.json for configuration 2018-07-25 15:08:29 +02:00
Oliver Tacke a55379adcf Fix Array use 2018-07-24 10:36:43 +02:00
Oliver Tacke c45be49a4f Merge branch 'master' of https://github.com/h5p/h5p-php-library 2018-07-23 15:30:31 +02:00
Oliver Tacke d3a63dd756 HFP-2133 Fix additional space 2018-07-23 15:30:10 +02:00
Oliver Tacke 023613c131 HFP-2131 Fix additional space 2018-07-23 15:26:09 +02:00
Oliver Tacke e22766157b HFP-2133 Add Creative Commons acronyms 2018-07-23 14:57:14 +02:00
Oliver Tacke 9ee5fb9907 HFP-2110 Refactor to have a plain setClipboard function
Custom editors handled storing data to the clipboard on their own,
so the datainclipboard trigger was missing for some functionality.
H5P.clipboardify() however doesn't cope with additional information
that the custom editors can deal with.

Custom editors that prepare their own clipboard data can now use
H5P.setClipboard() directly and set their data while other elements
will be informed about the clipboard change.

Also relevant for HFP-2111 and HFP-2112.
2018-07-18 10:45:14 +02:00
Oliver Tacke a295d7d434 HFP-1925 Fix typo 2018-07-12 10:07:01 +02:00
thomasmars 579ba96b49 HFP-1942 Add crossorigin api call.
Update minor version of core since interface changes
2018-07-11 14:44:45 +02:00
Oliver Tacke b1a01b728d Fix update script bug that was introduced with adding the hasmetadata field 2018-07-11 09:33:59 +02:00
Frode Petterson a015d1a134 Merge branch 'HFP-1905-metadata-system' 2018-07-03 15:49:21 +02:00
Frode Petterson 10aaa38844 HFP-2027 Fix copy-paste icons 2018-07-03 10:34:26 +02:00
Oliver Tacke e241ec6963 HFP-1905 Fix for LibraryNames with many elements 2018-06-28 18:36:58 +02:00
Oliver Tacke 14bcb913b7 HFP-1905 Include metadata in findCopyrights 2018-06-28 18:21:30 +02:00
Oliver Tacke 972c7a13f6 HFP-2074 Remove CC prefix in license names
Now that the optgroup feature is in place, the prefix is obsolete
2018-06-28 11:44:01 +02:00
Oliver Tacke ae85ea3f2a Merge branch 'HFP-1905-metadata-system' of https://github.com/h5p/h5p-php-library into HFP-1905-metadata-system 2018-06-27 16:01:20 +02:00
Oliver Tacke 9432d80b23 HFP-2075 Don't require protocol for metadata source field 2018-06-27 15:59:34 +02:00
Frode Petterson 1605581608 Merge branch 'copy-paste' into HFP-1905-metadata-system 2018-06-27 13:42:13 +02:00
Frode Petterson d24fd0e667 HFP-2072 Improve copy-paste API behavior 2018-06-26 11:52:57 +02:00
thomasmars d963a23a15 HFP-2074 Add optgroup to Creative Commons licenses in metadata dialog. 2018-06-26 10:51:48 +02:00
Frode Petterson b1446e8d60 HFP-2027 Add copy paste helpers to core 2018-06-25 15:59:17 +02:00
Oliver Tacke 4d286b0bdb Fix HFP-1905 Add CC for creative commons license names 2018-06-25 14:14:51 +02:00
Oliver Tacke d113809e80 HFP-1905 Fix source and link in copyright view 2018-06-25 14:14:13 +02:00
Oliver Tacke 8190fe1d42 HFP-1896 Fix metadata form error handling 2018-06-25 11:31:09 +02:00
Oliver Tacke 2a53b7bb7b HFP-2059 Accept objects as library options, too
Compound content types should be able to deactivate the metadata
button for their subcontent types. This should be achievable
by amending the options property of a library field.

The options array can not either contains strings with library names
or objects with the property "name" (mandatory) and further properties,
one of them being "hasmetadata"
2018-06-22 13:45:59 +02:00
Oliver Tacke 17162f32ef HFP-2052 Fix undefined source 2018-06-20 16:25:27 +02:00
Thomas 30cb2aec45
Merge pull request #50 from tsivert/max_score
Max score
2018-06-19 09:17:12 +02:00
Thomas Horn Sivertsen 930f85e0fb HFP-1806
Removed unused changes, fixed indentation
2018-06-18 11:24:04 +02:00
Oliver Tacke 04707a9f8a HFP-1871 Add function to load MathDisplay if params contain math 2018-06-13 18:36:23 +02:00
Oliver Tacke e179ec2934 HFP-2052 Make changes requested in UX review
- Add link for source
- Change URLs for licenses
2018-06-13 16:41:49 +02:00
Thomas Horn Sivertsen a59640672d HFP-1806
- fixed PhpDoc
- only load presave.js when editing a H5P
- moved loading logic from core to editor
- removed unused code
2018-06-07 12:43:12 +02:00
Oliver Tacke 367763a215 Merge remote-tracking branch 'origin/master' into HFP-1905-metadata-system 2018-06-05 13:07:01 +02:00
Oliver Tacke be77130fef HFP-1905 Require words for author roles 2018-06-05 08:54:12 +02:00
Oliver Tacke ea722126ff HFP-1905 Fix property naming and validation defaults
Fix property naming for more harmony (and peace in the world)
Fix validation on uploading content by adding Author as a role
2018-06-04 15:44:04 +02:00
Oliver Tacke 0fbc6ef5a8 HFP-1905 Fix potential undefined values 2018-06-01 17:44:21 +02:00
Oliver Tacke 8f45ea4d79 HFP-1905 Fix finding copyright edge case bug 2018-06-01 15:45:09 +02:00
thomasmars 3ce0adf418 HFP-1942 Add crossorigin api call.
Update minor version of core since interface changes
2018-06-01 11:09:45 +02:00
Oliver Tacke a30a93e62e HFP-1897 Set correct field types and boundaries 2018-05-29 17:23:06 +02:00
Oliver Tacke 47be831f49 HFP-1897 Fix author as default role 2018-05-29 17:00:56 +02:00
Oliver Tacke 00deb02aa7 HFP-1897 Set author as default role, change placeholder text for change 2018-05-28 18:01:28 +02:00
Oliver Tacke 3deda27f9b HFP-1898 Move mocked semantics to backend 2018-05-25 18:38:42 +02:00
Frode Petterson 942a083afa JI-575 Fix content upgrade script 2018-05-16 15:16:34 +02:00
Paal Joergensen d99ab7eda2 HFP-1994 Bump core minor version 2018-05-08 11:30:54 +02:00
Frode Petterson 022695ac74 JI-575 Add support for file aggregation 2018-05-03 10:27:06 +02:00
Oliver Tacke 58597460f6 HFP-1905 Fix updating for scripts with old update functions
"params" (and "extras", e.g. metadata) flow through each update function
and are changed if necessary. Since "extras" was added later and old
update functions don't return it, we need to ignore undefined values
-- or change every single update function in all content types.
2018-04-09 11:43:48 +02:00
Oliver Tacke 3b38e273eb HFP-1905 Bump minor core version number 2018-04-06 17:11:33 +02:00
Oliver Tacke fbc21f6368 HFP-1905 Remove console output 2018-04-05 17:22:31 +02:00
Oliver Tacke ef063ce5cb HFP-1905 Fix image in "rights of use" view 2018-04-05 17:17:56 +02:00
Oliver Tacke 83e3c58ba3 HFP-1943 Include metadata information in "rights of use" popup
Add copyright information of main content in popup
Add copyright information of subcontent in popup
HFP-1902 is intended to make the styling better
2018-04-04 15:46:30 +02:00
Oliver Tacke 95d99d0ad3 HFP-1905 Add update functionality for metadata 2018-04-03 15:17:46 +02:00
Oliver Tacke b28624ba8e HFP-1905 Allow metadata as keyword for subcontent 2018-03-26 17:44:00 +02:00
Oliver Tacke c589285351 HFP-1905 Fix unset values for array fields
Some array fields were filled with undefined and lead to warnings.
2018-03-26 11:24:26 +02:00
Oliver Tacke 6ef2f96e8b HFP-1905 Add logic for download/upload
Add metadata fields to h5p.json
2018-03-23 13:11:00 +01:00
Oliver Tacke 011c7df675 HFP-1905 Add metadata to contentData 2018-03-16 20:11:08 +01:00
Frode Petterson 0fb35a3f7c
HFP-1869 Fix fullscreen button icon not centered 2018-02-28 14:16:02 +01:00
Paal Joergensen 78c19d6779 Merge branch 'drsassafras-master' 2018-02-20 08:46:00 +01:00
Paal Joergensen 4a0739f1c4 Merge branch 'master' of https://github.com/drsassafras/h5p-php-library into drsassafras-master 2018-02-20 08:45:41 +01:00
Paal Joergensen 3ed15f2249 Remove old H5P logo 2018-02-20 08:34:51 +01:00
drsassafras 24bbbf08ae lossless image compression 2018-02-16 01:17:35 -05:00
Thomas Horn Sivertsen 615bac7c08 HFP-1806
Add presave for development and public libraries
2018-02-01 12:18:31 +01:00
Thomas Horn Sivertsen 04edd73855 HFP-1806
Formatting code + adding comments.
2018-01-19 14:56:07 +01:00
Thomas Horn Sivertsen 1b079d36f1 HFP-1806
Load presave script if present in library.
2018-01-19 14:42:43 +01:00
Paal Joergensen 95901159d0 HFP-1768 Send core api version as a single element 2017-11-23 15:15:03 +01:00
Paal Joergensen 90d1e7579d HFP-1768 Add api core version to requests to api.h5p.org 2017-11-23 11:39:03 +01:00
Frode Petterson f3efd217c8 HFP-1678 Remove unsued variable 2017-11-20 16:12:22 +01:00
Paal Joergensen f91f2e82fb HFP-1678 Add error code to error messages 2017-11-16 16:24:29 +01:00
Frode Petterson 6798e0bbbf HFP-924 Add singular version of plural install info 2017-11-15 13:24:56 +01:00
Frode Petterson 717edc2a6f HFP-924 Add support for more detailed messages when using AJAX 2017-11-14 15:06:54 +01:00
Frode Petterson 5919b64c2a Clean up syntax and avoid empty values 2017-11-06 09:59:46 +01:00
Frode Petterson b418d24c29
Merge pull request #42 from icmcnamara/embed-additional-head-tags
Add optional additional head tags support to embed
2017-11-06 09:53:00 +01:00
Ian McNamara 07ac995cf0 Prints optional additonal head tags in embed.php
Works in conjunction with modifications to class-h5p-php-admin.php
in the core h5p plugin. Allows other plugins to add code to be
inserted into the head of the embeded iframe generated by embed.php.

See discussion of this issue here:
https://github.com/h5p/h5p-wordpress-plugin/issues/58#issuecomment-337906304
2017-11-01 16:08:14 -05:00
Frode Petterson 500c264b88 Merge branch 'master' of github.com:h5p/h5p-php-library 2017-08-28 10:49:57 +02:00
Frode Petterson dfdfb3bd99 Add prevent deleting sub content of linked directories
Sometimes devs may link to library folders elsewhere, then we
should prevent traversing and deleting the linked content.
Default behavior now is to remove the link and not its content.
2017-08-28 10:45:54 +02:00
Paal Joergensen cbbff0e296 Merge branch 'release' 2017-08-25 11:19:53 +02:00
Paal Joergensen 0252beb03d Revert "HFP-1407 Improve robustness of content-id retrival"
This reverts commit e3d7cf2562.
2017-08-25 11:18:59 +02:00
Paal Joergensen 64f170b8a3 Define H5P Hub endpoints one place in code 2017-08-24 12:40:53 +02:00
Tom Arild Jakobsen e3d7cf2562 HFP-1407 Improve robustness of content-id retrival
The code made an assumption that the $element.parent() would contain
the [data-content-id] which isn't always true.

Changed the code, so that it looks up the parent with [data-content-id].
2017-08-23 15:22:29 +02:00
Frode Petterson f090e651e1 HFP-1405 Fix targeting wrong parent iframe element
Just in case there are two elements with the same ID avoid misbehaving
2017-08-23 12:44:15 +02:00
Paal Joergensen 7c3a322fda HFP-1317 Made library detail pager behave good 2017-08-07 16:38:09 +02:00
Frode Petterson f112f761c3 Prevent JS error when no pager is available 2017-08-04 11:04:10 +02:00
Frode Petterson 0dddbf654e Merge branch 'master' into release 2017-08-02 13:10:27 +02:00
Frode Petterson 7728243c18 Improve hashing logic 2017-07-27 13:36:51 +02:00
Frode Petterson b6019ade21 Merge pull request #40 from cornelles/validate-text-font-family
Fixing font-family regex pattern when validating text
2017-07-26 10:03:20 +02:00
Cornel Les 75803f8dfb Fixing font-family regex pattern when validating text 2017-07-20 17:54:12 +03:00
Frode Petterson 3a2cd46f6a Merge branch 'HFP-1174-feedback' 2017-07-13 13:30:39 +02:00
Frode Petterson cc5440cc4a Merge branch 'master' into HFP-1100-improve-file-handling 2017-07-07 10:59:38 +02:00
Frode Petterson b1531bcbc0 Add support for temporary file suffix
HFP-1100
2017-07-07 10:51:57 +02:00
Timothy Lim 91ff99145a HFP-1258 Whitelist .webvtt 2017-07-07 10:11:23 +02:00
Timothy Lim cc7caa6604 HFP-1258 Whitelist .vtt extension 2017-07-07 09:56:24 +02:00
Frode Petterson 6444c1443b Bump coreApi due to editor changes
HFP-1174
2017-06-26 10:43:59 +02:00
thomasmars f07ce1b3c3 Merge branch 'master' of https://github.com/h5p/h5p-php-library 2017-06-22 10:56:42 +02:00
thomasmars d2746b18b4 Make fullscreen button keyboard accessible
HFP-1199
2017-06-22 10:56:15 +02:00
Tom Arild Jakobsen 9ea6f277e1 Merge branch 'master' of github.com:h5p/h5p-php-library into HFP-574-remove-override-settings 2017-06-07 11:49:47 +02:00
Frode Petterson 278586ef58 Add forgotten symbol 2017-06-06 14:21:18 +02:00
Frode Petterson 3192f0fe19 Add default license when no version is selected 2017-06-06 13:51:51 +02:00
Paal Joergensen 46d772cb51 Added missing parameter in getLibraryUsage [HFP-1067] 2017-05-31 11:17:28 +02:00
Frode Petterson aaa0861355 Fix copyright not being display processes correctly
HFP-1079
2017-05-31 09:33:10 +02:00
Frode Petterson 9adc92d3c4 Move license definition for localization to work
HFP-1079
2017-05-30 15:43:26 +02:00
Frode Petterson 59fd08594f Support localized licenses
HFP-1079
2017-05-30 15:23:25 +02:00
Frode Petterson 42e0c99fd3 Add version info to license
HFP-1079
2017-05-30 14:12:22 +02:00
thomasmars fa31c56dce Fixed returnBytes function return correct amount of bytes 2017-05-29 11:18:12 +02:00
thomasmars 0ce7d66c3a Cast bytes to int before multiplying it.
Removes warning in PHP 7.0+
2017-05-25 13:52:50 +02:00
thomasmars d1bbed49fc Don't assume fetchLibrariesMetadata is AJAX
HFP-1103
2017-05-22 12:57:43 +02:00
Tom Arild Jakobsen 87bd3c7e11 Resize h5p container instead of body by default. HFP-574 2017-05-11 17:09:44 +02:00
Tom Arild Jakobsen f277fed4d1 Set overlay and dialog to be 'position: absolute;' again. HFP-574 2017-05-10 13:50:57 +02:00
Tom Arild Jakobsen dfc2e52ba5 Merge branch 'master' of github.com:h5p/h5p-php-library into HFP-574-remove-override-settings 2017-05-10 12:45:55 +02:00
Tom Arild Jakobsen 481322e6ae Deprecate 'overrideSettings'
* Deprecate and log warning to console when 'overrideSettings' is used
 * Change confirmation dialog be 'fixed' e.g relative to viewport instead of
   and arbitrary relative parent element
 * Same for the overlay mask
 * Set minimum height on body element, to fit confirmation dialog
 * Remove the minimum height on close dialog

Fixes HFP-574
2017-05-08 14:17:29 +02:00
Paal Joergensen 677adb0d8a HFP-1035 Whitelisted wav files 2017-05-03 10:02:27 +02:00
Paal Joergensen 3fda439aa1 Bumping core version 2017-05-02 10:30:27 +02:00
Timothy Lim fb76e09e8c HFP-967 Revert a revert
Ensures that latest code from stable is added.
2017-04-25 16:30:52 +02:00
Timothy Lim 56e453f6c1 HFP-967 Apply correct changes 2017-04-25 15:59:25 +02:00
Timothy Lim edb9e6244c Revert "HFP-967 Update content validator to handle headers and tables"
This reverts commit 9ee5d2ebe7.
2017-04-25 15:58:28 +02:00
Timothy Lim 8d01baca8e Merge branch 'master' of https://github.com/h5p/h5p-php-library 2017-04-25 15:37:18 +02:00
Timothy Lim 9ee5d2ebe7 HFP-967 Update content validator to handle headers and tables 2017-04-25 15:37:04 +02:00
Frode Petterson 60c822b47e Merge branch 'stable' 2017-04-20 15:02:15 +02:00
Frode Petterson 41cee98970 Merge branch 'release' into stable 2017-04-18 15:36:08 +02:00
Frode Petterson bd851f2929 Remove http_response_code()
Not supported prior to PHP 5.4
HFP-959
2017-04-18 14:54:58 +02:00
thomasmars d4c90e716d Merge branch 'CheckFileExistsBeforeZip' of https://github.com/mannes/h5p-php-library into mannes-CheckFileExistsBeforeZip 2017-04-18 10:44:37 +02:00
Paal Joergensen da568e4b8a Merge branch 'release' into stable 2017-04-18 09:26:01 +02:00
Frode Petterson dcbb5a2a18 Merge branch 'master' into release 2017-04-12 13:17:04 +02:00
thomasmars d50d98297b Set action frame button sizes in pixels to be IE11 compat
Frame is always set in pixels anyway, so should not be a problem
HFP-939
2017-04-11 19:34:58 +02:00
Paal Joergensen 727e88908a Made statistics being sent on updateContentTypeCache [HFP-931] 2017-04-11 14:51:27 +02:00
thomasmars 2ff14ecd37 Remove key message when registering with Hub until it is back.
JI-115
2017-04-11 13:02:44 +02:00
Frode Petterson d81fa06499 Check correct variable
JI-114
2017-04-11 09:35:17 +02:00
Frode Petterson c475db843d Separate statistics reporting from 'Use H5P Hub' option
JI-114
2017-04-10 14:09:02 +02:00
thomasmars c4f2b26116 Make sure contentId are handled when passed as strings 2017-04-09 17:43:56 +02:00
Tom Arild Jakobsen 86ee19905e Fix confirmation dialog confirm icon
* Position icon up a bit
 * Fix icon not showing in IE at all

Relates to: HFP-889
2017-04-07 10:28:17 +02:00
thomasmars a0069235f1 Make it possible to move content directory to existing content
HFP-899
2017-04-06 16:30:26 +02:00
Frode Petterson 29fd758bf5 Update phpdoc
HFP-884
2017-04-04 12:44:22 +02:00
Frode Petterson c5974e6212 Update fetch api 2017-04-03 14:51:54 +02:00
Frode Petterson 280946979f Remove update functionality
JI-111
2017-04-03 13:33:47 +02:00
Svein-Tore Griff With 98f1ac4abb Merge pull request #38 from otacke/HFP-878
Avoid accidently selecting things in the toolbar
2017-04-03 10:22:12 +02:00
otacke 8cb9e8b0d1 remove non standard touch CSS 2017-03-31 13:57:11 +02:00
otacke bd83ddc5e7 make actionbar buttons unselectable 2017-03-31 13:36:40 +02:00
Frode Petterson bfda796ab7 Allow processing after export is generated 2017-03-30 13:55:44 +02:00
Timothy Lim 33406c69cc JI-89 Fix spelling error 2017-03-28 13:32:30 +02:00
thomasmars d3d5dbe1a7 Removed api_version from site data, since it is part of url now. 2017-03-21 14:48:52 +01:00
thomasmars 3611da5921 Only send the necessary data when registering a site
Merge in the rest of the metadata when fetching ct cache
HFP-489
2017-03-18 15:39:27 +01:00
thomasmars 4098f7a0d9 Merge branches 'HFP-822-ajax-refactor' and 'master' of https://github.com/h5p/h5p-php-library into HFP-822-ajax-refactor
# Conflicts:
#	h5p.classes.php
2017-03-16 20:01:08 +01:00
thomasmars fd93b30a38 Fixed return statement of fetch libraries metadata
HFP-489
2017-03-16 10:09:52 +01:00
thomasmars 675c87df68 Added more detailed messages when site is or fails to register
HFP-489
2017-03-16 10:01:41 +01:00
thomasmars 93e9d6e0ec Register site with new endpoint if no site is already registered
HFP-489
2017-03-16 09:51:46 +01:00
thomasmars 75b8f9efd6 Fixed move content folder bug
HFP-822
2017-03-14 15:00:14 +01:00
thomasmars 754346992b Minor documentation details 2017-03-14 14:21:36 +01:00
thomasmars 1b19f2701d Make data optional in fetchExternalData function
HFP-822
2017-03-13 14:56:01 +01:00
thomasmars cf3022af43 Moved editor specific functionality to editor interface
Refactored hub endpoints into an abstract class for consistency and easier lookup
Fixed bug in moveContentDirectory function
HFP-822
2017-03-12 17:56:36 +01:00
thomasmars 0970f74b43 Made it easier to use ajax functions in core with existing endpoints
Moved common ajax functionality to core.
Created interface functions for ajax functionality that must be handled by each plugin
Re-encapsulated storage functions to keep a clean interface
Added function for moving temp files to the editor
HFP-822
2017-03-11 18:43:08 +01:00
Paal Joergensen b3e0539261 Resetting [HFP-805] 2017-03-10 14:29:49 +01:00
Frode Petterson 907396e49b Merge branch 'master' of github.com:h5p/h5p-php-library 2017-03-10 13:06:31 +01:00
Frode Petterson 2b327323e1 Add missing default 2017-03-10 13:06:19 +01:00
Svein-Tore Griff With 58d5eef422 Document ios landscape / portrait hack 2017-03-10 08:59:46 +01:00
Svein-Tore Griff With 918084647f Merge pull request #36 from lukemuller/master
Fixed iOS bug for Image Hotspots and iFrames
2017-03-10 08:56:09 +01:00
Luke Muller 4999862689 Fixed iOS bug for Image Hotspots and iFrames
There is a bug in iOS with IFrame's that when changing orientation width: 100% stays at landscape rather than going back to portrait. https://bugs.webkit.org/show_bug.cgi?id=155198. Tested on iOS 10 iPhone 7 on image hotspot.
2017-03-10 12:31:20 +10:00
thomasmars 16982c0207 Merge branch 'master' of https://github.com/h5p/h5p-php-library 2017-03-09 17:36:27 +01:00
thomasmars a720d46548 Make it easier to send files to the editor
HFP-822
2017-03-09 17:36:20 +01:00
Andreas Nergaard 358424f2be HFP-826 Added 2 new icons to the core font. 2017-03-08 12:25:56 +01:00
Paal Joergensen f247bbdfe8 Improved json returned from content type cache endpoint 2017-03-07 11:24:08 +01:00
Paal Joergensen 914ee55ac5 Fixed broken core - using wrong function name [HFP-805] 2017-03-07 10:36:49 +01:00
Paal Joergensen 37f4399ab4 Added interface function that returns library file URL [HFP-805] 2017-03-07 10:25:52 +01:00
Paal Joergensen c8b123c5c3 Using local icon if present (HFP-807) 2017-03-07 09:46:16 +01:00
thomasmars ae56eef91d Use ID instead of library_id for lbiraries
HFP-793
2017-03-03 15:45:19 +01:00
thomasmars a95323948e Improved upload size error msg
HFP-509
2017-03-03 14:47:15 +01:00
thomasmars 217c2006a4 Separate between setup error messages and disabling hub
HFP-509
2017-03-03 11:29:09 +01:00
thomasmars 318b9f4819 Restrict LRS dependent content if set
HFP-797
2017-03-03 10:43:39 +01:00
thomasmars 410c2a9ae1 Added permission check for restricted local libraries
Renamed cached library map function to something more appropriate
HFP-797
2017-03-03 10:33:21 +01:00
thomasmars 0af411bac8 Send json as camelCase
HFP-794
2017-03-02 14:39:36 +01:00
thomasmars c0e82edfb4 Fixed endpoint address
HFP-794
2017-03-02 14:25:30 +01:00
thomasmars 79e32f0a7f Added proper protocol for endpoints
HFP-794
2017-03-02 14:21:11 +01:00
thomasmars 515365d8df Add common hub endpoint to core
HFP-794
2017-03-02 14:14:26 +01:00
thomasmars 34b8a2fb58 Updated phpdocs
HFP-797
2017-03-02 13:10:00 +01:00
thomasmars 16228b3086 Merge branch 'master' of https://github.com/h5p/h5p-php-library 2017-03-02 12:49:45 +01:00
thomasmars 0e2edff5a8 Helper functions for ct cache
Generates properly formatted json from content type cache
Merges content type cache with locally installed libraries
HFP-797
2017-03-02 12:48:30 +01:00
Paal Joergensen 3dbb8fae70 Added check for icon.svg [HFP-806] 2017-03-02 11:43:45 +01:00
Frode Petterson 90fd9a2a28 Merge branch 'master' of github.com:h5p/h5p-php-library 2017-03-02 10:18:38 +01:00
Frode Petterson 66409f1a14 Merge branch 'JI-92-path-fix' 2017-03-02 10:18:28 +01:00
Frode Petterson 179601657c Remove prefix from file path
Should already be complete at this point.
JI-92
2017-03-02 10:17:16 +01:00
Frode Petterson b6ca0cd2df Merge branch 'master' of github.com:h5p/h5p-php-library 2017-02-28 13:05:50 +01:00
Frode Petterson 0f08031abf Allow Core to override permission check
HFP-504 HFP-505
2017-02-28 13:05:11 +01:00
thomasmars 362464ad56 Updated endpoint
JI-90
2017-02-27 16:01:08 +01:00
Frode Petterson a83ea9999d Merge branch 'master' of github.com:h5p/h5p-php-library 2017-02-27 14:15:17 +01:00
thomasmars 3068d58b2b Make update content type cache function public
JI-53
2017-02-24 17:00:43 +01:00
thomasmars 933b95f5ce Allow ajaxError to specify an error code as well.
JI-53
2017-02-24 16:34:16 +01:00
thomasmars ec5a164971 Send in current content type cache update timestamp when updating content type cache
JI-53
2017-02-24 16:06:55 +01:00
thomasmars 0641b3b824 Restored old package and tutorial functionality
Removed uuid registration, will need separate endpoint
Use time instead of localized time when setting ct cache update time
Changed variable names to match API docs
2017-02-24 15:38:49 +01:00
thomasmars 2b5a10bec6 Merge branches 'HFP-502-install-errors' and 'master' of https://github.com/h5p/h5p-php-library 2017-02-24 14:11:07 +01:00
thomasmars 1dec6453fd Check write access of H5P folder
HFP-502
2017-02-24 09:47:44 +01:00
thomasmars fb1ed589e5 Style for drupal form seems to live here
JI-47
2017-02-23 17:00:43 +01:00
thomasmars 585f4d238a Fixed incorrect hub enabled value after server check
HFP-502
2017-02-23 15:22:55 +01:00
thomasmars e88a23d265 Changed hub variable name to match new settings name
HFP-502
2017-02-23 14:54:37 +01:00
thomasmars a32f210188 Fixed enable hub button state after confirming dialog
HFP-502
2017-02-23 14:22:56 +01:00
thomasmars aa861fc8ce Make disable hub, into enable hub to match the checkbox state.
Implemented write access check
HFP-502
2017-02-23 14:20:56 +01:00
thomasmars 183ec0a930 Pass postData as array when fetching external ct cache data
JI-54
2017-02-23 13:28:59 +01:00
thomasmars 4a8a791327 Fixed default arg for update content type cache
JI-53
2017-02-23 12:43:18 +01:00
thomasmars 952a07456c Merge fetch libraries metadata and update content type cache into one request.
Use fetchExteralData instead of adding new functionality since we're now using post.
JI-53
2017-02-23 11:33:39 +01:00
Frode Petterson bdf60a943d Use realpath() instead of document root = safer
Document root might be rewritten or incorrect for some sites(observed on multiple WP)
HFP-784
2017-02-23 11:18:59 +01:00
Frode Petterson a6b01f510f Use realpath() instead of document root = safer
Document root might be rewritten or incorrect for some sites(observed on multiple WP)
HFP-784
2017-02-23 11:18:45 +01:00
thomasmars ff531a157c Improved error msg and check for openssl extension
HFP-502
2017-02-22 18:29:21 +01:00
thomasmars 1f7d03dfd4 Don't use verb in setting name.
HFP-502
2017-02-22 18:03:23 +01:00
thomasmars f556cde385 Added localized time interface for displaying correct time of content type cache update.
JI-53
2017-02-22 16:20:09 +01:00
thomasmars 58cbfc7f0c Moved update content type cache into library core and interface.
JI-53
2017-02-22 14:50:45 +01:00
Frode Petterson 79fa5076f2 Use realpath() instead of document root = safer
Document root might be rewritten or incorrect for some sites(observed on multiple WP)
HFP-784
2017-02-22 11:25:05 +01:00
thomasmars 24fd6b1bc5 Made server setup check return errors instead of setting them.
This is useful in cases where you want to process the error messages differently
HFP-502
2017-02-22 11:14:35 +01:00
thomasmars 46d4d403f4 Added default selectors for disable hub elements.
HFP-503
2017-02-21 20:01:30 +01:00
thomasmars c4affb23dd Added confirmation dialog functionality when disabling hub.
Refactored server setup check into check and var updates.
Moved bytes string parsing out of server setup check and fixed naming convention.
Fixed indentation to match library core instead of Moodle style.
2017-02-21 17:37:01 +01:00
thomasmars c70f8521bb Use core naming convention for requirements function
HFP-502
2017-02-21 14:31:01 +01:00
thomasmars ff496d9a38 Check for H5P requirements.
HFP-502
2017-02-21 14:01:49 +01:00
Frode Petterson c4b88c3992 Add reveling field support for settings
HFP-495
2017-02-20 15:06:42 +01:00
Andreas Nergaard 8f132cfffb Merge branch 'master' into HFP-186-tutorial-example-links 2017-02-09 17:23:18 +01:00
Andreas Nergaard c41d001754 HFP-750 Adding fixed icon. 2017-02-09 14:09:25 +01:00
Andreas Nergaard 3e9277c0f8 HFP-750 Updated h5p core font from 16 to 17. 2017-02-09 12:45:51 +01:00
Frode Petterson e66e6c5d76 Only clone content folder if it exists
HFP-731
2017-02-08 10:57:16 +01:00
Frode Petterson bb71ea20a3 Update JSDoc 2017-02-07 13:48:42 +01:00
Frode Petterson ea3b86dcfe Development mode must be set by default
HFP-724
2017-02-07 12:55:53 +01:00
Frode Petterson b555e4d7a4 Merge branch 'master' of github.com:h5p/h5p-php-library 2017-02-06 14:40:56 +01:00
Frode Petterson 26d0a3a341 Double check that contents settings exist
… before using them.
HFP-714
2017-02-06 14:39:59 +01:00
Frode Petterson 39d7ddc6b8 Merge branch 'master' of github.com:h5p/h5p-php-library 2017-01-31 13:36:32 +01:00
Frode Petterson e548b3575f Add custom xAPI events for action toolbar buttons 2017-01-31 13:35:23 +01:00
Timothy Lim 3b9dd95683 HFP-580 Update regex 2017-01-30 14:49:09 +01:00
Paal Joergensen ef4165a11d Fixed developer mode for Drupal 2017-01-30 11:38:34 +01:00
Paal Joergensen 6ab68eb6e2 Minor cleaning 2017-01-30 08:43:47 +01:00
Frode Petterson 9abe7ef321 Merge branch 'master' of github.com:h5p/h5p-php-library 2017-01-26 15:35:53 +01:00
Timothy Lim 5dc9e3ddd1 HFP-580 Handle language files with hyphens 2017-01-26 15:31:51 +01:00
Frode Petterson bdec1319ed Always return fileId for tracking tmp files 2017-01-26 14:56:36 +01:00
Frode Petterson 03271418f0 Use correct variable 2017-01-26 14:56:28 +01:00
Frode Petterson 95cfaf6b9e Merge branch 'master' into improved-file-handling 2017-01-26 14:12:43 +01:00
Frode Petterson e02df35bb1 Fix compability with PHP <5.4
Big thanks to andyrandom at drupal.org for providing the fix.
2017-01-26 10:37:26 +01:00
Paal Joergensen aedd0112c2 Merge branch 'release' into improved-file-handling 2017-01-13 15:20:11 +01:00
Frode Petterson 79fb0e310c Change confirm dialog overlay color tint
HFP-457
2017-01-13 13:06:22 +01:00
Paal Joergensen 6e135d0319 Merge branch 'release' into improved-file-handling 2017-01-11 16:21:15 +01:00
Paal Joergensen 738dced286 Added utility function for figuriong out if event is from child [HFP-436] 2017-01-04 16:16:28 +01:00
Paal Joergensen 2cc6c53da1 bg colors on h5p core buttons changed [HFP-413] 2017-01-02 15:30:42 +01:00
Tom Arild Jakobsen dcb02810f0 Change confirmation dialogs button color. Relates to: #HFP-413 2016-12-30 14:13:05 +01:00
Andreas Nergaard fc668c5ab3 Revert "Merge branch 'master' into HFP-186-tutorial-example-links"
This reverts commit 893f610861, reversing
changes made to e00bdbd125.
2016-12-22 15:10:15 +01:00
Andreas Nergaard 893f610861 Merge branch 'master' into HFP-186-tutorial-example-links
Conflicts:
	fonts/h5p-core-16.eot
	fonts/h5p-core-16.svg
	fonts/h5p-core-16.ttf
	fonts/h5p-core-16.woff
	styles/h5p.css
2016-12-22 12:50:56 +01:00
Paal Joergensen a41df0ad9e Merge branch 'master' into improved-file-handling 2016-12-21 15:17:56 +01:00
Paal Joergensen e00bdbd125 Making sure displayoptions.icon is a boolean [HFP-277] 2016-12-21 15:17:36 +01:00
Paal Joergensen 20042fba85 Merge branch 'master' into improved-file-handling 2016-12-21 13:34:06 +01:00
Paal Joergensen 671c079eee Merge branch 'improved-embed-and-download' 2016-12-21 13:21:39 +01:00
thomasmars 53f38d596b Merge branch 'master' of https://github.com/h5p/h5p-php-library 2016-12-21 11:35:43 +01:00
thomasmars e2634070d4 Ignore overrideSettings parameter fields.
HFP-391
2016-12-21 11:34:51 +01:00
Paal Joergensen 8f681a2140 Fixing missing semicolon [HFP-375] 2016-12-20 16:40:45 +01:00
Paal Joergensen 8dd766ecb8 More contrast between confirmation dialog and background [HFP-375] 2016-12-20 16:39:51 +01:00
Timothy Lim b91be29cec Add return statement to recursive function
HFP-391
2016-12-20 15:46:36 +01:00
Paal Joergensen 117e1457b7 Merge branch 'master' into improved-embed-and-download 2016-12-20 14:37:52 +01:00
Paal Joergensen 1341768c90 Fixed problem with empty actionbar [HFP-277] 2016-12-20 14:37:31 +01:00
Paal Joergensen f6449a6043 Improving confirmation dialog [HFP-375] 2016-12-20 13:08:49 +01:00
Paal Joergensen 87ec43d687 Using constants for the different display options, and avoid special cases [HFP-277] 2016-12-16 14:22:03 +01:00
Paal Joergensen 7b39a6900c Inheriting global disable setting for export & embed when saving [HFP-277] 2016-12-16 13:29:18 +01:00
Paal Joergensen ea0362c3da Making lines shorter [HFP-277] 2016-12-16 13:27:40 +01:00
Paal Joergensen a1e68d212b Updated comments [HFP-277] 2016-12-16 11:38:47 +01:00
Paal Joergensen 526d7ddd7e Made copyright button being shown [HFP-277] 2016-12-16 11:30:59 +01:00
Timothy Lim 28e34c1c09 Simplify fullscreenSupported
HFP-339
2016-12-14 16:21:42 +01:00
Andreas Nergaard 5a272ea2f1 Fixed broken font referrance and metadata after font update. 2016-12-14 09:32:57 +01:00
Timothy Lim bbe16fb8da Revert changes for canHasFullScreen
HFP-339
2016-12-13 19:46:21 +01:00
Timothy Lim f0d65d4f9d Refactor canHasFullscreen
HFP-339
2016-12-13 16:04:57 +01:00
Paal Joergensen cfd6cb1e63 Fixed download/embed button bug when permissions are used 2016-12-13 15:57:05 +01:00
jelenamilinovic 1058dab02d Delete h5p-core-15.woff 2016-12-13 13:46:02 +01:00
jelenamilinovic 26cedf7d70 Delete h5p-core-15.ttf 2016-12-13 13:45:58 +01:00
jelenamilinovic c442300cab Delete h5p-core-15.svg 2016-12-13 13:45:55 +01:00
jelenamilinovic afc2084c2e Delete h5p-core-15.eot 2016-12-13 13:45:48 +01:00
jelenamilinovic cddef83287 Add files via upload 2016-12-13 13:43:25 +01:00
thomasmars a326066c97 Only set tutorial url if it exists.
HFP-348
2016-12-13 11:36:28 +01:00
Paal Joergensen e69a81f403 Added description of new interface method [HFP-277] 2016-12-13 10:33:59 +01:00
Timothy Lim 52dc1b2a81 Refactor canHasFullScreen
HFP-339
2016-12-13 10:33:11 +01:00
Paal Joergensen 0a23dc043d Download and embed granularity (HFP-277) 2016-12-13 10:29:33 +01:00
thomasmars 7d741fa503 Reset list-style for list items in action bar.
HFP-350
2016-12-13 10:16:15 +01:00
Timothy Lim a4d6f3aaab Restore deprecated variable H5P.canHasFullScreen for backwards compatability
HFP-339
2016-12-12 11:28:59 +01:00
thomasmars d76ce3f3a5 Applied fix for Safari full screen in version > 9
Big thanks to Lest@t at Drupal for providing the patch.
HFP-342
2016-12-12 11:22:34 +01:00
Andreas Nergaard 180d179f66 HFP-186 Added new icons to h5p core font. 2016-12-09 09:23:02 +01:00
thomasmars bc28592e48 Merge branch 'master' into ignoreBuildFiles 2016-12-06 11:35:55 +01:00
thomasmars 47c35d5135 Merge branches 'master' and 'stable' of https://github.com/h5p/h5p-php-library 2016-12-06 11:35:24 +01:00
Pål Jørgensen c906cb7084 Merge pull request #33 from h5p/improved-message-for-library-in-smantics-no-valid
Improved message presented to user
2016-12-05 09:45:23 +01:00
thomasmars d100c5102a Merge branch 'release' into ignoreBuildFiles 2016-12-02 13:47:21 +01:00
Paal Joergensen 4d010ef38f Improved message presented to user 2016-12-01 11:34:28 +01:00
thomasmars 5ec651e696 Merge branch 'release' into ignoreBuildFiles 2016-11-30 13:24:33 +01:00
Paal Joergensen ed1fb00745 Merge branch 'release' into improved-file-handling 2016-11-30 11:19:08 +01:00
Pål Jørgensen ece72fcfbe Merge pull request #32 from h5p/semi-fullscreen-api-function
Added semi fullscreen function
2016-11-30 09:40:17 +01:00
Tom Arild Jakobsen 32d06356b1 Bump to version 1.11
Relates to: #HFP-285
2016-11-29 16:44:20 +01:00
Tom Arild Jakobsen 5494443533 validateGroup must handle isSubContent
* Update validateGroup in h4p.classes.php to allow subContentId into the data
 * Fix h5p-content-upgrade-process.js to take into account isSubContent

Relates to: #HFP-285
2016-11-29 15:44:32 +01:00
Tom Arild Jakobsen 0882879552 Allow subContentId in group validation. Relates to: #HFP-285 2016-11-28 14:55:57 +01:00
Tom Arild Jakobsen b4615e01b1 Allow subContentId in group validation. Relates to: #HFP-285 2016-11-28 14:54:33 +01:00
Tom Arild Jakobsen b55c1838a9 Update .gitignore 2016-11-23 14:21:28 +01:00
thomasmars 9b0d77a721 Check instanceof score as well to validate number.
HFP-215
2016-11-19 12:29:38 +01:00
thomasmars 3278535a04 Merge branch 'master' into ignoreBuildFiles 2016-11-17 13:28:17 +01:00
thomasmars f82f3a354c Removed debug
HFP-86
2016-11-17 13:27:41 +01:00
thomasmars 0d3648d601 Merge branch 'master' into ignoreBuildFiles 2016-11-17 12:57:58 +01:00
thomasmars d55134151c Moved registering of external dispatcher listener.
- This will dispatch events that are dispatched inside the constructor of
  content types
HFP-86
2016-11-17 12:56:15 +01:00
thomasmars 3e2266fe6c Merge branch 'master' into ignoreBuildFiles 2016-11-17 11:17:32 +01:00
thomasmars ec2ff180c1 Updated H5P font
HFP-114
2016-11-17 11:13:59 +01:00
thomasmars bb29d0c161 Merge branch 'master' into ignoreBuildFiles 2016-11-16 16:29:11 +01:00
Frode Petterson 44c0507887 Merge branch 'editor-redesign' 2016-11-16 16:12:40 +01:00
thomasmars 49e0ff09f4 Merge branch 'master' into ignoreBuildFiles 2016-11-16 14:41:46 +01:00
Paal Joergensen 6001b68b99 Making naming harder to misunderstand 2016-11-11 11:57:54 +01:00
Paal Joergensen 7e90871cb7 Fixing typo 2016-11-11 11:51:20 +01:00
Paal Joergensen 96f84a430a Added semi fullscreen function 2016-11-11 11:45:59 +01:00
Frode Petterson 1173341b76 Merge branch 'release' into improved-file-handling 2016-11-01 16:30:32 +01:00
thomasmars 426f51caa0 Check that score is a number before storing it to the database.
HFP-173

(cherry picked from commit bae3145)
2016-10-28 13:49:03 +02:00
thomasmars bae31451c0 Check that score is a number before storing it to the database.
HFP-173
2016-10-28 13:45:11 +02:00
thomasmars b4949c0d83 Don't store results if they have no score.
HFP-173

(cherry picked from commit 516c70a)
2016-10-28 10:46:40 +02:00
thomasmars 516c70add5 Don't store results if they have no score.
HFP-173
2016-10-28 10:46:05 +02:00
Frode Petterson 08a1cece26 Merge branch 'master' into improved-file-handling 2016-10-27 11:20:18 +02:00
thomasmars 0474ed89af Merge branch 'master' into ignoreBuildFiles 2016-10-21 09:55:08 +02:00
thomasmars f28036ca0e Bumped core API version because of API changes in editor 2016-10-21 09:53:59 +02:00
Frode Petterson bf554b8ee2 Updated composer config 2016-10-07 13:39:51 +02:00
Mannes 52723ad933 Check for file exists before adding to zip. Adding a non existent file to ZipArchive can lead to archive not being created 2016-10-05 17:14:48 +02:00
Frode Petterson c9e5680e85 Merge branch 'master' into improved-file-handling 2016-10-03 15:12:32 +02:00
Frode Petterson e4266efb22 Added framework method to clear dirsize cache
HFP-23
2016-09-30 13:41:50 +02:00
Frode Petterson 0a9aa5a783 Merge pull request #28 from limikael/master
don't fail silently in createExportFile
2016-09-30 11:31:17 +02:00
Håkon Ellingsen a2097d56cb HVP-73: Update font with new icons 2016-09-27 08:12:46 +02:00
Mikael Lindqvist ce796cf0cf don't fail silently in createExportFile 2016-09-26 12:05:02 +02:00
thomasmars cee88a544f Made it possible to ignore build files when exporting development folders. 2016-09-23 15:47:38 +02:00
Frode Petterson 1c5b9707e5 Regenerate export if missing on view
Thanks to paravibe on Drupal.org for contributing.
2016-09-23 10:52:40 +02:00
Frode Petterson 263a987eeb Added document root when creating zip
Thanks to paravibe on Drupal.org for contributing.
2016-09-23 10:31:55 +02:00
Frode Petterson 6b6d4cd109 Merge branch 'improved-file-handling' of github.com:h5p/h5p-php-library into improved-file-handling 2016-09-23 10:14:28 +02:00
Frode Petterson f0e7ea1283 Merge branch 'moodle-rc3' into improved-file-handling 2016-09-23 10:14:19 +02:00
thomasmars 7d86a6235b Merge branch 'release' of https://github.com/h5p/h5p-php-library into moodle-rc3 2016-09-21 14:34:24 +02:00
Thomas 218e48ee91 Merge pull request #25 from h5p/release
Merge 'release' into 'improved-file-handling'
2016-09-21 13:42:06 +02:00
Paal Joergensen 5f38e2b7f8 Bumped core because of bugfix for optional selects [HFJ-2183] 2016-09-21 13:22:35 +02:00
Frode Petterson fd34af6964 Use content array instead of just id
Makes it easier when additional properties are needed.
Also, don't try to translate PHP exception messages.
h5p/h5p-moodle-plugin#112
2016-09-14 10:44:10 +02:00
Frode Petterson c88c049438 Check if contents is set before using
h5p/h5p-moodle-plugin#112
2016-09-09 09:19:55 +02:00
Frode Petterson e8f90c9116 Allow overriding of content URLs
h5p/h5p-moodle-plugin#112
2016-09-08 16:34:53 +02:00
Frode Petterson 2896c9fdab Revert "Added content ID to export handlers"
This reverts commit 7fca1d100d.

Holding off on the exports for now
2016-09-08 14:48:08 +02:00
Frode Petterson 7fca1d100d Added content ID to export handlers
This is to enable for proper access control.
h5p/h5p-moodle-plugin#112
2016-09-08 13:32:57 +02:00
Paal Joergensen 5b8836b5be Making select beeing able to be optional 2016-08-29 15:54:48 +02:00
Frode Petterson d946f32b81 Merge branch 'master' into improved-file-handling 2016-08-02 13:37:26 +02:00
Frode Petterson 888a46844b Bumped core version 2016-08-02 12:57:43 +02:00
Frode Petterson 832aebf5e0 Moved regexp from editor to core
HFJ-2099
2016-07-29 14:15:00 +02:00
Frode Petterson 1ef52dfafe Merge branch 'release' of github.com:h5p/h5p-php-library into release 2016-07-29 13:47:17 +02:00
Frode Petterson 44633fc1db Updated regexp to support existing content to new content copy
HFJ-2099
2016-07-29 13:46:14 +02:00
Frode Petterson 8b31f88ca8 Increase performance by removing unused code 2016-07-27 16:17:58 +02:00
Frode Petterson 9f7b545f02 Added lost part of old fix
HVP-212
2016-07-15 16:14:32 +02:00
Svein-Tore Griff With 43748bc4b8 Add documentation regarding stylePatterns 2016-07-15 15:33:11 +02:00
Frode Petterson 61219a7d84 Merge branch 'master' into improved-file-handling 2016-07-14 10:29:30 +02:00
Frode Petterson 3d14588160 Bugfix: Check if library json is valid 2016-07-08 11:08:47 +02:00
ndobromirov 406a55be5c Excessive calls to variable_set HFJ-1893 2016-06-21 13:26:39 +02:00
Frode Petterson 18e2b79cc6 Merge branch 'master' of github.com:h5p/h5p-php-library 2016-06-21 09:34:37 +02:00
andyrandom 8cb0aad09e Allow hyphens in HTML tags HFJ-1951 2016-06-21 09:34:27 +02:00
Frode Petterson a6656c2e6f Support for when cookies are disabled
HFJ-1915
2016-06-20 14:57:14 +02:00
Frode Petterson 77b9959c87 Merge pull request #22 from davericher/patch-1
Minor cleanup
2016-06-17 08:59:40 +02:00
Dave Richer bcdaf59e5e Minor cleanup 2016-06-16 14:13:51 -04:00
Frode Petterson d4d9f81518 Merge branch 'stable' 2016-06-16 15:32:14 +02:00
Frode Petterson a9a99afb9b Handle non-existing content dir 2016-06-16 10:43:17 +02:00
Frode Petterson 94d3334f37 Merge branch 'improved-file-handling' of github.com:h5p/h5p-php-library into improved-file-handling 2016-06-15 10:34:43 +02:00
Frode Petterson ba2f7c5e67 Merge branch 'release' into improved-file-handling 2016-06-15 10:34:34 +02:00
Frode Petterson 89541acfa8 Allow for alternative editor path
(used by Drupal)
2016-06-14 12:39:15 +02:00
Frode Petterson ec2e0fbb71 Removed JS error on empty results 2016-06-13 14:46:15 +02:00
Frode Petterson 0ee4cc57fc Fixed saveFile not working for default storage 2016-06-13 12:47:44 +02:00
Frode Petterson fca0537a4d Use context and token in URL prefix 2016-06-13 10:31:09 +02:00
Frode Petterson 5e87aee63c Merge branch 'release' into improved-file-handling 2016-06-13 09:58:18 +02:00
Thomas Marstrander b3c55928e3 Remove tabindex of exitButton in confirmation dialog.
Trapped focus between confirm and cancel button.
HFJ-2004
2016-06-09 15:26:15 +02:00
Thomas Marstrander 51851f14c3 Use aria-labelledby to describe dialog, instead of alert.
HFJ-2003
2016-06-09 13:18:09 +02:00
Thomas Marstrander e10594fb49 Hide redundant confirmation dialog exit button for assistive technologies.
HFJ-2004
2016-06-09 11:26:11 +02:00
Paal Joergensen d42630c369 Merge branch 'mbstring-check' into release 2016-06-08 11:29:37 +02:00
Paal Joergensen 6caf44e54b Added checks for mbstring PHP extension [HFJ-1996] 2016-06-08 11:28:07 +02:00
Thomas Marstrander 8615deb23b Hide elements that confirmation dialog covers from assistive technologies.
HFJ-1995
2016-06-08 11:06:03 +02:00
Thomas Marstrander 10e1a7ba65 Use DOM Level 2 events.
HFJ-1999
2016-06-07 15:09:59 +02:00
Thomas Marstrander 8bd9e9c2db Merge remote-tracking branch 'origin/release' into release 2016-06-07 14:32:12 +02:00
Thomas Marstrander 77fb832221 Added focus capturing, redirecting it to the open confirmation dialog
HFJ-1995
2016-06-07 14:31:41 +02:00
Frode Petterson b261754cf1 Merge branch 'release' into improved-file-handling 2016-06-07 14:28:12 +02:00
Frode Petterson 2ebc9225ee Merge branch 'release' of github.com:h5p/h5p-php-library into release 2016-06-07 12:58:40 +02:00
Paal Joergensen f4cee6e284 Moved deletion of content user data to after dialog is closed [HFJ-1989] 2016-06-07 11:09:42 +02:00
Thomas Marstrander 87658ed42b Accessibility - reads confirmation dialog text on show.
HFJ-1992
2016-06-07 11:04:21 +02:00
Paal Joergensen 7807b8af68 Making sure reset dialog is only shown once [HFJ-1989] 2016-06-06 16:09:35 +02:00
Thomas Marstrander e3b29a2199 Accessibility - reads confirmation dialog text on show.
HFJ-1992
2016-06-06 14:57:51 +02:00
Frode Petterson 2bcf3b783f Merge branch 'release' 2016-06-06 10:01:36 +02:00
Thomas Marstrander f6ce5dff74 Added pointer cursor for core cancel button.
HFJ-1930
(cherry picked from commit c6b3b06)
2016-06-06 09:47:29 +02:00
Thomas Marstrander ed13203254 Use buttons instead of anchors in Confirmation Dialog.
HFJ-1930
(cherry picked from commit 27bc158)
2016-06-06 09:47:15 +02:00
Frode Petterson 0d6fac4099 Merge branch 'release' of github.com:h5p/h5p-php-library into release 2016-06-03 12:53:12 +02:00
Thomas Marstrander 93a07d2e9b Merge branch 'improved-file-handling' of https://github.com/h5p/h5p-php-library into improved-file-handling 2016-05-31 14:43:34 +02:00
Thomas Marstrander b102a7de21 Only add editor context when in editor.
HFJ-1972
2016-05-31 14:43:12 +02:00
Frode Petterson ce89b516ef Merge branch 'release' into improved-file-handling 2016-05-31 12:43:06 +02:00
Frode Petterson 594d992f19 Merge branch 'master' into improved-file-handling 2016-05-31 12:42:29 +02:00
Thomas Marstrander eba774c863 Prevent DOM pollution when having many confirmation dialogs.
Append confirmation dialog on show and detach it on hide.
HFJ-1969
(cherry picked from commit 0a63d12)
2016-05-31 11:49:26 +02:00
Frode Petterson c2f5feaae5 Improved error message for req core version
HFJ-1959
2016-05-31 10:51:59 +02:00
Thomas Marstrander 0a63d123cf Prevent DOM pollution when having many confirmation dialogs.
Append confirmation dialog on show and detach it on hide.
HFJ-1969
2016-05-31 10:19:07 +02:00
Thomas Marstrander 73a23d4679 Send context id together with post data in order to determine our context.
HFJ-1964
2016-05-30 10:35:06 +02:00
Frode Petterson bba5190876 Merge branch 'release' of github.com:h5p/h5p-php-library into improved-file-handling 2016-05-24 11:27:28 +02:00
Thomas Marstrander c6b3b06a97 Added pointer cursor for core cancel button.
HFJ-1930
2016-05-24 11:18:42 +02:00
Thomas Marstrander 27bc158708 Use buttons instead of anchors in Confirmation Dialog.
HFJ-1930
2016-05-23 14:34:56 +02:00
Paal Joergensen 2c4edb7b56 Merge branch 'master' into release 2016-05-13 14:56:40 +02:00
Frode Petterson cc121b2f53 Bugfix: Must be able to run from CLI 2016-05-13 13:42:44 +02:00
Frode Petterson 417af36c81 Bugfix: Must be able to run from CLI 2016-05-12 15:52:37 +02:00
Frode Petterson cbfa2913bc Merge branch 'master' into improved-file-handling 2016-05-09 13:21:47 +02:00
Frode Petterson 51698d325b Corrected file storage interface 2016-05-09 11:53:12 +02:00
Frode Petterson a36b2f1212 Removed TODO which makes no sense 2016-05-06 10:40:28 +02:00
Frode Petterson e056b6776a More functions for handling content files
Added three more functions to File Storage Interface
h5p/h5p-moodle-plugin#49
HFJ-1846
2016-05-04 16:52:02 +02:00
Thomas Marstrander e412c3a228 Make sure focus is set after timeout, to not skewer content.
HFJ-1867
2016-05-04 12:37:59 +02:00
Thomas Marstrander 7782b19e99 Do not set offset initially, sometimes ended up overflowing parent element.
Do calculation before setting popup offset.
HFJ-1867
2016-05-04 11:53:46 +02:00
Frode Petterson acaccea977 Allow pagination widget to handle empty pages 2016-05-03 12:47:16 +02:00
Thomas Marstrander 6e7e144900 Confirmation dialog - Focus confirm button on show.
HFJ-1860
2016-05-03 11:15:21 +02:00
Frode Petterson c9583cb8fa Merge branch 'master' into improved-file-handling 2016-04-26 11:57:04 +02:00
Thomas Marstrander 4da518296e Make sure confirmation dialog is displayed on top of CP interaction as button.
HFJ-1572
2016-04-26 10:38:41 +02:00
Frode Petterson c9349b8e26 Merge branch 'master' into improved-file-handling
Conflicts:
	h5p-default-storage.class.php
	h5p-file-storage.interface.php
2016-04-25 14:34:05 +02:00
Frode Petterson b6b2a6b1dd Merge branch 'master' of github.com:h5p/h5p-php-library 2016-04-25 14:32:34 +02:00
Frode Petterson 174d8c0941 Revert "Added function for reading file contents"
This reverts commit e324e298b9.
2016-04-25 14:32:16 +02:00
Frode Petterson 325ea27562 Added func. for saving uploaded files
h5p/h5p-moodle-plugin#48
HFJ-1845
2016-04-25 14:31:25 +02:00
Frode Petterson 7b38c3571e Made dir handling private to prevent abuse
h5p/h5p-moodle-plugin#48
HFJ-1845
2016-04-25 14:30:12 +02:00
Thomas Marstrander 05dfc9c374 Merge remote-tracking branch 'origin/master' 2016-04-25 13:17:56 +02:00
Thomas Marstrander 8a6733ceb4 Specified confirmation dialog css rules so they wont get overwritten by standard anchor styling.
Enabled iframe resize functionality for confirmation dialog.
HFJ-1572
2016-04-25 13:17:24 +02:00
Frode Petterson 1623f6701e Merge pull request #21 from davericher/patch-1
Prevent H5P Core from breaking console commands
2016-04-25 09:48:37 +02:00
Dave Richer 76e813a32e Update h5p.classes.php
Prevents H5P From breaking console PHP commands
2016-04-23 23:40:46 -04:00
Frode Petterson db6f18c984 Merge branch 'master' of github.com:h5p/h5p-php-library 2016-04-22 11:36:14 +02:00
Frode Petterson e324e298b9 Added function for reading file contents
h5p/h5p-moodle-plugin#47
HFJ-1844
2016-04-22 11:35:23 +02:00
Thomas Marstrander 926ff4af3a Avoid confirmation dialog skewering content.
HFJ-1572
2016-04-21 14:58:21 +02:00
Paal Joergensen 6869ecbb09 Handling several digits in major and minor version 2016-04-21 13:22:01 +02:00
Thomas Marstrander 414751aad2 Fixed uploading packages and export functionality with development mode.
Changed update package to save package, update package was moved from interface in january, replaced with savePackage.
Added optional parameter to exportLibrary where you can pass in development folder path for the library if it lives inside development folder.
HVP-147
2016-04-21 11:38:14 +02:00
Frode Petterson 64de9d53f8 Merge branch 'master' of github.com:h5p/h5p-php-library
Conflicts:
	README.txt
2016-04-13 11:33:39 +02:00
Frode Petterson b559935c09 Merge branch 'davericher-master' 2016-04-13 11:30:39 +02:00
Svein-Tore Griff With f510d0f0e9 Merge pull request #18 from marclaporte/patch-2
Fix some typos and improve clarity
2016-04-13 08:54:23 +02:00
Dave Richer 29a8601595 Major clean up of both syntactical errors and spelling 2016-04-13 00:01:15 -04:00
Marc Laporte b0f7c5cd35 Fix some typos and improve clarity 2016-04-12 18:30:26 -04:00
Frode Petterson e26a662341 Merge branch 'release' 2016-04-12 15:06:30 +02:00
Frode Petterson b93b7082dc Reset page offset when filtering by facets 2016-04-12 15:01:10 +02:00
Frode Petterson cdfb810501 Merge branch 'release' 2016-04-12 14:39:59 +02:00
Frode Petterson 7474916f3a scripts and styles arrays must always be defined 2016-04-12 11:37:55 +02:00
Frode Petterson 471a1ea6a8 Merge branch 'master' of github.com:h5p/h5p-php-library 2016-04-11 11:49:34 +02:00
Frode Petterson 38fc011c7f Fixed focus and active style for H5P bar
HFJ-1549
2016-04-11 11:49:01 +02:00
Thomas Marstrander 7f41e2b3c6 Merge remote-tracking branch 'origin/master' 2016-04-08 13:49:20 +02:00
Thomas Marstrander 711b9326bc CP editor interaction popup has z-index 100, so confirmation dialog must have z-index 101
HFJ-1572
2016-04-08 13:49:06 +02:00
Frode Petterson 84d93af447 Merge branch 'master' of github.com:h5p/h5p-php-library 2016-04-08 13:19:31 +02:00
Frode Petterson 9741dd882d Improved action bar buttons
Now supports space bar.
HFJ-1549
2016-04-08 13:18:35 +02:00
Thomas Marstrander 233b5e7653 Programmatically set focus to confirmation dialog.
HFJ-1572
2016-04-08 10:23:55 +02:00
Thomas Marstrander e8adccaa02 Updated confirmation dialog styles.
HFJ-1572
2016-04-07 16:31:41 +02:00
Thomas Marstrander ea620e12f0 Reverted left adjustment of confirmation dialog.
HFJ-1572
2016-04-07 15:22:19 +02:00
Thomas Marstrander bf7f5c863c Confirmation dialog adjustments.
Translated copyright dialog default texts.
Removed focus on click.
Adjusted left positioning when showing dialog.
Adjusted max width of dialog.
HFJ-1572
2016-04-07 14:51:56 +02:00
Frode Petterson 41c98cc13c Merge branch 'master' of github.com:h5p/h5p-php-library 2016-04-06 11:47:16 +02:00
Frode Petterson e0d3c2e1e0 Merge branch 'release' 2016-04-06 11:47:06 +02:00
Frode Petterson d4112a639a Merge pull request #17 from marclaporte/patch-1
Fix some typos and improve spelling
2016-04-06 09:39:06 +02:00
Marc Laporte 02e5f2045e Fix some typos 2016-04-05 12:40:06 -04:00
Thomas Marstrander 35a7213a67 Added confirmation dialog.
HFJ-1572
2016-04-05 18:35:02 +02:00
Frode Petterson 127dc4f0e1 Use correct ID when copying package 2016-04-05 16:06:09 +02:00
Frode Petterson 0c5971d6d4 Use numbers when comparing versions 2016-04-04 12:39:57 +02:00
Frode Petterson cdfab4d4b6 Merge branch 'master' of github.com:h5p/h5p-php-library 2016-04-04 11:12:16 +02:00
Frode Petterson a11e8d4365 Bumped coreApi version to reflect editor changes 2016-04-04 11:11:18 +02:00
Thomas Marstrander 17ad3d4825 Merge branch 'master' of https://github.com/h5p/h5p-php-library 2016-03-31 16:09:23 +02:00
Thomas Marstrander 4d277b2304 Added version number and links to licenses.
HFJ-1734
2016-03-31 16:07:45 +02:00
Paal Joergensen d912232433 Merge remote-tracking branch 'origin/more-font-styling' into release 2016-03-29 12:24:42 +02:00
Paal Joergensen f05d3b3bf5 Merge branch 'image-editing' into release 2016-03-29 11:43:30 +02:00
Frode Petterson 6b31d467a0 Merge branch 'master' of github.com:h5p/h5p-php-library 2016-03-21 12:51:04 +01:00
Frode Petterson 41464cb98c Corrected lib array 2016-03-21 12:35:44 +01:00
Frode Petterson 62e2f41884 Merged stuff 2016-03-21 11:56:56 +01:00
Frode Petterson 007137c257 Merge branch 'master' of github.com:h5p/h5p-php-library
Conflicts:
	h5p.classes.php
2016-03-21 11:51:45 +01:00
Frode Petterson 2ac631458f Merge branch 'master' into content-tags 2016-03-18 13:52:53 +01:00
Frode Petterson 14605dc790 A more natural tabindex
HFJ-1549
2016-03-17 14:22:23 +01:00
Frode Petterson b8a3965c6e Merge branch 'master' into file-storage-interface
Conflicts:
	h5p.classes.php
2016-03-16 10:01:13 +01:00
Paal Joergensen 5229e82764 Merge branch 'improved-ajax' 2016-03-15 16:09:01 +01:00
Thomas Marstrander 4775e3444f Added two new icons.
HFJ-1716
2016-03-14 16:01:45 +01:00
Frode Petterson de175737ea Use correct variable 2016-03-10 16:33:53 +01:00
Frode Petterson 89227e4639 Merge branch 'master' into image-editing 2016-03-10 14:22:04 +01:00
Frode Petterson 61ae8899cb Merge branch 'master' into event-logging
Conflicts:
	h5p.classes.php
2016-03-10 14:21:04 +01:00
Frode Petterson f05a370b42 Merge branch 'event-logging' of github.com:h5p/h5p-php-library into event-logging
Conflicts:
	h5p.classes.php
2016-03-10 14:19:30 +01:00
Frode Petterson 5b965636e0 Revert "HFJ-1610 - Gather statistics on dev or prod server."
This reverts commit 9b76fccfce.
2016-03-10 14:14:39 +01:00
Frode Petterson 36c8bf3362 Revert "HFJ-1610 - Track number of contents per library type."
This reverts commit 2e0498cd3a.
2016-03-10 14:14:33 +01:00
Frode Petterson 13a2988414 Revert "HFJ-1610 - Track libraries installed."
This reverts commit 5287d455b2.
2016-03-10 14:14:00 +01:00
Frode Petterson 0218493eab Added support for two more font styling options
HFJ-1646
2016-03-09 11:18:21 +01:00
Frode Petterson 437598aa8e Use key to avoid bugs 2016-03-07 10:58:39 +01:00
Thomas Marstrander 4ed368f5e7 Ratio added as field instead of parameter, removed from whitelist.
HFJ-1645
2016-03-06 13:40:50 +01:00
Thomas Marstrander ee245f9344 Whitelisted originalImage and ratio when validating Image.
HFJ-1645
2016-03-06 13:27:10 +01:00
Thomas Marstrander fa7b42120d Merge branch 'master' of https://github.com/h5p/h5p-php-library into image-editing 2016-03-06 11:42:37 +01:00
Thomas Marstrander 54ca645e2c Whitelisted originalImage attribute when filtering params.
HFJ-1645
2016-03-06 11:42:24 +01:00
Frode Petterson 93fd710509 Fixed typo
HFJ-1610
2016-03-04 13:56:05 +01:00
Frode Petterson 43e9c7adcb Avoid navigating inside iframe
HFJ-1479
2016-03-01 15:36:22 +01:00
Frode Petterson 35a0d09b9b Only use one filter for each column
HFJ-1620
2016-03-01 11:34:34 +01:00
Frode Petterson a41ecccb9a Added em-dash when facet cell is empty.
Other minor visual adjustments.
HFJ-1620
2016-03-01 10:43:13 +01:00
Frode Petterson a398589c80 Added support for Tags in data views
HFJ-1620
2016-02-29 16:35:22 +01:00
Frode Petterson b42193729e Merge branch 'improved-ajax' into improved-ajax-moodle
Conflicts:
	h5p.classes.php
2016-02-25 14:55:27 +01:00
Frode Petterson 0430e6ba28 Put AJAX response functions in core 2016-02-25 13:46:05 +01:00
Thomas Marstrander 92e4ab0f9e Merge branches 'file-storage-interface' and 'master' of https://github.com/h5p/h5p-php-library into file-storage-interface 2016-02-24 09:49:11 +01:00
Frode Petterson 06e9508eda Merge branch 'master' of github.com:h5p/h5p-php-library 2016-02-23 13:10:43 +01:00
Frode Petterson 6bfffbcf30 Added woff2 as a safe file type 2016-02-23 13:10:08 +01:00
Frode Petterson 4e06733ffb Use correct message 2016-02-22 12:01:18 +01:00
Frode Petterson 0aebdb345b Lets use a simpler solution 2016-02-22 11:58:25 +01:00
Frode Petterson 256bf1b6d2 Revert "Improved results and contentuserdata saving by queueing requests"
This reverts commit 3849f3a054.
2016-02-22 11:56:52 +01:00
Thomas Marstrander bfcf4228db Use variable with complete path HFJ-1695 2016-02-22 10:38:33 +01:00
Frode Petterson 12ba0d2da5 Abstract event base, usability enhancements 2016-02-19 13:38:38 +01:00
Frode Petterson 3849f3a054 Improved results and contentuserdata saving by queueing requests 2016-02-19 12:57:53 +01:00
Frode Petterson b42b28ab03 Use correct jQuery
HFJ-1610
2016-02-11 15:00:08 +01:00
Frode Petterson 7a87735f02 Removed sub_type from stats
HFJ-1610
2016-02-11 09:53:16 +01:00
Frode Petterson 4cf7a32b4a Get data from counters instead of log
HFJ-1610
2016-02-10 11:54:20 +01:00
Frode Petterson 58f3617fc1 Added counters
HFJ-1610
2016-02-10 11:49:20 +01:00
Frode Petterson 6580508b1d Merge branch 'release' into event-logging 2016-02-09 13:53:41 +01:00
Frode Petterson dc8b70748f Fixed once()
HFJ-1646
2016-02-09 13:53:17 +01:00
Frode Petterson 2a20dc23ae Use correct format
HFJ-1610
2016-02-09 13:52:35 +01:00
Frode Petterson b16b0c1e0b We're going to need authors 2016-02-09 10:55:44 +01:00
Frode Petterson cf3373d4ee Changes in format to be more POST friendly
HFJ-1610
2016-02-09 10:54:04 +01:00
Frode Petterson c4011e3bbb Use POST to get H5P updates
HFJ-1610
2016-02-08 11:39:21 +01:00
Frode Petterson 70baeb55a1 Add local ID from path
HFJ-1610
2016-02-08 10:38:53 +01:00
Frode Petterson fa90b0a1c3 Use correct variable 2016-02-05 11:09:57 +01:00
Frode Petterson 292e04de5d Combine library statistics
HFJ-1610
2016-02-04 16:34:32 +01:00
Frode Petterson 971e035626 Skip local check if network
HFJ-1610
2016-02-04 15:15:35 +01:00
Frode Petterson f5f89f2395 Helper for storing events
HFJ-1610
2016-02-04 14:13:59 +01:00
Frode Petterson 7328245e8d Merge branch 'master' into event-logging 2016-02-04 09:35:54 +01:00
Thomas Marstrander 5287d455b2 HFJ-1610 - Track libraries installed. 2016-02-03 15:58:49 +01:00
Thomas Marstrander 2e0498cd3a HFJ-1610 - Track number of contents per library type. 2016-02-03 15:36:35 +01:00
Frode Petterson 530ad8ee33 Corrected usage of static
HFJ-1610
2016-02-03 10:42:14 +01:00
Frode Petterson 62cd708f6b Added base class for H5P events
HFJ-1610
2016-02-02 17:03:53 +01:00
Thomas Marstrander 9b76fccfce HFJ-1610 - Gather statistics on dev or prod server. 2016-02-02 16:29:48 +01:00
Frode Petterson 3991875439 Avoid navigating inside iframe
HFJ-1479
2016-01-27 12:42:55 +01:00
Frode Petterson 633186c0d5 Support for data urls in css aggr. 2016-01-26 15:57:10 +01:00
Frode Petterson 36ca38705f Allow assets of only one type 2016-01-25 14:49:54 +01:00
Frode Petterson 3defc7abde Fixed CSS url caching bug 2016-01-25 14:49:29 +01:00
Frode Petterson 73fd170a3a Editor may use dirReady for the time being 2016-01-25 14:48:14 +01:00
Frode Petterson 64e2001156 Do not cache assets without files 2016-01-25 14:47:48 +01:00
Frode Petterson 875a7ccef3 Target correct folder when exporting libs 2016-01-25 14:46:55 +01:00
Frode Petterson 0f736ae1c5 Fixed issue forgotten during refactoring 2016-01-25 14:46:06 +01:00
Frode Petterson fb9a84e665 Dependencies may be indexed differently 2016-01-25 14:44:40 +01:00
Frode Petterson 5eb0e0e14c Avoid caching dependencies without assets 2016-01-25 14:44:10 +01:00
Frode Petterson 8597baa253 Revert "Added a general override rule"
This reverts commit 15381d64a4.

Will rename the class instead.
2016-01-21 10:24:36 +01:00
Frode Petterson a65625d123 Merge branch 'master' into file-storage-interface 2016-01-21 09:57:23 +01:00
Frode Petterson 15381d64a4 Added a general override rule 2016-01-21 09:56:49 +01:00
Frode Petterson fa4b6ab524 Merge branch 'master' of github.com:h5p/h5p-php-library 2016-01-20 13:23:09 +01:00
Frode Petterson f8c2a47580 Get the lastest version of a given library.
h5p/h5p-wordpress-plugin#28
2016-01-20 13:21:51 +01:00
Frode Petterson 604218f2e3 Hide buttons if there are no URLs 2016-01-15 14:12:24 +01:00
Frode Petterson 7c146ce919 Library list: use all available width 2016-01-15 14:11:57 +01:00
Frode Petterson dc69181025 Removed debug 2016-01-14 15:39:01 +01:00
Frode Petterson 12032461bc Follow existing naming conv. removed namespace 2016-01-14 09:46:00 +01:00
Frode Petterson 11481c3b4b Merge branch 'master' into file-storage-interface 2016-01-13 15:44:31 +01:00
Frode Petterson 00686b733d Added support for aggregating and caching library assets 2016-01-13 14:23:34 +01:00
Frode Petterson 1bf393a9af Allow custom URL for libraries 2016-01-13 08:45:00 +01:00
Frode Petterson b4fd0e098c Aggregate and cache content assets to improve performance 2016-01-12 18:09:31 +01:00
Frode Petterson f4ba0af1ef Fixed default file storage implementation 2016-01-12 12:55:03 +01:00
Frode Petterson 808e43bc66 Disable generating export on each request 2016-01-12 10:31:47 +01:00
Frode Petterson 0125afb440 Refactor for consistency 2016-01-12 10:31:36 +01:00
Frode Petterson 2bd972168e Isolate file operations in a separate class 2016-01-11 18:31:04 +01:00
Frode Petterson 510016b1cc Merge branch 'release' of github.com:h5p/h5p-php-library into release 2016-01-05 13:58:20 +01:00
Frode Petterson 59901fd1c9 Fixed resizing script trying to access iframe content
HFJ-1512
2016-01-05 13:57:16 +01:00
Paal Joergensen 919ac77f35 Readded check for undefined contentid in setActivityStarted() 2015-12-18 10:26:59 +01:00
Paal Joergensen e83b213183 Made content state saving more robust [HFJ-1450] 2015-12-18 10:06:33 +01:00
Frode Petterson 5e45e7d7dd Merge branch 'master' into release
Conflicts:
	js/h5p-x-api.js
2015-12-17 14:04:58 +01:00
Paal Joergensen e6ec257c6d Made setActivityStarted a little more robust [HFJ-1474] 2015-12-16 15:42:26 +01:00
Paal Joergensen 2d0e409ac4 Made content state beeing saved on safari@iPad when closing tab and leaving tab 2015-12-16 09:50:58 +01:00
Frode Petterson 2bc4dee85a Prevent crashing editor for old libraries 2015-12-10 14:49:30 +01:00
Frode Petterson b85ee0bd0b Merge branch 'auto-install' 2015-12-10 10:22:19 +01:00
Frode Petterson 932db9eb7a Merge pull request #6 from juho-jaakkola/composer
Adds minimal composer.json
2015-12-03 21:41:17 +01:00
Svein-Tore Griff With 3a2bb0a2fd Trigger attempted event the first time a user sees a question - HFJ-1397 2015-11-27 20:49:49 +01:00
Juho Jaakkola 6773f7aad8 Adds minimal composer.json 2015-11-27 13:10:41 +02:00
Frode Petterson 5aec15061c Make copyright fields translatable
https://github.com/h5p/h5p-image/issues/2
2015-11-23 14:35:51 +01:00
Svein-Tore Griff With 813103a28b Add GPL license 2015-11-17 14:10:26 +01:00
Frode Petterson 3c34ab223a Prevent assigning to the htmlcollection. 2015-11-13 11:18:53 +01:00
Frode Petterson 0c24965305 Keep track of the latest H5P release 2015-11-11 14:13:05 +01:00
Frode Petterson 16aa6813ae Use correct variable 2015-11-06 15:35:06 +01:00
Frode Petterson 2f5e1fcc91 Use correct variable. 2015-11-05 16:52:38 +01:00
Frode Petterson 7a369de7e7 Avoid undefined errors 2015-11-04 17:30:58 +01:00
Frode Petterson 4bca7055ab Merge branch 'master' into copy-and-paste 2015-11-04 11:38:52 +01:00
Svein-Tore Griff With e29be52de5 Merge branch 'master' of https://github.com/h5p/h5p-php-library 2015-11-01 00:32:55 +01:00
Svein-Tore Griff With b077af0981 Merge branch 'stable' 2015-11-01 00:32:47 +01:00
Svein-Tore Griff With ccfa2d516f Make sure we get answered statements in the result log 2015-11-01 00:30:45 +01:00
Svein-Tore Griff With 844883a1cf triggerXAPICompleted is deprecated so we don't change it. Also fixes doc 2015-11-01 00:23:10 +01:00
Svein-Tore Griff With cc6521c4a1 completed default value depends on verb 2015-11-01 00:19:56 +01:00
Svein-Tore Griff With e7fe53c235 Merge pull request #4 from garemoko/garemoko-issue-2
Add support for result.success & completion
2015-11-01 00:14:42 +01:00
Frode Petterson f0530957ad Improved semi-fullscreen for iPad. 2015-10-27 16:57:28 +01:00
Frode Petterson 876135436c Made resize script smarter to avoid flickering. 2015-10-26 14:13:21 +01:00
Frode Petterson f35e36cf5a Merge branch 'editor-padding' 2015-10-22 14:53:53 +02:00
Andrew Downes 76a02867aa Update triggerXAPICompleted and triggerXAPIScored
Added support for completion and success.
2015-10-20 11:29:01 +01:00
Andrew Downes f9ea9adb1b Add support for result.success & completion 2015-10-20 11:13:08 +01:00
Frode Petterson ee02f08bdb Prevent warnings when reading the directory fails
(There will still be error messages)
2015-10-14 14:43:03 +02:00
Paal Joergensen 78c06fb42a Merge branch 'master' into copy-and-paste 2015-10-06 14:00:08 +02:00
Frode Petterson cb8640195e Avoid thin grey lines around the iframe when using fullscreen on high-res devices. 2015-10-02 08:52:11 +02:00
Frode Petterson ef3cbd92c5 Improved semi-fullscreen? 2015-09-28 15:30:25 +02:00
Svein-Tore Griff With 1c99d7ed61 Remove the https since there are some servers that doesn't support it 2015-09-22 17:58:55 +02:00
Frode Petterson 8e3d78a2f6 Prevent use of files that belongs to other content. 2015-09-18 12:55:58 +02:00
Frode Petterson 742339ba8f Merge branch 'master' into editor-padding 2015-09-15 09:28:29 +02:00
Frode Petterson 46183a3a2e Fixed missing equal sign. 2015-09-15 09:26:58 +02:00
Frode Petterson 3e54270f4b Merge branch 'master' into editor-padding 2015-09-10 14:27:37 +02:00
Frode Petterson 2d43942c48 Use parent window instead of top for communications. 2015-09-10 14:27:12 +02:00
Frode Petterson 1cf1a38a1b Merge branch 'master' into editor-padding 2015-09-10 10:02:43 +02:00
Paal Joergensen cb59b9b79f Allowing text-align on wysiwygs [HPN-115] 2015-09-09 13:28:16 +02:00
Frode Petterson 98a7b759a9 Updated icons. 2015-09-03 09:04:04 +02:00
Frode Petterson 47d0f830d3 Removed asd 2015-09-02 15:44:38 +02:00
Frode Petterson 07b085e326 Use HTTPS, much safer. 2015-08-31 15:46:59 +02:00
Frode Petterson 3e3bba7133 Always use 100% for fullscreen. auto is needed for embed. 2015-08-27 15:10:02 +02:00
Frode Petterson 7737559dec Fixed off(). 2015-08-27 11:36:07 +02:00
Frode Petterson d8d7fdabdd Replaced nbsp. 2015-08-26 15:58:49 +02:00
Frode Petterson 1298643ab1 Merge branch 'master' of github.com:h5p/h5p-php-library 2015-08-10 13:04:44 +02:00
Frode Petterson 600975db8b Inconsistent placeholder format. Causes issues in WP. 2015-08-10 13:04:38 +02:00
Svein-Tore Griff With 8d9781f4ae Also add class when framed 2015-07-30 18:11:59 +02:00
Svein-Tore Griff With 71f147058d Rename isStandalone to isRoot and use ned libraryInfo instead of the so called ubername 2015-07-20 13:40:59 +02:00
Svein-Tore Griff With aa96d726bd Merge branch 'master' of https://github.com/h5p/h5p-php-library 2015-07-20 13:05:48 +02:00
Svein-Tore Griff With 5d1cd188d0 Add duration and scaled to result 2015-07-20 13:05:41 +02:00
Svein-Tore Griff With 769fd219bc API 1.6 2015-07-20 13:03:05 +02:00
Paal Joergensen 56e74c2d68 Renamed H5P.Base to H5P.ContentType.
Moved H5P.ContentType code to separate file.
Made H5P.ContentType extend H5P.EventDispatcher.
2015-07-17 13:32:35 +02:00
Paal Joergensen 8cf384f46a Fixed H5P.Base.getLibraryFilePath() bug 2015-07-14 14:46:35 +02:00
Paal Joergensen e36582c714 Added H5P base class that all H5P libraries automatically extends 2015-07-14 14:37:39 +02:00
Svein-Tore Griff With 03370c9500 Add info about the library being used to the xAPI statements 2015-07-10 12:58:02 +02:00
Svein-Tore Griff With 8431304dd0 Remove todos 2015-07-10 11:41:28 +02:00
Frode Petterson 8b9eed2349 Auto seems to work much better if embedded content gets scollbars. 2015-07-07 13:53:20 +02:00
Frode Petterson b30ae98858 Added logo. 2015-07-07 13:25:53 +02:00
Frode Petterson 1764e80511 Merge branch 'master' of github.com:h5p/h5p-php-library 2015-06-25 15:15:04 +02:00
Frode Petterson 3e21226b3b No decimals in embed dialog. 2015-06-25 15:14:55 +02:00
Frode Petterson 3d4165df55 Use local variable. 2015-06-23 14:24:19 +02:00
Frode Petterson f9e07f4b80 Merge branch 'master' of github.com:h5p/h5p-php-library 2015-06-23 11:22:41 +02:00
Frode Petterson 89a03eba8a Merge branch 'master' of github.com:h5p/h5p-php-library 2015-06-23 11:12:38 +02:00
Frode Petterson b9229ba75f Don't try to get data when there's no user. 2015-06-23 11:12:29 +02:00
Frode Petterson 18638f4913 Merge branch 'master' of github.com:h5p/h5p-php-library 2015-06-22 11:23:40 +02:00
Frode Petterson d4ea0a1255 Use warnings to tell the admin what is wrong. Removed duplicate message 2015-06-22 11:22:49 +02:00
Frode Petterson 6ad53d66f3 Improve error handling. 2015-06-22 10:02:07 +02:00
Frode Petterson 2beff66195 Do not try to validate empty params. 2015-06-16 14:52:22 +02:00
Frode Petterson aa49bc88a2 Merge branch 'release' 2015-06-15 16:11:21 +02:00
Frode Petterson 36558b0846 Options are optional. 2015-06-15 16:11:11 +02:00
Frode Petterson d8cf40623e Improved error handling in case upload dir isn't writable, zip isn't enabled or folders are missing. 2015-06-15 14:57:51 +02:00
Frode Petterson b399a68adc Merge branch 'release'
Conflicts:
	h5p.classes.php
2015-06-04 14:47:34 +02:00
Frode Petterson c40d273704 Fixed this arg for external dispatcher. 2015-06-04 14:39:02 +02:00
Frode Petterson aded8d1f43 Avoid errors. Merged in from D7. 2015-05-27 10:11:01 +02:00
Frode Petterson 3460e400a0 Fixed special case for export/download. 2015-05-22 15:50:00 +02:00
Frode Petterson d85815b3be Keep the content's disable settings when re-saving after global options have changed. (More consistent and reliable) 2015-05-22 15:31:28 +02:00
Frode Petterson 9db33dd61b Merge branch 'release' of github.com:h5p/h5p-php-library into release 2015-05-22 13:29:04 +02:00
Frode Petterson 6ecb15a1d0 There is no disable about for content, it's only a global setting. 2015-05-22 13:28:52 +02:00
Frode Petterson 101d5aab31 There is no disable all option. Disabling frame does the same. 2015-05-22 13:28:45 +02:00
Frode Petterson 52dca53883 There is no disable all option. Disabling frame does the same. 2015-05-22 13:20:44 +02:00
Frode Petterson 7e009d00ca There is no disable about for content, it's only a global setting. 2015-05-22 13:18:13 +02:00
Thomas Marstrander d5979f1bcc Merge branch 'release' of https://github.com/h5p/h5p-php-library into release 2015-05-21 13:03:28 +02:00
Thomas Marstrander 99522f59bf Skip groups that are null. This is done because groups with only one entry are concatenated with their entry. 2015-05-21 13:02:52 +02:00
Frode Petterson 3a0abf935e Merge branch 'release' 2015-05-21 10:17:06 +02:00
Frode Petterson 8e82b515a2 Prevent updating pagination when there's no table. 2015-05-21 09:50:58 +02:00
Frode Petterson 834764e316 Eliminate warnings. 2015-05-20 10:55:02 +02:00
Svein-Tore Griff With 227e0829fd Avoid printing very scary error message for all old interactive videos 2015-05-18 15:14:33 +02:00
Frode Petterson ac96408bc9 Merge branch 'release' 2015-05-18 09:41:07 +02:00
Frode Petterson 3f6abd722d Prevent crashing if getCopyrights fail. 2015-05-15 12:21:23 +02:00
Svein-Tore Griff With e2b6f3527e Merge branch 'semantics-font' into release 2015-05-13 14:06:56 +02:00
Svein-Tore Griff With 85d66d52c0 Add DISABLE_ALL constant 2015-05-13 11:48:56 +02:00
Paal Joergensen a8b465adb7 Merge branch 'smart-file-names' 2015-05-13 10:16:13 +02:00
Svein-Tore Griff With eb6ec29cb6 Remove deprecated name 2015-05-12 16:09:36 +02:00
Frode Petterson ca0c848e0f Use correct element. 2015-05-12 10:04:21 +02:00
Frode Petterson 5568a59854 Pre-generate copyright information. 2015-05-11 16:00:55 +02:00
Frode Petterson cee887901b Make sure styles are filtered if they're not specified in the semantics. 2015-05-11 14:15:16 +02:00
Frode Petterson e404c3ac68 Allow certain style tags on spans. 2015-05-08 16:06:04 +02:00
Frode Petterson ba862f0078 Embed: Always br. Get w/h from correct el. 2015-05-07 15:16:59 +02:00
Frode Petterson e0534dd778 Fixed frame disable broken. Probably a merge gone wrong. 2015-05-07 15:13:28 +02:00
Frode Petterson ccc03782df Cleaned up docs to make JSdoc generation more meaningful. 2015-05-05 13:13:57 +02:00
Frode Petterson 467f97c11f Use correct uuid variable 2015-04-28 12:42:36 +02:00
Frode Petterson 31872111eb Use content. 2015-04-27 15:20:40 +02:00
Thomas Marstrander 9ee8130aae Added copyrights fix. 2015-04-27 13:21:31 +02:00
Frode Petterson 4683e61fa7 Delete correct export file. 2015-04-27 13:13:00 +02:00
Frode Petterson 66928f397e Merge branch 'master' of github.com:h5p/h5p-php-library 2015-04-27 10:15:11 +02:00
Frode Petterson e6ce2780fa Merge branch 'semi-fullscreen-z-index-fix' 2015-04-27 10:15:00 +02:00
Svein-Tore Griff With a0501eb861 Merge branch 'stable' 2015-04-22 22:58:00 +02:00
Frode Petterson ccccec84e7 Use correct path. 2015-04-22 15:19:01 +02:00
Svein-Tore Griff With ae512b2b03 Merge branch 'release' into stable 2015-04-22 14:01:56 +02:00
Frode Petterson 3eea931332 Merge branch 'release' into smart-file-names 2015-04-22 13:42:17 +02:00
Frode Petterson 260b6fe044 Restrict IE FullScreen. 2015-04-22 12:55:18 +02:00
Frode Petterson 886c631461 Use correct variable. 2015-04-22 10:58:59 +02:00
Frode Petterson 9a37a99574 Re-added "Remove empty params." to master.
This reverts commit 31ee0bd51a.
2015-04-22 10:44:16 +02:00
Frode Petterson 31ee0bd51a Removed "Remove empty params." from release.
This reverts commit 8c68f23823.
2015-04-22 10:43:18 +02:00
Frode Petterson 540c96178d Merge branch 'master' of github.com:h5p/h5p-php-library 2015-04-22 09:51:45 +02:00
Frode Petterson 1c6b818841 Merge branch 'release'
Conflicts:
	js/h5p.js
2015-04-22 09:51:36 +02:00
Frode Petterson af8e9e8f30 Relay events to top window. 2015-04-22 09:49:58 +02:00
Frode Petterson c13e0a0a9a Fixed fullscreen checker. 2015-04-21 16:55:23 +02:00
Frode Petterson cdceb41d74 Prevent running multiple resizer. 2015-04-21 16:55:04 +02:00
Frode Petterson b3dea65fd8 Remove element from DOM the correct way. 2015-04-21 16:54:31 +02:00
Frode Petterson 1091890596 Fixed fullscreen checker. 2015-04-21 16:22:51 +02:00
Frode Petterson 27a0a33298 Prevent running multiple resizer. 2015-04-21 15:08:59 +02:00
Frode Petterson 8433f654af Remove element from DOM the correct way. 2015-04-21 13:56:24 +02:00
Frode Petterson 28f8a8dc8a Create a spaceholder when resizing iframes. 2015-04-21 09:09:41 +02:00
Frode Petterson 51a77c02ab Merge branch 'master' of github.com:h5p/h5p-php-library 2015-04-20 15:37:59 +02:00
Frode Petterson 59bb32fa44 Create a spaceholder when resizing iframes. 2015-04-20 15:37:49 +02:00
Frode Petterson 8c68f23823 Remove empty params. 2015-04-20 15:10:31 +02:00
Frode Petterson fba8badf1a Use URL template to support URLs of different formatting. 2015-04-20 10:30:52 +02:00
Svein-Tore Griff With 165db6ff6c externalEmbed is either false or undefined it seems 2015-04-16 20:14:53 +02:00
Svein-Tore Griff With cf7ae066ad Add disable support for uploads as well 2015-04-15 13:54:46 +02:00
Svein-Tore Griff With 09c6d5c4f8 Handle cases where a field don't have params 2015-04-14 14:01:28 +02:00
Svein-Tore Griff With 80a80aef7a Better debugging 2015-04-14 14:01:14 +02:00
Thomas Marstrander 2725f591b7 Changed z-index of semi-fullscreen to 1000 to have priority over all drupal elements. 2015-04-14 13:41:27 +02:00
Svein-Tore Griff With 9a92a61484 Make sure state is ignored when disabled 2015-04-13 20:31:21 +02:00
Svein-Tore Griff With ba2355c2ec Make sure state is ignored when disabled 2015-04-13 20:30:40 +02:00
Svein-Tore Griff With 0b609e882d Add about to disable sources and make sure each source is set 2015-04-13 19:58:41 +02:00
Svein-Tore Griff With 868c06929d Whitespace changes 2015-04-13 18:41:53 +02:00
Svein-Tore Griff With fba425220e Resolve conflicts 2015-04-13 18:32:33 +02:00
Svein-Tore Griff With 912a670607 Merge branch 'master' into upgrade-speed 2015-04-13 18:16:19 +02:00
Svein-Tore Griff With 497301d6ad Add triggerXAPIScored and deprecate triggerXAPICompleted 2015-04-09 19:42:05 +02:00
Svein-Tore Griff With 5b36e468ac Rewrite so that we add options as an object instead of a very long list of parameters 2015-04-09 14:00:00 +02:00
Frode Petterson ea26ae95db Merge tag 'wp-1.4.0' into upgrade-speed 2015-04-08 09:35:57 +02:00
Svein-Tore Griff With 5b55b78ded createH5PTitle->createTitle 2015-04-07 19:52:18 +02:00
Svein-Tore Griff With ed23b9fff0 Merge branch 'master' into aggregated-xapi 2015-04-07 19:33:48 +02:00
Svein-Tore Griff With 5c3620c637 Bubbling for event system 2015-04-07 19:33:21 +02:00
Svein-Tore Griff With efbe56001d User data fixes 2015-04-07 19:32:44 +02:00
Svein-Tore Griff With cfa747f20c Add path fixes 2015-04-07 19:30:46 +02:00
Frode Petterson 5adffcaeb8 Added content id. 2015-04-07 15:36:28 +02:00
Frode Petterson 2dfdc04217 Fixed exports with development mode enabled. 2015-03-27 11:51:17 +01:00
Frode Petterson bf227bdae0 Moved in changes from Drupal. 2015-03-27 10:29:34 +01:00
Frode Petterson 7a3e6ee847 Merge branch 'aggregated-xapi' of ssh://stash.joubel.com:7999/h5p/php-core into aggregated-xapi
Conflicts:
	js/h5p.js
2015-03-27 10:27:54 +01:00
Svein-Tore Griff With 61a8e7e9e9 Make view work again as well 2015-03-24 19:36:13 +01:00
Svein-Tore Griff With 065ee4e8a2 Make editor work again 2015-03-24 19:29:28 +01:00
Svein-Tore Griff With ef7a31d2e1 Try to get back the no url branch 2015-03-24 18:55:13 +01:00
Svein-Tore Griff With 58d0d3e32c Merge branch 'no-url-fopen' into aggregated-xapi 2015-03-24 18:27:23 +01:00
Svein-Tore Griff With c746457a87 Make xAPI work in editor 2015-03-24 18:24:07 +01:00
Frode Petterson c4c2f6b16a Display dialog when content user data is reset. 2015-03-24 16:17:26 +01:00
Frode Petterson 24fa34f9c2 Avoid parsing state multiple times. 2015-03-24 11:01:23 +01:00
Frode Petterson e153acbf3e Merge branch 'no-url-fopen' into content-user-data 2015-03-23 10:54:00 +01:00
Frode Petterson 9ae40ad739 Merge branch 'master' into no-url-fopen 2015-03-23 10:53:47 +01:00
Frode Petterson acd3aa2dba Merge branch 'master' of github.com:h5p/h5p-php-library 2015-03-23 10:53:30 +01:00
Frode Petterson cfe73006a2 Added back deprecated function. 2015-03-23 10:53:21 +01:00
Frode Petterson bb059d63e2 Merge branch 'no-url-fopen' into content-user-data 2015-03-23 10:02:23 +01:00
Frode Petterson eee77519b7 Always use complete URLs. 2015-03-23 09:45:02 +01:00
Frode Petterson 67288c2a0b Added auto save loop. Added save after xAPI events. Made it possible to disable saving. 2015-03-22 20:44:35 +01:00
Svein-Tore Griff With 8e113ff792 Add parameter set as parameter 5 to new runnable, and blacklist libraries that already have a custom third parameter for their constructor 2015-03-22 20:39:16 +01:00
Svein-Tore Griff With 9d38f83886 Refactor completed listener to use more of the new xAPI api functions 2015-03-22 20:38:57 +01:00
Svein-Tore Griff With eb02a5942d Make externalDispatcher from framed content work again 2015-03-22 20:38:33 +01:00
Svein-Tore Griff With d3453b8637 Context bug fix 2015-03-22 20:38:17 +01:00
Svein-Tore Griff With 5d6d22a13f Accept other verbs than the adl verbs 2015-03-22 20:37:48 +01:00
Svein-Tore Griff With 46c9260755 Don't bubble by default 2015-03-22 20:37:28 +01:00
Svein-Tore Griff With 6b3e550a48 Don't bubble by default 2015-03-22 20:37:10 +01:00
Frode Petterson a712d6ed61 Removed debug. 2015-03-22 19:31:35 +01:00
Frode Petterson 431cff0196 New API for saving user data per content. 2015-03-22 19:28:16 +01:00
Svein-Tore Griff With 9a204b3d8f Make sure title are added 2015-03-22 15:14:28 +01:00
Svein-Tore Griff With c4e488f9c8 Get contentId from the right place in the statement 2015-03-22 13:27:40 +01:00
Svein-Tore Griff With 44e8cba365 Merge branch 'master' into aggregated-xapi 2015-03-22 13:14:40 +01:00
Svein-Tore Griff With 1c4a5e014b Comment out prefixing that isn't working 2015-03-22 13:12:44 +01:00
Svein-Tore Griff With e76fc9eff3 Merge branch 'no-url-fopen' of https://github.com/h5p/h5p-php-library 2015-03-22 12:46:41 +01:00
Svein-Tore Griff With 5a882e4d55 Improve title generator 2015-03-22 12:45:03 +01:00
Svein-Tore Griff With 93f2bcc01a Use uuid instead of h5pUUID 2015-03-22 12:44:55 +01:00
Svein-Tore Griff With e14c24cc07 Fix xAPI statement structure to follow the standard better 2015-03-22 12:43:07 +01:00
Svein-Tore Griff With b79a5b61b8 uuid consists of lowercase letters 2015-03-22 12:42:07 +01:00
Svein-Tore Griff With 3da0de4626 Fix bubble system 2015-03-22 11:17:58 +01:00
Svein-Tore Griff With 313bb757ba Add bubble system and xAPI context 2015-03-21 16:45:38 +01:00
Svein-Tore Griff With 76b0fc04f8 Make UUID creator available for everyone 2015-03-21 14:16:31 +01:00
Frode Petterson e6e3ee7559 Allow assets to be relative to another location.
Allow assets to contain external URLs.
2015-03-20 11:28:21 +01:00
Svein-Tore Griff With b04756a520 Merge branch 'master' into improved-packaging 2015-03-19 19:27:47 +01:00
Svein-Tore Griff With 8494e85c3e Remove todo items 2015-03-19 19:27:44 +01:00
Frode Petterson 51a1d333e2 Improved packaging. Made sure zip format is followed by always using forward slashes. This will make h5p export work on Windows. 2015-03-19 16:58:48 +01:00
Frode Petterson 1b28c7b128 Use different vars for URL and file path to avoid having allow_url_fopen = On. 2015-03-18 14:25:55 +01:00
Frode Petterson 6541faf8ba Renamed humanId => slug.
Moved most of the slug generating code out of the framework and into core.
Remove old export files.
Use old export file until new slug is generated.
Added support for converting more special chars.
2015-03-13 15:17:19 +01:00
Frode Petterson c7a7a99590 Merge branch 'master' into smart-file-names 2015-03-13 13:05:20 +01:00
Frode Petterson fb82328535 Fullscreen fix 2015-03-13 12:51:31 +01:00
Frode Petterson c35d7f8334 Added support for generating human readable H5P file names. 2015-03-12 14:38:10 +01:00
Frode Petterson 5931ed5d76 Merge branch 'new-font' 2015-03-11 13:17:44 +01:00
Frode Petterson 7ef9ffbf1f Added default sort option to data view. Improved buttons. 2015-03-11 11:40:07 +01:00
Frode Petterson efd79c9e79 Support init target. 2015-03-10 10:09:31 +01:00
Frode Petterson 2f44edd65a Prevent double init. Ie9 fix. 2015-03-10 10:08:35 +01:00
Frode Petterson 72db596bac Make sure H5P.externalEmbed is set inside the iframe. Run H5P.init from external resource to ensure correct execution order in IE9. 2015-03-10 09:53:33 +01:00
Svein-Tore Griff With b45bfe770b Critical bug fix for safari 2015-03-06 12:56:41 +01:00
Frode Petterson 6d4caf855d Fixed error handling. 2015-03-04 11:30:20 +01:00
Frode Petterson c91391e0bc Fixed URLs.
Finishing touches on the time tracking.
2015-03-04 11:13:32 +01:00
Frode Petterson 812c3b5e7c Merge branch 'master' into upgrade-speed 2015-03-04 10:21:29 +01:00
Thomas Marstrander 23f68d821e Added woff to css inline 2015-03-04 10:06:35 +01:00
Svein-Tore Griff With 96b1014f80 Merge branch 'master' into new-embed 2015-03-03 18:10:07 +01:00
Frode Petterson acca962775 Fixed misplaced stash (after merge). 2015-03-03 11:03:18 +01:00
Frode Petterson cd5b37df62 Merge branch 'master' into new-font 2015-03-03 10:46:26 +01:00
Frode Petterson 22d085386e Merge branch 'new-embed' of github.com:h5p/h5p-php-library into new-embed 2015-03-02 16:03:48 +01:00
Frode Petterson e961f614a4 Fixed so that iframes can be loaded before resizer script. 2015-03-02 15:53:29 +01:00
Svein-Tore Griff With 99db5699fb Handle anonymous users 2015-03-02 15:49:27 +01:00
Svein-Tore Griff With 553ae243d2 UX improvements to embed code system 2015-03-02 15:01:05 +01:00
Frode Petterson 8e53f62679 Make sure admin container is empty. 2015-03-02 13:42:15 +01:00
Frode Petterson 07cd5c0d42 Added a floating touch. 2015-02-27 15:37:16 +01:00
Frode Petterson 1c1829b13b Fixed integration bug. 2015-02-27 14:53:38 +01:00
Frode Petterson aac10b86fa Make old embed code insert new. 2015-02-27 14:53:26 +01:00
Frode Petterson f2595b2bce Change how H5Ps are integrated. 2015-02-27 13:59:42 +01:00
Frode Petterson d1cc8bcb71 Moved embed template to core. 2015-02-27 11:05:22 +01:00
Frode Petterson 77d589ec68 Fixed absolute URLs violating its parent. 2015-02-27 10:55:47 +01:00
Frode Petterson 1e4a7ff26f Removed unused code. 2015-02-27 10:29:43 +01:00
Frode Petterson 4e594dd573 Fixed dialog pos and expand. 2015-02-27 10:26:57 +01:00
Frode Petterson 037e26f42b Space support. 2015-02-27 08:57:02 +01:00
Frode Petterson 3463a3c671 Added support for multiple workers during content upgrade. 2015-02-26 16:16:20 +01:00
Frode Petterson fabde2f1ce Automatic positioning. 2015-02-25 13:05:45 +01:00
Frode Petterson 1861f696c1 Added new embed design. 2015-02-25 12:10:07 +01:00
Frode Petterson 0c5aacfa24 Fixed old fullscreen exit in iframe. 2015-02-24 16:02:14 +01:00
Svein-Tore Griff With d6e69e63ee Use this instead of self so that we're compatible with jsdoc 2015-02-20 15:34:38 +01:00
Frode Petterson 1fef537c8c Merge branch 'new-embed' of github.com:h5p/h5p-php-library into new-embed 2015-02-20 13:17:52 +01:00
Frode Petterson 93cd6eea28 Removed empty file. 2015-02-20 13:17:41 +01:00
Thomas Marstrander 152b51f02a Added new font 2015-02-20 13:00:50 +01:00
Frode Petterson f76290cdde Made user results work in new embed. 2015-02-20 11:41:09 +01:00
Frode Petterson 971a55df58 Satisfy JSHint and prevent crashing. 2015-02-20 10:26:33 +01:00
Frode Petterson 688b00f55e Merge branch 'master' into new-embed
Conflicts:
	js/h5p.js
2015-02-20 10:15:36 +01:00
Frode Petterson 2b1c894307 Merge branch 'master' into settings
Conflicts:
	h5p.classes.php
2015-02-19 15:50:04 +01:00
Svein-Tore Griff With 95a0b000db Remove scary error messages 2015-02-18 19:58:03 +01:00
Svein-Tore Griff With 3d4d72c5a7 Avoid exporting git files 2015-02-18 19:50:23 +01:00
Svein-Tore Griff With c7c46bc779 Fix spelling error 2015-02-18 15:20:20 +01:00
Svein-Tore Griff With 0d8fe7498c Remove code not being used 2015-02-18 15:08:55 +01:00
Svein-Tore Griff With e981e7d605 Trigger xAPI events on top as well if inside ifra 2015-02-18 10:59:47 +01:00
Svein-Tore Griff With d6db07481e Make sure the contentId is set on content types 2015-02-18 09:07:57 +01:00
Svein-Tore Griff With 1995da20bb Remove old todo items 2015-02-18 09:07:38 +01:00
Svein-Tore Griff With a96e5cc7b9 Make the xAPI integration work for stuff that aren't content types 2015-02-18 09:07:19 +01:00
Svein-Tore Griff With 0a6dd4808b Rename the external api 2015-02-17 10:57:21 +01:00
Svein-Tore Griff With 537c62ab33 Get url to the H5P content from the framework 2015-02-17 10:57:12 +01:00
Svein-Tore Griff With c330282351 Refactor xAPI code 2015-02-16 16:47:04 +01:00
Svein-Tore Griff With b575426f83 Add documentation 2015-02-16 15:30:49 +01:00
Svein-Tore Griff With 2237f026c9 Documentation updates 2015-02-16 14:26:09 +01:00
Svein-Tore Griff With 10fbca1549 Documentation updates 2015-02-16 14:22:54 +01:00
Frode Petterson 84f8fb1cff Merge branch 'master' of github.com:h5p/h5p-php-library 2015-02-12 16:00:41 +01:00
Frode Petterson 1d24d073ed Moved "libraries saving" out of savePackage to make it easier to read and handle. Added UI messages when adding and updating libraries. Minor code optimizations. 2015-02-12 15:56:31 +01:00
Svein-Tore Griff With 8d7ce8f4f1 Merge branch 'master' of https://github.com/h5p/h5p-php-library 2015-02-12 15:46:55 +01:00
Svein-Tore Griff With cb1be24f62 Merge branch 'master' into xAPI 2015-02-12 15:46:34 +01:00
Svein-Tore Griff With 83a077be15 Rename api function 2015-02-12 15:46:25 +01:00
Frode Petterson 9fc5f82b2f Fixed empty frame. 2015-02-12 11:52:55 +01:00
Svein-Tore Griff With 36b1fd2d8c Add helper function to get verbs 2015-02-11 20:06:40 +01:00
Svein-Tore Griff With 5483a3f151 Remove event dispatcher 2015-02-11 18:02:58 +01:00
Svein-Tore Griff With c4aedca522 Resolve conflicts 2015-02-11 18:02:25 +01:00
Svein-Tore Griff With f8434bf788 Add scopes to event system 2015-02-11 17:31:01 +01:00
Svein-Tore Griff With 079f4992b4 bugfixes 2015-02-11 15:56:35 +01:00
Frode Petterson 42fbb6ab1f Reverse direction of dependency loading. The libraries used last in the parameters are now loaded first, e.g. summary is now loaded before iv! 2015-02-11 14:40:01 +01:00
Frode Petterson fb77a4d20d bugfix. 2015-02-10 16:40:23 +01:00
Frode Petterson c764d13b32 Moved display options helpers into core. 2015-02-10 16:29:16 +01:00
Frode Petterson 3c712193b3 Merge branch 'master' into settings
Conflicts:
	styles/h5p.css
2015-02-09 15:25:09 +01:00
Frode Petterson a0c5fe0e18 Comment out semi full screen. 2015-02-09 11:51:39 +01:00
Frode Petterson 11d9cb2f35 Trigger events. 2015-02-09 11:47:33 +01:00
Frode Petterson 18a3ed4a8f Simplified integration code to avoid to much duplication.
Added resizing script for new embed code.
Added iframe communicator when embedding.
2015-02-09 10:22:14 +01:00
Svein-Tore Griff With a090468657 Merge branch 'text-editor' 2015-02-05 12:01:16 +01:00
Svein-Tore Griff With 9a0da8614b Add helper functions 2015-02-05 10:46:55 +01:00
Svein-Tore Griff With c8a2465827 Add documentation and change function names for deprecated functions 2015-02-04 18:43:06 +01:00
Frode Petterson 21674d31ac Merge branch 'master' into settings
Conflicts:
	js/h5p.js
2015-02-04 09:32:03 +01:00
Svein-Tore Griff With fc4f791e6e Bump core api version 2015-02-03 20:15:15 +01:00
Svein-Tore Griff With efdd7f9f7a Moving x-api and Event handling code to separate files and refining it 2015-02-03 20:11:01 +01:00
Svein-Tore Griff With 7daa4ff2c8 Merge branch 'master' into xAPI 2015-02-03 17:47:26 +01:00
Svein-Tore Griff With f66e6a3ce9 Merge branch 'manually-move-files' 2015-02-03 14:02:54 +01:00
Svein-Tore Griff With e12ba70b95 Merge branch 'master' into adaptivity 2015-02-03 13:44:52 +01:00
Svein-Tore Griff With daa91b1372 Merge branch 'master' into text-editor 2015-02-02 14:28:52 +01:00
Svein-Tore Griff With ae6329595b Add ordering of libraries 2015-01-30 10:59:40 +01:00
Svein-Tore Griff With 06ba81c2ab Merge branch 'master' of https://github.com/h5p/h5p-php-library 2015-01-28 15:35:27 +01:00
Svein-Tore Griff With b0e6bed517 Update README.txt 2015-01-27 11:28:02 +01:00
Frode Petterson ead790ae1a Make sure fields in optional groups also becomes optional. 2015-01-20 14:48:22 +01:00
Svein-Tore Griff With 3beaa8302a Remove H5P special chars 2015-01-14 18:13:23 +01:00
Svein-Tore Griff With 62618104af Resolve conflict 2015-01-14 18:09:18 +01:00
Svein-Tore Griff With 64dd059c03 Add support for deprecated event system 2015-01-14 18:08:36 +01:00
Svein-Tore Griff With 61eb998d48 Add xAPI todo list 2015-01-14 17:27:32 +01:00
Svein-Tore Griff With 43e98afe4b Merge branch 'text-editor' of https://github.com/h5p/h5p-php-library into text-editor 2015-01-14 09:55:48 +01:00
Frode Petterson 8cee9820b0 Merge branch 'master' into text-editor 2015-01-13 13:38:51 +01:00
Frode Petterson ae8609dd86 Replaced another rename function. 2015-01-09 10:00:40 +01:00
git e7b7cd2abe Issue https://www.drupal.org/node/2402099 by drinkdecaf: H5P on Pantheon Environments 2015-01-09 09:59:29 +01:00
Frode Petterson 35a7f39a0b Merge branch 'master' of github.com:h5p/h5p-php-library 2015-01-09 09:53:13 +01:00
Svein-Tore Griff With 1420a96a2c Merge branch 'atomic-dev-mode' 2015-01-08 11:20:49 +01:00
Svein-Tore Griff With fb517c7592 Merge branch 'master' into atomic-dev-mode 2015-01-08 11:20:18 +01:00
Pål Jørgensen ec4678bf0b Fixed issue #2397891 (drupal.org), and made jshint a little happier 2014-12-30 10:54:26 +01:00
Frode Petterson 74fc840366 Added support for debugging events. 2014-12-17 16:57:46 +01:00
Frode Petterson 1aef9e376d Removed ulgy border from full screen. 2014-12-15 16:04:01 +01:00
Frode Petterson acb36845c0 Fixed wrong args. 2014-12-15 11:50:48 +01:00
Svein-Tore Griff With 7dfab8393f Merge branch 'atomic-dev-mode' into text-editor 2014-12-03 16:10:50 +01:00
falcon fb07f54e35 Make it possible to do the dependency transactions in an atomic way 2014-11-27 23:14:15 +01:00
Frode Petterson 8d5d16652b Merge tag 'wp-1.2.2' into stable 2014-11-27 11:36:54 +01:00
Frode Petterson 746f6417a4 Merge branch 'master' into stable 2014-11-27 11:24:15 +01:00
Svein-Tore Griff With e2abcd20b1 Merge branch 'master' of https://github.com/h5p/h5p-php-library 2014-11-27 11:14:12 +01:00
Svein-Tore Griff With cc455f2b2d Implement changes after testing against Scrom Cloud 2014-11-17 11:08:43 +01:00
Svein-Tore Griff With e581690ce6 Merge branch 'master' into stable 2014-11-11 11:37:12 +01:00
Frode Petterson 2bba9a183b Bumped api version. 2014-11-10 11:35:15 +01:00
Frode Petterson bc5159e272 Added event dispatcher. 2014-11-10 11:31:23 +01:00
Svein-Tore Griff With 05d9982070 Add code to make it easy for others to register for xAPI events 2014-11-02 21:37:30 +01:00
Svein-Tore Griff With 5d32c4451c Add real url to statement object 2014-11-02 21:30:19 +01:00
Svein-Tore Griff With 378224f7c6 Get real actor 2014-11-02 21:16:27 +01:00
Svein-Tore Griff With 01779c0004 Use score instead of points 2014-11-02 21:16:19 +01:00
Svein-Tore Griff With 658db52f89 Resolve conflicts 2014-11-02 21:07:08 +01:00
Frode Petterson d0e8bfe0b1 Merge branch 'master' of github.com:h5p/h5p-php-library 2014-11-02 17:04:28 +01:00
Frode Petterson 3220cea7af Merge branch 'master' of github.com:h5p/h5p-php-library 2014-11-02 10:22:37 +01:00
Svein-Tore Griff With 9391b60a03 Refactoring xAPI to use inheritence and event classes 2014-11-01 21:54:42 +01:00
Svein-Tore Griff With b3da2c5b32 Resolving conflicts 2014-11-01 20:42:34 +01:00
Svein-Tore Griff With af0ec62d02 Merge branch 'xAPI' of https://github.com/h5p/h5p-php-library into xAPI 2014-11-01 12:31:27 +01:00
Frode Petterson 0d874e11f8 Merge branch 'whitelist' into settings 2014-10-28 10:05:38 +01:00
falcon 22a559ccd8 Shorter function names and a few bugfixes 2014-10-26 22:18:28 +01:00
Frode Petterson 6c38bfe38c Merge branch 'whitelist' into settings 2014-10-23 15:31:34 +02:00
Frode Petterson 2636ddc393 Make it easy to disable generic content features. 2014-10-23 14:02:34 +02:00
Svein-Tore Griff With 5922786982 xAPI 2014-10-13 22:19:59 +02:00
58 changed files with 11926 additions and 2011 deletions

2
.gitignore vendored
View File

@ -1 +1,3 @@
vendor
*~
.idea

40
.travis.yml Normal file
View File

@ -0,0 +1,40 @@
language: php
# At present the only jobs to run are a php lint.
# Run this against all supported versions of PHP.
jobs:
include:
# Bionic supports PHP 7.1, 7.2, 7.3, and 7.4.
# https://docs.travis-ci.com/user/reference/bionic/#php-support
- php: 7.4
dist: bionic
- php: 7.3
dist: bionic
- php: 7.2
dist: bionic
- php: 7.1
dist: bionic
# Xenial was the last Travis distribution to support PHP 5.6, and 7.0.
# https://docs.travis-ci.com/user/reference/xenial/#php-support
- php: 7.0
dist: xenial
- php: 5.6
dist: xenial
# Trusty was the last Travis distribution to support PHP 5.4, and 5.5.
# https://docs.travis-ci.com/user/languages/php/#php-54x---55x-support-is-available-on-precise-and-trusty-only
- php: 5.5
dist: trusty
- php: 5.4
dist: trusty
# Precise was the last Travis distribution to support PHP 5.2, and 5.3.
# https://docs.travis-ci.com/user/languages/php/#php-52x---53x-support-is-available-on-precise-only
- php: 5.3
dist: precise
script:
# Run a php lint across all PHP files.
- find . -type f -name '*\.php' -print0 | xargs -0 -n1 php -l

674
LICENSE.txt Normal file
View File

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

View File

@ -1,13 +1,14 @@
This folder contains the h5p general library. The files within this folder are not specific to any framework.
This folder contains the general H5P library. The files within this folder are not specific to any framework.
Any interaction with LMS, CMS or other frameworks is done through interfaces. Plattforms needs to implement
the following interfaces in order for the h5p libraries to work:
Any interaction with an LMS, CMS or other frameworks is done through interfaces. Platforms need to implement
the H5PFrameworkInterface(in h5p.classes.php) and also do the following:
- TODO: Fill in here
- Provide a form for uploading H5P packages.
- Place the uploaded H5P packages in a temporary directory
+++
In addition frameworks need to do the following:
See existing implementations for details. For instance the Drupal H5P module located at drupal.org/project/h5p
- Provide a form for uploading h5p packages.
- Place the uploaded h5p packages in a temporary directory
We will make available documentation and tutorials for creating platform integrations in the future.
See existing implementations for details. For instance the Drupal h5p module located on drupal.org/project/h5p
The H5P PHP library is GPL licensed due to GPL code being used for purifying HTML provided by authors.

35
composer.json Normal file
View File

@ -0,0 +1,35 @@
{
"name": "h5p/h5p-core",
"type": "library",
"description": "H5P Core functionality in PHP",
"keywords": ["h5p","hvp","interactive","content","quiz"],
"homepage": "https://h5p.org",
"license": "GPL-3.0",
"authors": [
{
"name": "Svein-Tore Griff With",
"email": "with@joubel.com",
"homepage": "http://joubel.com",
"role": "CEO"
},
{
"name": "Frode Petterson",
"email": "frode.petterson@joubel.com",
"homepage": "http://joubel.com",
"role": "Developer"
}
],
"require": {
"php": ">=5.3.0"
},
"autoload": {
"files": [
"h5p.classes.php",
"h5p-development.class.php",
"h5p-file-storage.interface.php",
"h5p-default-storage.class.php",
"h5p-event-base.class.php",
"h5p-metadata.class.php"
]
}
}

View File

@ -1,5 +1,5 @@
<h2>Overview</h2>
<p>H5P is a file format for content/applications made using modern, open web technlogies (HTML5). The format enables easy installation and transfer of applications/content on different CMSes, LMSes and other platforms. An H5P canbe uploaded and published on a platform in mostly the same way one would publish a Flash file today. H5P files may also be updated by simply uploading a new version of the file, the same way as one would using Flash.</p>
<p>H5P is a file format for content/applications made using modern, open web technologies (HTML5). The format enables easy installation and transfer of applications/content on different CMSes, LMSes and other platforms. An H5P can be uploaded and published on a platform in mostly the same way one would publish a Flash file today. H5P files may also be updated by simply uploading a new version of the file, the same way as one would using Flash.</p>
<p>H5P opens for extensive reuse of code and wide flexibility regarding what may be developed as an H5P.</p>
<p>The system uses package files containing all necessary files and libraries for the application to function. These files are based on open formats.</p>
<h2>Overview of package files</h2>
@ -12,7 +12,7 @@
<li>A mandatory file in the root folder named <i>h5p.json</i></li>
<li>An optional image file named <i>h5p.jpg</i>. This is an icon or an image of the application, 512 × 512 pixels. This image may be used by the platform as a preview of the application, and could be included in OG meta tags for use with social media.</li>
<li>One content folder, named <i>content</i>. This will contain the preset configuration for the application, as well as any required media files.</li>
<li>One or more library diractories named the same as the library's internal name.</li>
<li>One or more library directories named the same as the library's internal name.</li>
</ol>
<h2>h5p.json</h2>
<p>The <i>h5p.json</i> file is a normal JSON text file containing a JSON object with the following predefined properties.</p>
@ -27,7 +27,7 @@
<ul><li>contentType - Textual description of the type of content.</li>
<li>description - Textual description of the package.</li>
<li>author - Name of author.</li>
<li>license - Kode for the content license. Use the following creative commons codes: cc-by, cc-by-sa, cc-by-nd, cc-by-nc, cc-by-nc-sa, cc-by-nc-nd. In addition for public domain: pd, and closed license: cr. More may be added later.</li>
<li>license - Code for the content license. Use the following Creative Commons codes: cc-by, cc-by-sa, cc-by-nd, cc-by-nc, cc-by-nc-sa, cc-by-nc-nd. In addition for public domain: pd, and closed license: cr. More may be added later.</li>
<li>dynamicDependencies - Libraries that may be loaded dynamically during execution.</li>
<li>width - Width of the package content in cases where the package is not dynamically resizable.</li>
<li>height - Height of the package content.</li>
@ -74,9 +74,9 @@
<p>The root of a library folder shall contain a file name <i>library.json</i> formatted similar to the package's <i>hp5.json</i>, but with a few differences. The library shall also have one or more images in the root folder, named <i>library.jpg</i>, <i>library1.jpg</i> etc. Image sizes 512px × 512px, and will be used in the H5P editor tool.</p>
<p>Libraries are not allowed to modify the dokument tree in ways that will have consequences for the web site or will be noticable by the user without the library explicitly being initialized from the main package library or another invoked library.</p>
<p>Libraries are not allowed to modify the document tree in ways that will have consequences for the web site or will be noticeable by the user without the library explicitly being initialized from the main package library or another invoked library.</p>
<p>The library shall always include a Javascript object function named the same as the defined library <i>machineName</i> (defined in <i>library.json</i> and used as the library folder name). This object will be instantiated with the library options as parameter. The resulting object must contain a function <i>attach(target)</i> that will be called after instantiation to attach the library DOM to the main DOM inside <i>target</i></p>
<p>The library shall always include a JavaScript object function named the same as the defined library <i>machineName</i> (defined in <i>library.json</i> and used as the library folder name). This object will be instantiated with the library options as parameter. The resulting object must contain a function <i>attach(target)</i> that will be called after instantiation to attach the library DOM to the main DOM inside <i>target</i></p>
<h3>Example</h3>
<p>A library called H5P.multichoice would typically be instantiated and attached to the page like this:</p>
@ -138,7 +138,7 @@ multichoice.attach($multichoiceContainer);</code>
<h2>Allowed file types</h2>
<p>Files that require server side execution or that cannot be regarded an open standard shall not be used. Allowed file types: js, json, png, jpg, gif, svg, css, mp3, wav (audio: PCM), m4a (audio: AAC), mp4 (video: H.264, audio: AAC/MP3), ogg (video: Theora, audio: Vorbis) and webm (video VP8, audio: Vorbis). Administrators of web sites implementing H5P may open for accepting further formats. HTML files shall not be used. HTML for each library shall be inserted from the library scripts to ease code reuse. (By avoiding content being defined in said HTML).</p>
<h2>API functions</h2>
<p>The following javascript functions are available through h5p:</p>
<p>The following JavaScript functions are available through h5p:</p>
<ul>
<li>H5P.getUserData(namespace, variable)</li>
<li>H5P.setUserData(namespace, variable, data)</li>
@ -156,13 +156,13 @@ multichoice.attach($multichoiceContainer);</code>
<h2>Best practices</h2>
<p>H5P is a very open standard. This is positive for flexibility. Most content may be produces as H5P. But this also allows for bad code, security weaknesses, code that may be difficult to reuse. Therefore the following best practices should be followed to get the most from H5P:</p>
<ul>
<li>Think reusability when creating a library. H5P support depencies between libraries, so the same small quiz-library may be used in various larger packages or libraries.</li>
<li>H5P support library updates. This enables all content using a common library to be updated at once. This must be accounted for when writing new libraries. A library should be as general as possible. The content format should be thought out so there are no changes to the required content data when a library is updated. Note: Multiple versions of a library may exists at the same time, only patch level updates will be automatically installed.</li>
<li>An H5P should not interact directly with the containing web site. It shall only affect elements within its own generated DOM tree. Elements shall also only be injected within the target defined on initialization. This is to avoid depencies to a specific platform or web page.</li>
<li>Think reusability when creating a library. H5P support dependencies between libraries, so the same small quiz-library may be used in various larger packages or libraries.</li>
<li>H5P supports library updates. This enables all content using a common library to be updated at once. This must be accounted for when writing new libraries. A library should be as general as possible. The content format should be thought out so there are no changes to the required content data when a library is updated. Note: Multiple versions of a library may exists at the same time, only patch level updates will be automatically installed.</li>
<li>An H5P should not interact directly with the containing web site. It shall only affect elements within its own generated DOM tree. Elements shall also only be injected within the target defined on initialization. This is to avoid dependencies to a specific platform or web page.</li>
<li>Prefix objects, global functions, etc with h5p to minimize the chance of namespace conflicts with the rest of the web page. Remember that there may also be multiple H5P objects inserted on a page, so plan ahead to avoid conflicts.</li>
<li>Content should be responsive.</li>
<li>Content should be WCAG 2 AA compliant</li>
<li>All generated HTML should validate.</li>
<li>All css should validate (some browser specific non-standard CSS may at times be required)</li>
<li>Best practices for javascript, html, etc. should of course also be followed when writing an H5P.</li>
<li>All CSS should validate (some browser specific non-standard CSS may at times be required)</li>
<li>Best practices for JavaScript, HTML, etc. should of course also be followed when writing an H5P.</li>
</ul>

20
embed.php Normal file
View File

@ -0,0 +1,20 @@
<!doctype html>
<html lang="<?php print $lang; ?>" class="h5p-iframe">
<head>
<meta charset="utf-8">
<title><?php print $content['title']; ?></title>
<?php for ($i = 0, $s = count($scripts); $i < $s; $i++): ?>
<script src="<?php print $scripts[$i]; ?>"></script>
<?php endfor; ?>
<?php for ($i = 0, $s = count($styles); $i < $s; $i++): ?>
<link rel="stylesheet" href="<?php print $styles[$i]; ?>">
<?php endfor; ?>
<?php if (!empty($additional_embed_head_tags)): print implode("\n", $additional_embed_head_tags); endif; ?>
</head>
<body>
<div class="h5p-content" data-content-id="<?php print $content['id']; ?>"></div>
<script>
H5PIntegration = <?php print json_encode($integration); ?>;
</script>
</body>
</html>

BIN
fonts/h5p-core-28.eot Normal file

Binary file not shown.

114
fonts/h5p-core-28.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 97 KiB

BIN
fonts/h5p-core-28.ttf Normal file

Binary file not shown.

BIN
fonts/h5p-core-28.woff Normal file

Binary file not shown.

BIN
fonts/h5p-hub-publish.eot Normal file

Binary file not shown.

38
fonts/h5p-hub-publish.svg Normal file
View File

@ -0,0 +1,38 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>
<json>
<![CDATA[
{
"fontFamily": "h5p-hub",
"description": "Font generated by IcoMoon.",
"majorVersion": 1,
"minorVersion": 3,
"version": "Version 1.3",
"fontId": "h5p-hub",
"psName": "h5p-hub",
"subFamily": "Regular",
"fullName": "h5p-hub"
}
]]>
</json>
</metadata>
<defs>
<font id="h5p-hub" horiz-adv-x="1024">
<font-face units-per-em="1024" ascent="960" descent="-64" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" horiz-adv-x="512" d="" />
<glyph unicode="&#xe900;" glyph-name="dropdown" data-tags="dropdown" d="M1004.654 717.002c-11.526 11.526-27.853 19.209-45.142 19.209h-895.161c-35.538 0-63.391-27.853-64.352-63.391 0-17.289 6.724-33.616 19.209-46.103l447.582-447.582c24.013-24.972 63.391-25.933 88.363-1.92 0.961 0.961 0.961 0.961 1.92 1.92l447.582 447.582c24.972 24.013 25.933 63.391 1.92 88.363-0.961 0.961-0.961 0.961-1.92 1.92z" />
<glyph unicode="&#xe901;" glyph-name="info" data-tags="info" d="M745.14 76.307c-0.699 25.827-20.941 46.069-46.768 46.768h-46.069v418.813c-1.395 25.827-21.639 46.069-46.768 46.069h-279.209c-25.827 0-46.768-20.941-47.465-46.768v-92.837c0.699-25.827 20.941-46.069 46.768-46.768h46.768v-279.209h-46.069c-25.827-0.699-46.069-20.941-46.768-46.768v-92.837c0.699-25.827 20.941-46.069 46.768-46.768h372.045c25.827 0.699 46.069 20.941 46.768 46.768v93.534zM638.343 946.041c-8.376 9.075-20.242 13.96-32.806 13.96h-185.673c-25.827-0.699-46.069-20.941-46.768-46.768v-139.604c0.699-25.827 20.941-46.069 46.768-46.768h186.372c25.129 1.395 45.371 21.639 46.069 46.768v139.604c0 12.564-5.584 24.43-13.96 32.806z" />
<glyph unicode="&#xe902;" glyph-name="thick-arrow" data-tags="thick-arrow" d="M997.162 446.653c0.634 22.167-8.234 44.336-24.701 59.537l-428.789 428.789c-32.302 32.936-85.505 33.568-118.44 0.634 0 0-0.634-0.634-0.634-0.634l-49.403-49.403c-32.936-32.302-32.936-84.871-1.266-117.806 0.634-0.634 0.634-0.634 1.266-1.266l192.544-193.81h-463.625c-21.535 0.634-41.802-8.234-55.737-24.701-14.567-16.467-22.167-38.002-21.535-59.537v-84.238c-0.634-21.535 6.967-43.068 21.535-59.537 13.935-16.467 34.202-25.335 55.737-24.701h464.259l-193.81-190.644c-32.936-32.936-33.568-86.138-0.634-119.073 0 0 0.634-0.634 0.634-0.634l49.403-49.403c32.936-32.302 86.138-32.302 119.073 0l429.423 429.423c15.201 15.201 24.067 35.468 24.701 57.003v0z" />
<glyph unicode="&#xe903;" glyph-name="check" data-tags="check" d="M1021.469 686.541c0 17.084-6.328 32.903-18.349 44.924l-89.849 89.215c-24.677 24.677-64.539 24.677-89.215 0.633 0 0 0 0-0.633-0.633l-432.156-432.79-193.616 194.25c-24.677 24.677-64.539 24.677-89.215 0.633 0 0 0 0-0.633-0.633l-89.215-89.215c-24.677-24.677-24.677-64.539-0.633-89.215 0 0 0 0 0.633-0.633l327.755-327.755c24.677-24.677 64.539-24.677 89.215-0.633 0 0 0 0 0.633 0.633l569.46 569.46c12.022 12.022 18.349 27.84 18.349 44.924v0l-2.531-3.163z" />
<glyph unicode="&#xe904;" glyph-name="close" data-tags="close" d="M1024 856.869l-103.131 103.131-408.869-408.869-408.869 408.869-103.131-103.131 408.869-408.869-408.869-408.869 103.131-103.131 408.869 408.869 408.869-408.869 103.131 103.131-408.869 408.869z" />
<glyph unicode="&#xe905;" glyph-name="plus" data-tags="plus" d="M597.333 533.333v426.667h-170.667v-426.667h-426.667v-170.667h426.667v-426.667h170.667v426.667h426.667v170.667z" />
<glyph unicode="&#xe906;" glyph-name="filters" data-tags="filters" d="M217.543 834.589v98.249c0 14.999-12.163 27.162-27.162 27.162h-8.785c-14.999 0-27.162-12.163-27.162-27.162v-98.249c-63.792-14.19-110.78-70.3-110.78-137.38s46.988-123.189 109.844-137.208l0.936-592.841c0-14.999 12.163-27.162 27.162-27.162h7.99c14.999 0 27.162 12.163 27.162 27.162v588.669c69.551 9.191 122.666 68.109 122.666 139.435 0 71.041-52.699 129.772-121.13 139.246zM549.82 417.644v515.184c0 14.999-12.163 27.162-27.162 27.162h-4.796c-14.999 0-27.162-12.163-27.162-27.162v-513.593c-71.358-12.114-125.020-73.469-125.020-147.364s53.662-135.26 124.145-147.242l0.884-159.869c0-14.999 12.163-27.162 27.162-27.162h4.796c14.999 0 27.162 12.163 27.162 27.162v159.745c67.325 15.43 116.8 74.826 116.8 145.772s-49.464 130.342-115.794 145.579zM980.345 594.96c-0.075 69.212-51.022 126.499-117.453 136.489l-0.764 201.379c0 14.999-12.163 27.162-27.162 27.162h-6.387c-14.999 0-27.162-12.163-27.162-27.162v-205.273c-58.17-16.849-99.977-69.642-99.977-132.191s41.807-115.342 99-131.95l0.967-500.252c0-14.999 12.163-27.162 27.162-27.162h4.796c14.999 0 27.162 12.163 27.162 27.162v496.022c67.608 9.329 119.206 66.436 119.809 135.722z" />
<glyph unicode="&#xe907;" glyph-name="arrow-line" data-tags="arrow-line" d="M995.878 700.739l-43.703 43.703c-17.591 16.506-41.326 26.645-67.432 26.645s-49.837-10.139-67.483-26.693l-303.387-303.389-305.935 304.692c-17.468 16.781-41.244 27.116-67.432 27.116s-49.958-10.335-67.464-27.148l-44.92-44.92c-17.371-17.206-28.122-41.062-28.122-67.432s10.752-50.226 28.112-67.421l414.583-414.583c17.206-17.371 41.062-28.122 67.432-28.122s50.226 10.752 67.421 28.112l418.329 414.583c17.371 17.206 28.122 41.062 28.122 67.432s-10.752 50.226-28.112 67.421z" />
<glyph unicode="&#xe908;" glyph-name="check-empty" data-tags="check-empty" d="M910.2 846.2v-796.4h-796.4v796.4h796.4zM910.2 960h-796.4c-62.6 0-113.8-51.2-113.8-113.8v-796.4c0-62.6 51.2-113.8 113.8-113.8h796.4c62.6 0 113.8 51.2 113.8 113.8v796.4c0 62.6-51.2 113.8-113.8 113.8z" />
<glyph unicode="&#xe909;" glyph-name="check1" data-tags="check" d="M910.2 960h-796.4c-62.6 0-113.8-51.2-113.8-113.8v-796.4c0-62.6 51.2-113.8 113.8-113.8h796.4c62.6 0 113.8 51.2 113.8 113.8v796.4c0 62.6-51.2 113.8-113.8 113.8zM398.2 163.6l-284.4 284.4 79.6 79.6 204.8-204.8 432.4 432.4 79.6-79.6-512-512z" />
<glyph unicode="&#xe90a;" glyph-name="details-arrow" data-tags="details-arrow" d="M512 960.001l-90.24-90.24 357.12-357.76h-778.879v-127.999h778.879l-357.12-357.76 90.24-90.24 511.999 511.999z" />
<glyph unicode="&#xe90b;" glyph-name="Spinner" data-tags="Spinner" d="M1023.953 448.071c1.137 83.016-18.195 164.895-56.861 238.814-75.625 145.563-216.069 245.637-378.121 270.087v-135.328c85.291-16.489 162.621-63.115 217.207-130.779 89.839-108.035 112.015-257.578 56.861-387.219-38.097-91.545-110.309-163.758-201.855-201.855-93.82-40.37-200.149-40.37-293.969 0-91.545 38.097-163.758 110.309-201.855 201.855-55.155 129.642-32.979 279.184 56.861 387.219 54.586 67.663 131.917 114.289 217.207 130.779v135.328c-163.758-22.745-305.91-123.388-382.102-270.087-69.938-135.328-76.193-294.537-17.058-434.982 51.174-123.388 149.542-221.756 272.93-272.361 127.367-54.017 270.655-54.017 398.023 0 122.819 51.174 220.619 148.975 271.793 271.793 26.724 61.978 40.37 129.073 40.94 196.738v0z" />
</font></defs></svg>

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
fonts/h5p-hub-publish.ttf Normal file

Binary file not shown.

BIN
fonts/h5p-hub-publish.woff Normal file

Binary file not shown.

Binary file not shown.

View File

@ -1,42 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>
<json>
{
"fontFamily": "h5p-core-fonts",
"majorVersion": 1,
"minorVersion": 0,
"fontURL": "http://h5p.org",
"license": "MIT license",
"licenseURL": "http://opensource.org/licenses/MIT",
"designer": "Magnus Vik Magnussen",
"designerURL": "",
"version": "Version 1.0",
"fontId": "h5p-core-fonts",
"psName": "h5p-core-fonts",
"subFamily": "Regular",
"fullName": "h5p-core-fonts",
"description": "Generated by IcoMoon"
}
</json>
</metadata>
<defs>
<font id="h5p-core-fonts" horiz-adv-x="1024">
<font-face units-per-em="1024" ascent="960" descent="-64" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" d="" horiz-adv-x="512" />
<glyph unicode="&#xe888;" d="M660.48 703.59c-140.288 0-253.952-113.664-253.952-253.952 0-122.47 86.63-224.666 202.138-248.627v206.234h-86.835c-11.264 0-14.541 7.168-7.373 16.179l133.12 164.659c7.168 9.011 18.842 9.011 26.010 0l133.12-164.659c7.373-8.602 3.686-16.179-7.373-16.179h-86.835v-206.234c115.507 23.962 202.138 126.157 202.138 248.627-0.205 140.288-113.869 253.952-254.157 253.952z" horiz-adv-x="1321" />
<glyph unicode="&#xe889;" d="M662.118 701.952c-140.288 0-253.952-113.664-253.952-253.952s113.664-253.952 253.952-253.952 253.952 113.664 253.952 253.952-113.664 253.952-253.952 253.952zM621.773 652.8h83.763v-65.946h-83.763v65.946zM748.749 273.92h-173.67v50.995h49.562v159.13h-49.562v50.995h133.53v-210.125h40.346v-50.995z" horiz-adv-x="1321" />
<glyph unicode="&#xe88a;" d="M925.491 236.646l-114.688 114.688c27.238 37.888 43.213 84.378 43.213 134.554 0 127.59-103.834 231.424-231.424 231.424s-231.424-103.834-231.424-231.424c0-127.59 103.834-231.424 231.424-231.424 50.176 0 96.666 15.974 134.554 43.213l114.688-114.688c5.325-5.325 13.926-5.325 19.251 0l34.406 34.406c5.325 5.12 5.325 13.926 0 19.251zM622.797 318.566c-92.365 0-167.117 74.752-167.117 167.117s74.752 167.117 167.117 167.117c92.365 0 167.117-74.752 167.117-167.117s-74.752-167.117-167.117-167.117z" horiz-adv-x="1321" />
<glyph unicode="&#xe88b;" d="M324.468 566.591c-4.186-4.186-2.79-8.372 3.255-8.835l111.615-11.86c6.046-0.697 10.464 3.721 9.766 9.766l-11.86 111.615c-0.697 6.046-4.65 7.441-8.835 3.255l-103.942-103.942zM399.112 634.259l-64.644 64.876c-4.186 4.186-11.161 4.186-15.581 0l-23.254-23.254c-4.186-4.186-4.186-11.161 0-15.581l64.876-64.876zM896.497 670.533c-4.186 4.186-8.372 2.79-8.835-3.255l-11.86-111.615c-0.697-6.046 3.721-10.464 9.766-9.766l111.615 11.86c6.046 0.697 7.441 4.65 3.255 8.835l-103.942 103.942zM964.165 595.657l64.876 64.876c4.186 4.186 4.186 11.161 0 15.581l-23.254 23.254c-4.186 4.186-11.161 4.186-15.581 0l-64.876-64.876zM1000.44 320.34c4.186 4.186 2.79 8.372-3.255 8.835l-111.615 11.86c-6.046 0.697-10.464-3.721-9.766-9.766l11.86-111.615c0.697-6.046 4.65-7.441 8.835-3.255l103.942 103.942zM925.564 252.441l64.876-64.876c4.186-4.186 11.161-4.186 15.581 0l23.254 23.254c4.186 4.186 4.186 11.161 0 15.581l-64.876 64.876zM428.41 216.398c4.186-4.186 8.372-2.79 8.835 3.255l11.86 111.615c0.697 6.046-3.721 10.464-9.766 9.766l-111.615-11.86c-6.046-0.697-7.441-4.65-3.255-8.835l103.942-103.942zM360.51 291.273l-64.876-64.876c-4.186-4.186-4.186-11.161 0-15.581l23.254-23.254c4.186-4.186 11.161-4.186 15.581 0l64.876 64.876zM477.939 572.404v-248.809h365.076v248.809h-365.076zM797.905 368.707h-274.854v158.355h274.621v-158.355z" horiz-adv-x="1321" />
<glyph unicode="&#xe88c;" d="M495.845 602.867c4.186 4.186 2.79 8.372-3.255 8.835l-111.615 11.86c-6.046 0.697-10.464-3.721-9.766-9.766l11.86-111.615c0.697-6.046 4.65-7.441 8.835-3.255l103.942 103.942zM421.202 534.968l64.876-64.876c4.186-4.186 11.161-4.186 15.581 0l23.254 23.254c4.186 4.186 4.186 11.161 0 15.581l-64.876 64.876zM932.774 498.924c4.186-4.186 8.372-2.79 8.835 3.255l11.86 111.615c0.697 6.046-3.721 10.464-9.766 9.766l-111.615-11.86c-6.046-0.697-7.441-4.65-3.255-8.835l103.942-103.942zM864.873 573.799l-64.876-64.876c-4.186-4.186-4.186-11.161 0-15.581l23.254-23.254c4.186-4.186 11.161-4.186 15.581 0l64.876 64.876zM828.83 284.064c-4.186-4.186-2.79-8.372 3.255-8.835l111.615-11.86c6.046-0.697 10.464 3.721 9.766 9.766l-11.86 111.615c-0.697 6.046-4.65 7.441-8.835 3.255l-103.942-103.942zM903.707 351.733l-64.876 64.876c-4.186 4.186-11.161 4.186-15.581 0l-23.254-23.254c-4.186-4.186-4.186-11.161 0-15.581l64.876-64.876zM391.903 388.008c-4.186 4.186-8.372 2.79-8.835-3.255l-11.86-111.615c-0.697-6.046 3.721-10.464 9.766-9.766l111.615 11.86c6.046 0.697 7.441 4.65 3.255 8.835l-103.942 103.942zM459.802 313.131l64.876 64.876c4.186 4.186 4.186 11.161 0 15.581l-23.254 23.254c-4.186 4.186-11.161 4.186-15.581 0l-64.876-64.876zM284.938 707.273v-518.547h751.079v518.547h-751.079zM990.906 233.837h-660.857v428.325h660.623v-428.325z" horiz-adv-x="1321" />
<glyph unicode="&#xe88d;" d="M776.047 615.89c9.535 0 12.323 6.046 6.278 13.486l-110.918 137.194c-6.046 7.441-15.581 7.441-21.625 0l-110.918-137.194c-6.046-7.441-3.023-13.486 6.278-13.486h230.904zM617.459 623.562v-167.19c0-9.535 7.673-17.208 17.208-17.208h51.623c9.535 0 17.208 7.673 17.208 17.208v167.19zM544.909 280.11c-9.535 0-12.323-6.046-6.278-13.486l110.918-137.194c6.046-7.441 15.581-7.441 21.625 0l110.918 137.194c6.046 7.441 3.023 13.486-6.278 13.486h-230.904zM703.497 272.438v167.19c0 9.535-7.673 17.208-17.208 17.208h-51.623c-9.535 0-17.208-7.673-17.208-17.208v-167.19z" horiz-adv-x="1321" />
<glyph unicode="&#xe88e;" d="M1062.773 608.822c-21.364 20.404-53.527 31.205-96.254 31.205h-148.821v-76.81h-168.504l-14.162-60.968c11.762 5.521 28.565 9.602 40.087 12.483 11.521 2.88 23.044 1.681 34.325 1.681 38.405 0 69.369-12.001 93.131-35.285 23.763-23.044 35.765-52.567 35.765-87.611 0-24.722-6.241-48.488-18.484-71.529-12.243-22.804-29.764-41.766-52.327-53.768-8.161-4.321-17.043-2.4-26.644-12.001h141.62v144.021h70.811c47.767 0 83.292 9.843 106.335 31.684 23.285 21.844 34.806 51.848 34.806 90.494 0.241 37.205-10.321 66.009-31.684 86.411zM965.8 488.087c-9.12-7.921-25.204-11.284-48.006-11.284h-35.285v86.411h39.846c22.084 0 37.205-5.281 45.125-13.683 7.921-8.401 12.001-18.722 12.001-30.724 0-12.483-4.562-22.804-13.683-30.724zM671.518 446.559c-20.642 0-38.646-12.001-47.287-29.285l-103.694 15.122 46.807 207.629h-100.095v-163.222h-122.417v163.222h-120.017v-384.053h120.017v144.021h122.417v-144.021h148.579c-17.522 9.602-32.643 13.202-45.125 22.563-12.721 9.602-22.804 20.883-30.724 32.885s-13.921 25.685-19.203 43.686l103.694 15.122c8.642-17.283 26.403-29.044 47.047-29.044 29.044 0 52.567 23.522 52.567 52.567s-23.522 52.807-52.567 52.807z" horiz-adv-x="1321" />
<glyph unicode="&#xe88f;" d="M1030.554 429.363c1.638-3.277 0-3.277-1.638-6.349-20.89-22.323-46.49-35.226-76.8-41.574-12.902-1.638-25.6-3.277-36.864-3.277-12.493 0-18.637 0-27.238 1.638-1.638 0.205-3.277 1.638-4.71 3.277-67.174 60.826-135.987 121.651-203.162 182.477-1.638 1.638-4.71 1.638-6.349 1.638-23.962-6.349-47.923-12.902-73.523-19.251-25.6-4.71-51.2-1.638-75.162 12.902-12.902 7.987-22.323 19.251-28.877 33.587-4.71 9.626 1.638 22.323 12.902 25.6 43.213 12.902 86.426 28.877 128 44.851 12.902 4.71 27.238 7.987 41.574 6.349 4.71 0 9.626-3.277 14.336-4.71 41.574-15.974 83.149-30.31 124.723-46.49 1.638-1.638 4.71-1.638 7.987 0 30.31 7.987 62.464 17.613 92.774 25.6 3.277 1.638 4.71 0 6.349-1.638zM420.864 437.35c19.251 9.626 36.864 6.349 51.2-9.626 12.902-12.902 12.902-28.877 3.277-49.562 19.251 3.277 33.587-3.277 43.213-19.251 11.264-17.613 7.987-33.587-6.349-49.562 4.71 0 11.264 0 15.974-1.638 14.336-3.277 25.6-12.902 30.31-27.238s1.638-27.238-7.987-36.864c-4.71-6.349-11.264-11.264-15.974-17.613s-11.264-11.264-15.974-17.613c-14.336-14.336-38.502-15.974-52.838-1.638-30.31 30.31-55.91 64.102-83.149 97.69-17.613 22.323-33.587 43.213-49.562 65.536-7.987 9.626-12.902 19.251-14.336 31.949 0 7.987 1.638 15.974 7.987 22.323 9.626 9.626 17.613 19.251 27.238 28.877 17.613 17.613 47.923 12.698 62.464-7.987 1.434-1.434 3.072-4.506 4.506-7.782zM571.392 224.563l27.238-28.877c17.613-15.974 46.49-12.902 57.549 7.987l-3.277 3.277c-22.323 22.323-46.49 46.49-68.813 68.813-3.277 3.277-4.71 7.987-3.277 12.902 1.638 4.71 4.71 7.987 9.626 9.626 4.71 1.638 9.626 0 12.902-4.71 14.336-14.336 30.31-30.31 44.851-44.851 14.336-14.336 30.31-28.877 44.851-44.851 7.987-9.626 19.251-11.264 30.31-9.626 14.336 3.277 23.962 11.264 30.31 25.6 1.638 3.277 0 4.71-1.638 6.349-43.213 43.213-86.426 84.787-128 128-3.277 3.277-6.349 7.987-4.71 14.336 1.638 9.626 12.902 14.336 22.323 7.987 1.638-1.638 3.277-1.638 3.277-3.277 43.213-43.213 88.064-88.064 131.277-131.277 3.277-3.277 4.71-3.277 7.987-3.277 17.613 1.638 33.587 15.974 36.864 33.587 0 3.277 0 4.71-1.638 6.349-49.562 49.562-99.123 99.123-148.89 148.89-3.277 3.277-4.71 6.349-4.71 11.264 0 4.71 3.277 11.264 7.987 12.698 4.71 1.638 9.626 1.638 14.336-3.277 3.277-3.277 7.987-7.987 11.264-11.264 35.226-35.226 70.451-70.451 105.677-105.677 11.264-11.264 22.323-20.89 31.949-31.949 1.638-1.638 4.71-3.277 6.349-1.638 23.962 4.71 38.502 30.31 28.877 54.477l38.298-1.638c0-0.205 0-0.41 0.205-0.614 1.434-7.987 1.434-17.203-0.205-24.986-6.349-30.31-23.962-49.562-52.838-59.187-1.638 0-3.277-1.638-3.277-3.277-9.626-31.949-33.587-52.838-67.174-55.91-3.277 0-3.277-1.638-4.71-3.277-17.613-33.587-57.549-49.562-91.136-36.864-4.71 1.638-9.626 4.71-14.336 6.349-6.349-6.349-14.336-12.698-22.323-15.974-27.238-12.698-57.549-6.349-78.438 14.336-9.626 9.626-19.251 19.251-30.31 28.877 7.987 7.987 14.336 15.974 23.962 25.6l1.434-1.024zM404.89 744.55c31.949-9.626 62.464-20.89 94.413-30.31 33.587-11.264 65.536-20.89 99.123-31.949 1.638 0 1.638 0 3.277-1.638-17.613-6.349-33.587-11.264-49.562-17.613-1.638 0-3.277 0-4.71 0-44.851 14.336-91.136 28.877-135.987 43.213-3.277 1.638-4.71 0-7.987-1.638l-80.077-185.549c0-9.626 4.71-17.613 11.264-25.6 3.277-4.71 6.349-7.987 7.987-9.626-7.987-7.987-14.336-15.974-22.323-25.6-15.974 19.251-28.877 38.502-30.31 64.102l89.498 212.787c-0.41-0.205 12.902 13.312 25.395 9.421z" horiz-adv-x="1321" />
<glyph unicode="&#xe890;" d="M660.48 701.952c-140.288 0-253.952-113.664-253.952-253.952s113.664-253.952 253.952-253.952 253.952 113.664 253.952 253.952-113.664 253.952-253.952 253.952zM796.058 371.2c6.963-6.963 6.963-18.022 0-24.986l-33.997-33.997c-6.963-6.963-18.022-6.963-24.986 0l-76.8 76.8-76.595-76.595c-6.963-6.963-18.022-6.963-24.986 0l-33.997 33.997c-6.963 6.963-6.963 18.022 0 24.986l76.8 76.8-76.8 76.8c-6.963 6.963-6.963 18.022 0 24.986l33.997 33.997c6.963 6.963 18.022 6.963 24.986 0l76.8-76.8 76.8 76.8c6.963 6.963 18.022 6.963 24.986 0l33.997-33.997c6.963-6.963 6.963-18.022 0-24.986l-77.005-77.005 76.8-76.8z" horiz-adv-x="1321" />
<glyph unicode="&#xe891;" d="M324.468 566.591c-4.186-4.186-2.79-8.372 3.255-8.835l111.615-11.86c6.046-0.697 10.464 3.721 9.766 9.766l-11.86 111.615c-0.697 6.046-4.65 7.441-8.835 3.255l-103.942-103.942zM399.112 634.259l-64.644 64.876c-4.186 4.186-11.161 4.186-15.581 0l-23.254-23.254c-4.186-4.186-4.186-11.161 0-15.581l64.876-64.876zM896.497 670.533c-4.186 4.186-8.372 2.79-8.835-3.255l-11.86-111.615c-0.697-6.046 3.721-10.464 9.766-9.766l111.615 11.86c6.046 0.697 7.441 4.65 3.255 8.835l-103.942 103.942zM964.165 595.657l64.876 64.876c4.186 4.186 4.186 11.161 0 15.581l-23.254 23.254c-4.186 4.186-11.161 4.186-15.581 0l-64.876-64.876zM1000.44 320.34c4.186 4.186 2.79 8.372-3.255 8.835l-111.615 11.86c-6.046 0.697-10.464-3.721-9.766-9.766l11.86-111.615c0.697-6.046 4.65-7.441 8.835-3.255l103.942 103.942zM925.564 252.441l64.876-64.876c4.186-4.186 11.161-4.186 15.581 0l23.254 23.254c4.186 4.186 4.186 11.161 0 15.581l-64.876 64.876zM428.41 216.398c4.186-4.186 8.372-2.79 8.835 3.255l11.86 111.615c0.697 6.046-3.721 10.464-9.766 9.766l-111.615-11.86c-6.046-0.697-7.441-4.65-3.255-8.835l103.942-103.942zM360.51 291.273l-64.876-64.876c-4.186-4.186-4.186-11.161 0-15.581l23.254-23.254c4.186-4.186 11.161-4.186 15.581 0l64.876 64.876zM477.939 572.404v-248.809h365.076v248.809h-365.076zM797.905 368.707h-274.854v158.355h274.621v-158.355z" horiz-adv-x="1321" />
<glyph unicode="&#xe892;" d="M599.553 337.314c4.419-3.023 8.138-9.998 8.138-15.581v-58.599c0-5.348-3.721-7.441-8.138-4.419l-220.906 148.123c-4.419 3.023-8.138 9.998-8.138 15.348v50.228c0 5.348 3.721 12.323 8.138 15.581l220.906 149.517c4.419 3.023 8.138 1.162 8.138-4.419v-58.599c0-5.348-3.721-12.556-8.138-15.581l-152.773-106.731c-4.419-3.023-4.419-8.138 0-11.161l152.773-103.71zM874.175 440.559c4.419 3.023 4.65 8.138 0 11.161l-152.773 106.731c-4.419 3.023-8.138 10.232-8.138 15.581v58.599c0 5.348 3.721 7.441 8.138 4.419l220.906-149.517c4.419-3.023 8.138-9.998 8.138-15.581v-50.228c0-5.348-3.721-12.323-8.138-15.348l-220.906-148.123c-4.419-3.023-8.138-1.162-8.138 4.419v58.599c0 5.348 3.721 12.323 8.138 15.581l152.773 103.71z" horiz-adv-x="1321" />
<glyph unicode="&#xe893;" d="M502.17 522.957c-12.902 0-16.998-8.192-8.806-18.227l152.166-188.006c8.192-10.035 21.504-10.035 29.696 0l152.166 188.006c8.192 10.035 4.301 18.227-8.806 18.227h-316.416zM719.462 512.512v139.878c0 12.902-10.65 23.552-23.552 23.552h-70.656c-12.902 0-23.552-10.65-23.552-23.552v-139.878zM798.106 375.91c-8.602 0-20.070-5.53-25.6-12.288l-75.162-92.979c-5.325-6.758-15.36-16.589-22.118-21.914 0 0-4.506-3.686-14.746-3.686s-14.746 3.686-14.746 3.686c-6.758 5.325-16.589 15.36-22.118 21.914l-75.162 92.979c-5.325 6.758-16.998 12.288-25.6 12.288h-130.253c-8.602 0-15.77-6.963-15.77-15.77v-141.722c0-8.602 6.963-15.77 15.77-15.77h535.962c8.602 0 15.77 6.963 15.77 15.77v141.722c0 8.602-6.963 15.77-15.77 15.77h-130.458zM448.102 261.018c-15.565 0-28.262 12.698-28.262 28.262 0 15.565 12.698 28.262 28.262 28.262s28.262-12.698 28.262-28.262c-0.205-15.565-12.698-28.262-28.262-28.262z" horiz-adv-x="1321" />
<glyph unicode="&#xe894;" d="M742.605 448l107.11 107.11c9.626 9.626 9.626 25.19 0 34.816l-47.309 47.309c-9.626 9.626-25.19 9.626-34.816 0l-107.11-107.11-107.11 107.11c-9.626 9.626-25.19 9.626-34.816 0l-47.309-47.309c-9.626-9.626-9.626-25.19 0-34.816l107.11-107.11-107.11-107.11c-9.626-9.626-9.626-25.19 0-34.816l47.309-47.309c9.626-9.626 25.19-9.626 34.816 0l107.11 107.11 107.11-107.11c9.626-9.626 25.19-9.626 34.816 0l47.309 47.309c9.626 9.626 9.626 25.19 0 34.816l-107.11 107.11z" horiz-adv-x="1321" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

View File

@ -0,0 +1,586 @@
<?php
/**
* File info?
*/
/**
* The default file storage class for H5P. Will carry out the requested file
* operations using PHP's standard file operation functions.
*
* Some implementations of H5P that doesn't use the standard file system will
* want to create their own implementation of the \H5P\FileStorage interface.
*
* @package H5P
* @copyright 2016 Joubel AS
* @license MIT
*/
class H5PDefaultStorage implements \H5PFileStorage {
private $path, $alteditorpath;
/**
* The great Constructor!
*
* @param string $path
* The base location of H5P files
* @param string $alteditorpath
* Optional. Use a different editor path
*/
function __construct($path, $alteditorpath = NULL) {
// Set H5P storage path
$this->path = $path;
$this->alteditorpath = $alteditorpath;
}
/**
* Store the library folder.
*
* @param array $library
* Library properties
*/
public function saveLibrary($library) {
$dest = $this->path . '/libraries/' . \H5PCore::libraryToString($library, TRUE);
// Make sure destination dir doesn't exist
\H5PCore::deleteFileTree($dest);
// Move library folder
self::copyFileTree($library['uploadDirectory'], $dest);
}
/**
* Store the content folder.
*
* @param string $source
* Path on file system to content directory.
* @param array $content
* Content properties
*/
public function saveContent($source, $content) {
$dest = "{$this->path}/content/{$content['id']}";
// Remove any old content
\H5PCore::deleteFileTree($dest);
self::copyFileTree($source, $dest);
}
/**
* Remove content folder.
*
* @param array $content
* Content properties
*/
public function deleteContent($content) {
\H5PCore::deleteFileTree("{$this->path}/content/{$content['id']}");
}
/**
* Creates a stored copy of the content folder.
*
* @param string $id
* Identifier of content to clone.
* @param int $newId
* The cloned content's identifier
*/
public function cloneContent($id, $newId) {
$path = $this->path . '/content/';
if (file_exists($path . $id)) {
self::copyFileTree($path . $id, $path . $newId);
}
}
/**
* Get path to a new unique tmp folder.
*
* @return string
* Path
*/
public function getTmpPath() {
$temp = "{$this->path}/temp";
self::dirReady($temp);
return "{$temp}/" . uniqid('h5p-');
}
/**
* Fetch content folder and save in target directory.
*
* @param int $id
* Content identifier
* @param string $target
* Where the content folder will be saved
*/
public function exportContent($id, $target) {
$source = "{$this->path}/content/{$id}";
if (file_exists($source)) {
// Copy content folder if it exists
self::copyFileTree($source, $target);
}
else {
// No contnet folder, create emty dir for content.json
self::dirReady($target);
}
}
/**
* Fetch library folder and save in target directory.
*
* @param array $library
* Library properties
* @param string $target
* Where the library folder will be saved
* @param string $developmentPath
* Folder that library resides in
*/
public function exportLibrary($library, $target, $developmentPath=NULL) {
$folder = \H5PCore::libraryToString($library, TRUE);
$srcPath = ($developmentPath === NULL ? "/libraries/{$folder}" : $developmentPath);
self::copyFileTree("{$this->path}{$srcPath}", "{$target}/{$folder}");
}
/**
* Save export in file system
*
* @param string $source
* Path on file system to temporary export file.
* @param string $filename
* Name of export file.
* @throws Exception Unable to save the file
*/
public function saveExport($source, $filename) {
$this->deleteExport($filename);
if (!self::dirReady("{$this->path}/exports")) {
throw new Exception("Unable to create directory for H5P export file.");
}
if (!copy($source, "{$this->path}/exports/{$filename}")) {
throw new Exception("Unable to save H5P export file.");
}
}
/**
* Removes given export file
*
* @param string $filename
*/
public function deleteExport($filename) {
$target = "{$this->path}/exports/{$filename}";
if (file_exists($target)) {
unlink($target);
}
}
/**
* Check if the given export file exists
*
* @param string $filename
* @return boolean
*/
public function hasExport($filename) {
$target = "{$this->path}/exports/{$filename}";
return file_exists($target);
}
/**
* Will concatenate all JavaScrips and Stylesheets into two files in order
* to improve page performance.
*
* @param array $files
* A set of all the assets required for content to display
* @param string $key
* Hashed key for cached asset
*/
public function cacheAssets(&$files, $key) {
foreach ($files as $type => $assets) {
if (empty($assets)) {
continue; // Skip no assets
}
$content = '';
foreach ($assets as $asset) {
// Get content from asset file
$assetContent = file_get_contents($this->path . $asset->path);
$cssRelPath = preg_replace('/[^\/]+$/', '', $asset->path);
// Get file content and concatenate
if ($type === 'scripts') {
$content .= $assetContent . ";\n";
}
else {
// Rewrite relative URLs used inside stylesheets
$content .= preg_replace_callback(
'/url\([\'"]?([^"\')]+)[\'"]?\)/i',
function ($matches) use ($cssRelPath) {
if (preg_match("/^(data:|([a-z0-9]+:)?\/)/i", $matches[1]) === 1) {
return $matches[0]; // Not relative, skip
}
return 'url("../' . $cssRelPath . $matches[1] . '")';
},
$assetContent) . "\n";
}
}
self::dirReady("{$this->path}/cachedassets");
$ext = ($type === 'scripts' ? 'js' : 'css');
$outputfile = "/cachedassets/{$key}.{$ext}";
file_put_contents($this->path . $outputfile, $content);
$files[$type] = array((object) array(
'path' => $outputfile,
'version' => ''
));
}
}
/**
* Will check if there are cache assets available for content.
*
* @param string $key
* Hashed key for cached asset
* @return array
*/
public function getCachedAssets($key) {
$files = array();
$js = "/cachedassets/{$key}.js";
if (file_exists($this->path . $js)) {
$files['scripts'] = array((object) array(
'path' => $js,
'version' => ''
));
}
$css = "/cachedassets/{$key}.css";
if (file_exists($this->path . $css)) {
$files['styles'] = array((object) array(
'path' => $css,
'version' => ''
));
}
return empty($files) ? NULL : $files;
}
/**
* Remove the aggregated cache files.
*
* @param array $keys
* The hash keys of removed files
*/
public function deleteCachedAssets($keys) {
foreach ($keys as $hash) {
foreach (array('js', 'css') as $ext) {
$path = "{$this->path}/cachedassets/{$hash}.{$ext}";
if (file_exists($path)) {
unlink($path);
}
}
}
}
/**
* Read file content of given file and then return it.
*
* @param string $file_path
* @return string
*/
public function getContent($file_path) {
return file_get_contents($file_path);
}
/**
* Save files uploaded through the editor.
* The files must be marked as temporary until the content form is saved.
*
* @param \H5peditorFile $file
* @param int $contentid
*/
public function saveFile($file, $contentId) {
// Prepare directory
if (empty($contentId)) {
// Should be in editor tmp folder
$path = $this->getEditorPath();
}
else {
// Should be in content folder
$path = $this->path . '/content/' . $contentId;
}
$path .= '/' . $file->getType() . 's';
self::dirReady($path);
// Add filename to path
$path .= '/' . $file->getName();
copy($_FILES['file']['tmp_name'], $path);
return $file;
}
/**
* Copy a file from another content or editor tmp dir.
* Used when copy pasting content in H5P Editor.
*
* @param string $file path + name
* @param string|int $fromid Content ID or 'editor' string
* @param int $toid Target Content ID
*/
public function cloneContentFile($file, $fromId, $toId) {
// Determine source path
if ($fromId === 'editor') {
$sourcepath = $this->getEditorPath();
}
else {
$sourcepath = "{$this->path}/content/{$fromId}";
}
$sourcepath .= '/' . $file;
// Determine target path
$filename = basename($file);
$filedir = str_replace($filename, '', $file);
$targetpath = "{$this->path}/content/{$toId}/{$filedir}";
// Make sure it's ready
self::dirReady($targetpath);
$targetpath .= $filename;
// Check to see if source exist and if target doesn't
if (!file_exists($sourcepath) || file_exists($targetpath)) {
return; // Nothing to copy from or target already exists
}
copy($sourcepath, $targetpath);
}
/**
* Copy a content from one directory to another. Defaults to cloning
* content from the current temporary upload folder to the editor path.
*
* @param string $source path to source directory
* @param string $contentId Id of contentarray
*/
public function moveContentDirectory($source, $contentId = NULL) {
if ($source === NULL) {
return NULL;
}
// TODO: Remove $contentId and never copy temporary files into content folder. JI-366
if ($contentId === NULL || $contentId == 0) {
$target = $this->getEditorPath();
}
else {
// Use content folder
$target = "{$this->path}/content/{$contentId}";
}
$contentSource = $source . '/' . 'content';
$contentFiles = array_diff(scandir($contentSource), array('.','..', 'content.json'));
foreach ($contentFiles as $file) {
if (is_dir("{$contentSource}/{$file}")) {
self::copyFileTree("{$contentSource}/{$file}", "{$target}/{$file}");
}
else {
copy("{$contentSource}/{$file}", "{$target}/{$file}");
}
}
// TODO: Return list of all files so that they can be marked as temporary. JI-366
}
/**
* Checks to see if content has the given file.
* Used when saving content.
*
* @param string $file path + name
* @param int $contentId
* @return string File ID or NULL if not found
*/
public function getContentFile($file, $contentId) {
$path = "{$this->path}/content/{$contentId}/{$file}";
return file_exists($path) ? $path : NULL;
}
/**
* Checks to see if content has the given file.
* Used when saving content.
*
* @param string $file path + name
* @param int $contentid
* @return string|int File ID or NULL if not found
*/
public function removeContentFile($file, $contentId) {
$path = "{$this->path}/content/{$contentId}/{$file}";
if (file_exists($path)) {
unlink($path);
// Clean up any empty parent directories to avoid cluttering the file system
$parts = explode('/', $path);
while (array_pop($parts) !== NULL) {
$dir = implode('/', $parts);
if (is_dir($dir) && count(scandir($dir)) === 2) { // empty contains '.' and '..'
rmdir($dir); // Remove empty parent
}
else {
return; // Not empty
}
}
}
}
/**
* Check if server setup has write permission to
* the required folders
*
* @return bool True if site can write to the H5P files folder
*/
public function hasWriteAccess() {
return self::dirReady($this->path);
}
/**
* Check if the file presave.js exists in the root of the library
*
* @param string $libraryFolder
* @param string $developmentPath
* @return bool
*/
public function hasPresave($libraryFolder, $developmentPath = null) {
$path = is_null($developmentPath) ? 'libraries' . '/' . $libraryFolder : $developmentPath;
$filePath = realpath($this->path . '/' . $path . '/' . 'presave.js');
return file_exists($filePath);
}
/**
* Check if upgrades script exist for library.
*
* @param string $machineName
* @param int $majorVersion
* @param int $minorVersion
* @return string Relative path
*/
public function getUpgradeScript($machineName, $majorVersion, $minorVersion) {
$upgrades = "/libraries/{$machineName}-{$majorVersion}.{$minorVersion}/upgrades.js";
if (file_exists($this->path . $upgrades)) {
return $upgrades;
}
else {
return NULL;
}
}
/**
* Store the given stream into the given file.
*
* @param string $path
* @param string $file
* @param resource $stream
* @return bool
*/
public function saveFileFromZip($path, $file, $stream) {
$filePath = $path . '/' . $file;
// Make sure the directory exists first
$matches = array();
preg_match('/(.+)\/[^\/]*$/', $filePath, $matches);
self::dirReady($matches[1]);
// Store in local storage folder
return file_put_contents($filePath, $stream);
}
/**
* Recursive function for copying directories.
*
* @param string $source
* From path
* @param string $destination
* To path
* @return boolean
* Indicates if the directory existed.
*
* @throws Exception Unable to copy the file
*/
private static function copyFileTree($source, $destination) {
if (!self::dirReady($destination)) {
throw new \Exception('unabletocopy');
}
$ignoredFiles = self::getIgnoredFiles("{$source}/.h5pignore");
$dir = opendir($source);
if ($dir === FALSE) {
trigger_error('Unable to open directory ' . $source, E_USER_WARNING);
throw new \Exception('unabletocopy');
}
while (false !== ($file = readdir($dir))) {
if (($file != '.') && ($file != '..') && $file != '.git' && $file != '.gitignore' && !in_array($file, $ignoredFiles)) {
if (is_dir("{$source}/{$file}")) {
self::copyFileTree("{$source}/{$file}", "{$destination}/{$file}");
}
else {
copy("{$source}/{$file}", "{$destination}/{$file}");
}
}
}
closedir($dir);
}
/**
* Retrieve array of file names from file.
*
* @param string $file
* @return array Array with files that should be ignored
*/
private static function getIgnoredFiles($file) {
if (file_exists($file) === FALSE) {
return array();
}
$contents = file_get_contents($file);
if ($contents === FALSE) {
return array();
}
return preg_split('/\s+/', $contents);
}
/**
* Recursive function that makes sure the specified directory exists and
* is writable.
*
* @param string $path
* @return bool
*/
private static function dirReady($path) {
if (!file_exists($path)) {
$parent = preg_replace("/\/[^\/]+\/?$/", '', $path);
if (!self::dirReady($parent)) {
return FALSE;
}
mkdir($path, 0777, true);
}
if (!is_dir($path)) {
trigger_error('Path is not a directory ' . $path, E_USER_WARNING);
return FALSE;
}
if (!is_writable($path)) {
trigger_error('Unable to write to ' . $path . ' check directory permissions ', E_USER_WARNING);
return FALSE;
}
return TRUE;
}
/**
* Easy helper function for retrieving the editor path
*
* @return string Path to editor files
*/
private function getEditorPath() {
return ($this->alteditorpath !== NULL ? $this->alteditorpath : "{$this->path}/editor");
}
}

View File

@ -9,20 +9,22 @@ class H5PDevelopment {
const MODE_CONTENT = 1;
const MODE_LIBRARY = 2;
private $h5pF, $libraries, $language;
private $h5pF, $libraries, $language, $filesPath;
/**
* Constructor.
*
* @param object $H5PFramework
* @param H5PFrameworkInterface|object $H5PFramework
* The frameworks implementation of the H5PFrameworkInterface
* @param string $filesPath
* Path to where H5P should store its files
* @param $language
* @param array $libraries Optional cache input.
*/
public function __construct($H5PFramework, $filesPath, $language, $libraries = NULL) {
public function __construct(H5PFrameworkInterface $H5PFramework, $filesPath, $language, $libraries = NULL) {
$this->h5pF = $H5PFramework;
$this->language = $language;
$this->filesPath = $filesPath;
if ($libraries !== NULL) {
$this->libraries = $libraries;
}
@ -34,7 +36,7 @@ class H5PDevelopment {
/**
* Get contents of file.
*
* @param string File path.
* @param string $file File path.
* @return mixed String on success or NULL on failure.
*/
private function getFileContents($file) {
@ -65,7 +67,7 @@ class H5PDevelopment {
$contents = scandir($path);
for ($i = 0, $s = count($contents); $i < $s; $i++) {
if ($contents[$i]{0} === '.') {
if ($contents[$i][0] === '.') {
continue; // Skip hidden stuff.
}
@ -76,23 +78,33 @@ class H5PDevelopment {
}
$library = json_decode($libraryJSON, TRUE);
if ($library === FALSE) {
if ($library === NULL) {
continue; // Invalid JSON.
}
// TODO: Validate props? Not really needed, is it? this is a dev site.
// Save/update library.
$library['libraryId'] = $this->h5pF->getLibraryId($library['machineName'], $library['majorVersion'], $library['minorVersion']);
// Convert metadataSettings values to boolean & json_encode it before saving
$library['metadataSettings'] = isset($library['metadataSettings']) ?
H5PMetadata::boolifyAndEncodeSettings($library['metadataSettings']) :
NULL;
// Save/update library.
$this->h5pF->saveLibraryData($library, $library['libraryId'] === FALSE);
$library['path'] = $libraryPath;
// Need to decode it again, since it is served from here.
$library['metadataSettings'] = json_decode($library['metadataSettings']);
$library['path'] = 'development/' . $contents[$i];
$this->libraries[H5PDevelopment::libraryToString($library['machineName'], $library['majorVersion'], $library['minorVersion'])] = $library;
}
// TODO: Should we remove libraries without files? Not really needed, but must be cleaned up some time, right?
// Go trough libraries and insert dependencies. Missing deps. will just be ignored and not available. (I guess?!)
$this->h5pF->lockDependencyStorage();
foreach ($this->libraries as $library) {
$this->h5pF->deleteLibraryDependencies($library['libraryId']);
// This isn't optimal, but without it we would get duplicate warnings.
@ -104,11 +116,12 @@ class H5PDevelopment {
}
}
}
$this->h5pF->unlockDependencyStorage();
// TODO: Deps must be inserted into h5p_nodes_libraries as well... ? But only if they are used?!
}
/**
* @return array Libraris in development folder.
* @return array Libraries in development folder.
*/
public function getLibraries() {
return $this->libraries;
@ -137,12 +150,10 @@ class H5PDevelopment {
*/
public function getSemantics($name, $majorVersion, $minorVersion) {
$library = H5PDevelopment::libraryToString($name, $majorVersion, $minorVersion);
if (isset($this->libraries[$library]) === FALSE) {
return NULL;
}
return $this->getFileContents($this->libraries[$library]['path'] . '/semantics.json');
return $this->getFileContents($this->filesPath . $this->libraries[$library]['path'] . '/semantics.json');
}
/**
@ -151,6 +162,7 @@ class H5PDevelopment {
* @param string $name of the library.
* @param int $majorVersion of the library.
* @param int $minorVersion of the library.
* @param $language
* @return string Translation
*/
public function getLanguage($name, $majorVersion, $minorVersion, $language) {
@ -160,7 +172,7 @@ class H5PDevelopment {
return NULL;
}
return $this->getFileContents($this->libraries[$library]['path'] . '/language/' . $language . '.json');
return $this->getFileContents($this->filesPath . $this->libraries[$library]['path'] . '/language/' . $language . '.json');
}
/**
@ -168,7 +180,7 @@ class H5PDevelopment {
*
* @param string $name Machine readable library name
* @param integer $majorVersion
* @param integer $majorVersion
* @param $minorVersion
* @return string Library identifier.
*/
public static function libraryToString($name, $majorVersion, $minorVersion) {

191
h5p-event-base.class.php Normal file
View File

@ -0,0 +1,191 @@
<?php
/**
* The base class for H5P events. Extend to track H5P events in your system.
*
* @package H5P
* @copyright 2016 Joubel AS
* @license MIT
*/
abstract class H5PEventBase {
// Constants
const LOG_NONE = 0;
const LOG_ALL = 1;
const LOG_ACTIONS = 2;
// Static options
public static $log_level = self::LOG_ACTIONS;
public static $log_time = 2592000; // 30 Days
// Protected variables
protected $id, $type, $sub_type, $content_id, $content_title, $library_name, $library_version, $time;
/**
* Adds event type, h5p library and timestamp to event before saving it.
*
* Common event types with sub type:
* content, <none> content view
* embed viewed through embed code
* shortcode viewed through internal shortcode
* edit opened in editor
* delete deleted
* create created through editor
* create upload created through upload
* update updated through editor
* update upload updated through upload
* upgrade upgraded
*
* results, <none> view own results
* content view results for content
* set new results inserted or updated
*
* settings, <none> settings page loaded
*
* library, <none> loaded in editor
* create new library installed
* update old library updated
*
* @param string $type
* Name of event type
* @param string $sub_type
* Name of event sub type
* @param string $content_id
* Identifier for content affected by the event
* @param string $content_title
* Content title (makes it easier to know which content was deleted etc.)
* @param string $library_name
* Name of the library affected by the event
* @param string $library_version
* Library version
*/
function __construct($type, $sub_type = NULL, $content_id = NULL, $content_title = NULL, $library_name = NULL, $library_version = NULL) {
$this->type = $type;
$this->sub_type = $sub_type;
$this->content_id = $content_id;
$this->content_title = $content_title;
$this->library_name = $library_name;
$this->library_version = $library_version;
$this->time = time();
if (self::validLogLevel($type, $sub_type)) {
$this->save();
}
if (self::validStats($type, $sub_type)) {
$this->saveStats();
}
}
/**
* Determines if the event type should be saved/logged.
*
* @param string $type
* Name of event type
* @param string $sub_type
* Name of event sub type
* @return boolean
*/
private static function validLogLevel($type, $sub_type) {
switch (self::$log_level) {
default:
case self::LOG_NONE:
return FALSE;
case self::LOG_ALL:
return TRUE; // Log everything
case self::LOG_ACTIONS:
if (self::isAction($type, $sub_type)) {
return TRUE; // Log actions
}
return FALSE;
}
}
/**
* Check if the event should be included in the statistics counter.
*
* @param string $type
* Name of event type
* @param string $sub_type
* Name of event sub type
* @return boolean
*/
private static function validStats($type, $sub_type) {
if ( ($type === 'content' && $sub_type === 'shortcode insert') || // Count number of shortcode inserts
($type === 'library' && $sub_type === NULL) || // Count number of times library is loaded in editor
($type === 'results' && $sub_type === 'content') ) { // Count number of times results page has been opened
return TRUE;
}
elseif (self::isAction($type, $sub_type)) { // Count all actions
return TRUE;
}
return FALSE;
}
/**
* Check if event type is an action.
*
* @param string $type
* Name of event type
* @param string $sub_type
* Name of event sub type
* @return boolean
*/
private static function isAction($type, $sub_type) {
if ( ($type === 'content' && in_array($sub_type, array('create', 'create upload', 'update', 'update upload', 'upgrade', 'delete'))) ||
($type === 'library' && in_array($sub_type, array('create', 'update'))) ) {
return TRUE; // Log actions
}
return FALSE;
}
/**
* A helper which makes it easier for systems to save the data.
* Add all relevant properties to a assoc. array.
* There are no NULL values. Empty string or 0 is used instead.
* Used by both Drupal and WordPress.
*
* @return array with keyed values
*/
protected function getDataArray() {
return array(
'created_at' => $this->time,
'type' => $this->type,
'sub_type' => empty($this->sub_type) ? '' : $this->sub_type,
'content_id' => empty($this->content_id) ? 0 : $this->content_id,
'content_title' => empty($this->content_title) ? '' : $this->content_title,
'library_name' => empty($this->library_name) ? '' : $this->library_name,
'library_version' => empty($this->library_version) ? '' : $this->library_version
);
}
/**
* A helper which makes it easier for systems to save the data.
* Used in WordPress.
*
* @return array with strings
*/
protected function getFormatArray() {
return array(
'%d',
'%s',
'%s',
'%d',
'%s',
'%s',
'%s'
);
}
/**
* Stores the event data in the database.
*
* Must be overridden by plugin.
*/
abstract protected function save();
/**
* Add current event data to statistics counter.
*
* Must be overridden by plugin.
*/
abstract protected function saveStats();
}

View File

@ -0,0 +1,222 @@
<?php
/**
* File info?
*/
/**
* Interface needed to handle storage and export of H5P Content.
*/
interface H5PFileStorage {
/**
* Store the library folder.
*
* @param array $library
* Library properties
*/
public function saveLibrary($library);
/**
* Store the content folder.
*
* @param string $source
* Path on file system to content directory.
* @param array $content
* Content properties
*/
public function saveContent($source, $content);
/**
* Remove content folder.
*
* @param array $content
* Content properties
*/
public function deleteContent($content);
/**
* Creates a stored copy of the content folder.
*
* @param string $id
* Identifier of content to clone.
* @param int $newId
* The cloned content's identifier
*/
public function cloneContent($id, $newId);
/**
* Get path to a new unique tmp folder.
*
* @return string
* Path
*/
public function getTmpPath();
/**
* Fetch content folder and save in target directory.
*
* @param int $id
* Content identifier
* @param string $target
* Where the content folder will be saved
*/
public function exportContent($id, $target);
/**
* Fetch library folder and save in target directory.
*
* @param array $library
* Library properties
* @param string $target
* Where the library folder will be saved
*/
public function exportLibrary($library, $target);
/**
* Save export in file system
*
* @param string $source
* Path on file system to temporary export file.
* @param string $filename
* Name of export file.
*/
public function saveExport($source, $filename);
/**
* Removes given export file
*
* @param string $filename
*/
public function deleteExport($filename);
/**
* Check if the given export file exists
*
* @param string $filename
* @return boolean
*/
public function hasExport($filename);
/**
* Will concatenate all JavaScrips and Stylesheets into two files in order
* to improve page performance.
*
* @param array $files
* A set of all the assets required for content to display
* @param string $key
* Hashed key for cached asset
*/
public function cacheAssets(&$files, $key);
/**
* Will check if there are cache assets available for content.
*
* @param string $key
* Hashed key for cached asset
* @return array
*/
public function getCachedAssets($key);
/**
* Remove the aggregated cache files.
*
* @param array $keys
* The hash keys of removed files
*/
public function deleteCachedAssets($keys);
/**
* Read file content of given file and then return it.
*
* @param string $file_path
* @return string contents
*/
public function getContent($file_path);
/**
* Save files uploaded through the editor.
* The files must be marked as temporary until the content form is saved.
*
* @param \H5peditorFile $file
* @param int $contentId
*/
public function saveFile($file, $contentId);
/**
* Copy a file from another content or editor tmp dir.
* Used when copy pasting content in H5P.
*
* @param string $file path + name
* @param string|int $fromId Content ID or 'editor' string
* @param int $toId Target Content ID
*/
public function cloneContentFile($file, $fromId, $toId);
/**
* Copy a content from one directory to another. Defaults to cloning
* content from the current temporary upload folder to the editor path.
*
* @param string $source path to source directory
* @param string $contentId Id of content
*
* @return object Object containing h5p json and content json data
*/
public function moveContentDirectory($source, $contentId = NULL);
/**
* Checks to see if content has the given file.
* Used when saving content.
*
* @param string $file path + name
* @param int $contentId
* @return string|int File ID or NULL if not found
*/
public function getContentFile($file, $contentId);
/**
* Remove content files that are no longer used.
* Used when saving content.
*
* @param string $file path + name
* @param int $contentId
*/
public function removeContentFile($file, $contentId);
/**
* Check if server setup has write permission to
* the required folders
*
* @return bool True if server has the proper write access
*/
public function hasWriteAccess();
/**
* Check if the library has a presave.js in the root folder
*
* @param string $libraryName
* @param string $developmentPath
* @return bool
*/
public function hasPresave($libraryName, $developmentPath = null);
/**
* Check if upgrades script exist for library.
*
* @param string $machineName
* @param int $majorVersion
* @param int $minorVersion
* @return string Relative path
*/
public function getUpgradeScript($machineName, $majorVersion, $minorVersion);
/**
* Store the given stream into the given file.
*
* @param string $path
* @param string $file
* @param resource $stream
* @return bool
*/
public function saveFileFromZip($path, $file, $stream);
}

156
h5p-metadata.class.php Normal file
View File

@ -0,0 +1,156 @@
<?php
/**
* Utility class for handling metadata
*/
abstract class H5PMetadata {
private static $fields = array(
'title' => array(
'type' => 'text',
'maxLength' => 255
),
'a11yTitle' => array(
'type' => 'text',
'maxLength' => 255,
),
'authors' => array(
'type' => 'json'
),
'changes' => array(
'type' => 'json'
),
'source' => array(
'type' => 'text',
'maxLength' => 255
),
'license' => array(
'type' => 'text',
'maxLength' => 32
),
'licenseVersion' => array(
'type' => 'text',
'maxLength' => 10
),
'licenseExtras' => array(
'type' => 'text',
'maxLength' => 5000
),
'authorComments' => array(
'type' => 'text',
'maxLength' => 5000
),
'yearFrom' => array(
'type' => 'int'
),
'yearTo' => array(
'type' => 'int'
),
'defaultLanguage' => array(
'type' => 'text',
'maxLength' => 32,
)
);
/**
* JSON encode metadata
*
* @param object $content
* @return string
*/
public static function toJSON($content) {
// Note: deliberatly creating JSON string "manually" to improve performance
return
'{"title":' . (isset($content->title) ? json_encode($content->title) : 'null') .
',"a11yTitle":' . (isset($content->a11y_title) ? $content->a11y_title : 'null') .
',"authors":' . (isset($content->authors) ? $content->authors : 'null') .
',"source":' . (isset($content->source) ? '"' . $content->source . '"' : 'null') .
',"license":' . (isset($content->license) ? '"' . $content->license . '"' : 'null') .
',"licenseVersion":' . (isset($content->license_version) ? '"' . $content->license_version . '"' : 'null') .
',"licenseExtras":' . (isset($content->license_extras) ? json_encode($content->license_extras) : 'null') .
',"yearFrom":' . (isset($content->year_from) ? $content->year_from : 'null') .
',"yearTo":' . (isset($content->year_to) ? $content->year_to : 'null') .
',"changes":' . (isset($content->changes) ? $content->changes : 'null') .
',"defaultLanguage":' . (isset($content->default_language) ? '"' . $content->default_language . '"' : 'null') .
',"authorComments":' . (isset($content->author_comments) ? json_encode($content->author_comments) : 'null') . '}';
}
/**
* Make the metadata into an associative array keyed by the property names
* @param mixed $metadata Array or object containing metadata
* @param bool $include_title
* @param bool $include_missing For metadata fields not being set, skip 'em.
* Relevant for content upgrade
* @param array $types
* @return array
*/
public static function toDBArray($metadata, $include_title = true, $include_missing = true, &$types = array()) {
$fields = array();
if (!is_array($metadata)) {
$metadata = (array) $metadata;
}
foreach (self::$fields as $key => $config) {
// Ignore title?
if ($key === 'title' && !$include_title) {
continue;
}
$exists = array_key_exists($key, $metadata);
// Don't include missing fields
if (!$include_missing && !$exists) {
continue;
}
$value = $exists ? $metadata[$key] : null;
// lowerCamelCase to snake_case
$db_field_name = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $key));
switch ($config['type']) {
case 'text':
if ($value !== null && strlen($value) > $config['maxLength']) {
$value = mb_substr($value, 0, $config['maxLength']);
}
$types[] = '%s';
break;
case 'int':
$value = ($value !== null) ? intval($value) : null;
$types[] = '%d';
break;
case 'json':
$value = ($value !== null) ? json_encode($value) : null;
$types[] = '%s';
break;
}
$fields[$db_field_name] = $value;
}
return $fields;
}
/**
* The metadataSettings field in libraryJson uses 1 for true and 0 for false.
* Here we are converting these to booleans, and also doing JSON encoding.
* This is invoked before the library data is beeing inserted/updated to DB.
*
* @param array $metadataSettings
* @return string
*/
public static function boolifyAndEncodeSettings($metadataSettings) {
// Convert metadataSettings values to boolean
if (isset($metadataSettings['disable'])) {
$metadataSettings['disable'] = $metadataSettings['disable'] === 1;
}
if (isset($metadataSettings['disableExtraTitleField'])) {
$metadataSettings['disableExtraTitleField'] = $metadataSettings['disableExtraTitleField'] === 1;
}
return json_encode($metadataSettings);
}
}

File diff suppressed because it is too large Load Diff

16
images/h5p.svg Normal file
View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 345 150" enable-background="new 0 0 345 150" xml:space="preserve">
<g>
<path fill="#FFFFFF" d="M325.7,14.7C317.6,6.9,305.3,3,289,3h-43.5H234v31h-66l-5.4,22.2c4.5-2.1,10.9-4.2,15.3-5.3
c4.4-1.1,8.8-0.9,13.1-0.9c14.6,0,26.5,4.5,35.6,13.3c9.1,8.8,13.6,20,13.6,33.4c0,9.4-2.3,18.5-7,27.2c-4.7,8.7-11.3,15.4-19.9,20
c-3.1,1.6-6.5,3.1-10.2,4.1h42.4H259V95h25c18.2,0,31.7-4.2,40.6-12.5c8.9-8.3,13.3-19.9,13.3-34.6
C337.9,33.6,333.8,22.5,325.7,14.7z M288.7,60.6c-3.5,3-9.6,4.4-18.3,4.4H259V33h13.2c8.4,0,14.2,1.5,17.2,4.7
c3.1,3.2,4.6,6.9,4.6,11.5C294,53.9,292.2,57.6,288.7,60.6z"/>
<path fill="#FFFFFF" d="M176.5,76.3c-7.9,0-14.7,4.6-18,11.2L119,81.9L136.8,3h-23.6H101v62H51V3H7v145h44V95h50v53h12.2h42
c-6.7-2-12.5-4.6-17.2-8.1c-4.8-3.6-8.7-7.7-11.7-12.3c-3-4.6-5.3-9.7-7.3-16.5l39.6-5.7c3.3,6.6,10.1,11.1,17.9,11.1
c11.1,0,20.1-9,20.1-20.1S187.5,76.3,176.5,76.3z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="36px" height="36px" viewBox="0 0 36 36" enable-background="new 0 0 36 36" xml:space="preserve">
<g>
<path fill="#FFFFFF" d="M0.126,13.306h3.07l0.365,3.476h3.354L6.55,13.306h3.083l1.044,9.934H7.594l-0.422-4.018H3.818L4.24,23.24
H1.17L0.126,13.306z"/>
<path fill="#FFFFFF" d="M27.738,13.306h5.103c1.111,0,1.916,0.264,2.414,0.793c0.498,0.529,0.696,1.281,0.593,2.257
c-0.105,1.003-0.489,1.787-1.152,2.351c-0.662,0.565-1.613,0.847-2.85,0.847h-1.681l-0.387,3.686h-3.083L27.738,13.306z
M30.376,17.541h0.752c0.592,0,1.018-0.103,1.279-0.308c0.261-0.205,0.408-0.469,0.442-0.789c0.033-0.312-0.043-0.576-0.228-0.793
c-0.185-0.217-0.564-0.325-1.138-0.325h-0.874L30.376,17.541z"/>
<g>
<polygon fill="#E24E26" points="12.431,25.515 11.035,9.851 26.38,9.851 24.982,25.512 18.698,27.254 "/>
<polygon fill="#F06529" points="18.707,25.923 23.785,24.515 24.98,11.132 18.707,11.132 "/>
<polygon fill="#EAEAEA" points="18.707,16.941 16.165,16.941 15.99,14.974 18.707,14.974 18.707,13.053 18.701,13.053
13.89,13.053 13.936,13.568 14.408,18.862 18.707,18.862 "/>
<polygon fill="#EAEAEA" points="18.707,21.93 18.699,21.933 16.56,21.355 16.423,19.823 15.383,19.823 14.494,19.823
14.763,22.839 18.699,23.932 18.707,23.929 "/>
<polygon fill="#FFFFFF" points="18.701,16.941 18.701,18.862 21.066,18.862 20.843,21.354 18.701,21.932 18.701,23.931
22.639,22.839 22.668,22.514 23.119,17.457 23.166,16.941 22.649,16.941 "/>
<polygon fill="#FFFFFF" points="18.701,13.053 18.701,14.246 18.701,14.969 18.701,14.974 23.335,14.974 23.335,14.974
23.341,14.974 23.38,14.542 23.467,13.568 23.513,13.053 "/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

100
js/h5p-action-bar.js Normal file
View File

@ -0,0 +1,100 @@
/**
* @class
* @augments H5P.EventDispatcher
* @param {Object} displayOptions
* @param {boolean} displayOptions.export Triggers the display of the 'Download' button
* @param {boolean} displayOptions.copyright Triggers the display of the 'Copyright' button
* @param {boolean} displayOptions.embed Triggers the display of the 'Embed' button
* @param {boolean} displayOptions.icon Triggers the display of the 'H5P icon' link
*/
H5P.ActionBar = (function ($, EventDispatcher) {
"use strict";
function ActionBar(displayOptions) {
EventDispatcher.call(this);
/** @alias H5P.ActionBar# */
var self = this;
var hasActions = false;
// Create action bar
var $actions = H5P.jQuery('<ul class="h5p-actions"></ul>');
/**
* Helper for creating action bar buttons.
*
* @private
* @param {string} type
* @param {string} customClass Instead of type class
*/
var addActionButton = function (type, customClass) {
/**
* Handles selection of action
*/
var handler = function () {
self.trigger(type);
};
H5P.jQuery('<li/>', {
'class': 'h5p-button h5p-noselect h5p-' + (customClass ? customClass : type),
role: 'button',
tabindex: 0,
title: H5P.t(type + 'Description'),
html: H5P.t(type),
on: {
click: handler,
keypress: function (e) {
if (e.which === 32) {
handler();
e.preventDefault(); // (since return false will block other inputs)
}
}
},
appendTo: $actions
});
hasActions = true;
};
// Register action bar buttons
if (displayOptions.export || displayOptions.copy) {
// Add export button
addActionButton('reuse', 'export');
}
if (displayOptions.copyright) {
addActionButton('copyrights');
}
if (displayOptions.embed) {
addActionButton('embed');
}
if (displayOptions.icon) {
// Add about H5P button icon
H5P.jQuery('<li><a class="h5p-link" href="http://h5p.org" target="_blank" title="' + H5P.t('h5pDescription') + '"></a></li>').appendTo($actions);
hasActions = true;
}
/**
* Returns a reference to the dom element
*
* @return {H5P.jQuery}
*/
self.getDOMElement = function () {
return $actions;
};
/**
* Does the actionbar contain actions?
*
* @return {Boolean}
*/
self.hasActions = function () {
return hasActions;
};
}
ActionBar.prototype = Object.create(EventDispatcher.prototype);
ActionBar.prototype.constructor = ActionBar;
return ActionBar;
})(H5P.jQuery, H5P.EventDispatcher);

View File

@ -0,0 +1,410 @@
/*global H5P*/
H5P.ConfirmationDialog = (function (EventDispatcher) {
"use strict";
/**
* Create a confirmation dialog
*
* @param [options] Options for confirmation dialog
* @param [options.instance] Instance that uses confirmation dialog
* @param [options.headerText] Header text
* @param [options.dialogText] Dialog text
* @param [options.cancelText] Cancel dialog button text
* @param [options.confirmText] Confirm dialog button text
* @param [options.hideCancel] Hide cancel button
* @param [options.hideExit] Hide exit button
* @param [options.skipRestoreFocus] Skip restoring focus when hiding the dialog
* @param [options.classes] Extra classes for popup
* @constructor
*/
function ConfirmationDialog(options) {
EventDispatcher.call(this);
var self = this;
// Make sure confirmation dialogs have unique id
H5P.ConfirmationDialog.uniqueId += 1;
var uniqueId = H5P.ConfirmationDialog.uniqueId;
// Default options
options = options || {};
options.headerText = options.headerText || H5P.t('confirmDialogHeader');
options.dialogText = options.dialogText || H5P.t('confirmDialogBody');
options.cancelText = options.cancelText || H5P.t('cancelLabel');
options.confirmText = options.confirmText || H5P.t('confirmLabel');
/**
* Handle confirming event
* @param {Event} e
*/
function dialogConfirmed(e) {
self.hide();
self.trigger('confirmed');
e.preventDefault();
}
/**
* Handle dialog canceled
* @param {Event} e
*/
function dialogCanceled(e) {
self.hide();
self.trigger('canceled');
e.preventDefault();
}
/**
* Flow focus to element
* @param {HTMLElement} element Next element to be focused
* @param {Event} e Original tab event
*/
function flowTo(element, e) {
element.focus();
e.preventDefault();
}
// Offset of exit button
var exitButtonOffset = 2 * 16;
var shadowOffset = 8;
// Determine if we are too large for our container and must resize
var resizeIFrame = false;
// Create background
var popupBackground = document.createElement('div');
popupBackground.classList
.add('h5p-confirmation-dialog-background', 'hidden', 'hiding');
// Create outer popup
var popup = document.createElement('div');
popup.classList.add('h5p-confirmation-dialog-popup', 'hidden');
if (options.classes) {
options.classes.forEach(function (popupClass) {
popup.classList.add(popupClass);
});
}
popup.setAttribute('role', 'dialog');
popup.setAttribute('aria-labelledby', 'h5p-confirmation-dialog-dialog-text-' + uniqueId);
popupBackground.appendChild(popup);
popup.addEventListener('keydown', function (e) {
if (e.which === 27) {// Esc key
// Exit dialog
dialogCanceled(e);
}
});
// Popup header
var header = document.createElement('div');
header.classList.add('h5p-confirmation-dialog-header');
popup.appendChild(header);
// Header text
var headerText = document.createElement('div');
headerText.classList.add('h5p-confirmation-dialog-header-text');
headerText.innerHTML = options.headerText;
header.appendChild(headerText);
// Popup body
var body = document.createElement('div');
body.classList.add('h5p-confirmation-dialog-body');
popup.appendChild(body);
// Popup text
var text = document.createElement('div');
text.classList.add('h5p-confirmation-dialog-text');
text.innerHTML = options.dialogText;
text.id = 'h5p-confirmation-dialog-dialog-text-' + uniqueId;
body.appendChild(text);
// Popup buttons
var buttons = document.createElement('div');
buttons.classList.add('h5p-confirmation-dialog-buttons');
body.appendChild(buttons);
// Cancel button
var cancelButton = document.createElement('button');
cancelButton.classList.add('h5p-core-cancel-button');
cancelButton.textContent = options.cancelText;
// Confirm button
var confirmButton = document.createElement('button');
confirmButton.classList.add('h5p-core-button');
confirmButton.classList.add('h5p-confirmation-dialog-confirm-button');
confirmButton.textContent = options.confirmText;
// Exit button
var exitButton = document.createElement('button');
exitButton.classList.add('h5p-confirmation-dialog-exit');
exitButton.setAttribute('aria-hidden', 'true');
exitButton.tabIndex = -1;
exitButton.title = options.cancelText;
// Cancel handler
cancelButton.addEventListener('click', dialogCanceled);
cancelButton.addEventListener('keydown', function (e) {
if (e.which === 32) { // Space
dialogCanceled(e);
}
else if (e.which === 9 && e.shiftKey) { // Shift-tab
flowTo(confirmButton, e);
}
});
if (!options.hideCancel) {
buttons.appendChild(cancelButton);
}
else {
// Center buttons
buttons.classList.add('center');
}
// Confirm handler
confirmButton.addEventListener('click', dialogConfirmed);
confirmButton.addEventListener('keydown', function (e) {
if (e.which === 32) { // Space
dialogConfirmed(e);
}
else if (e.which === 9 && !e.shiftKey) { // Tab
const nextButton = !options.hideCancel ? cancelButton : confirmButton;
flowTo(nextButton, e);
}
});
buttons.appendChild(confirmButton);
// Exit handler
exitButton.addEventListener('click', dialogCanceled);
exitButton.addEventListener('keydown', function (e) {
if (e.which === 32) { // Space
dialogCanceled(e);
}
});
if (!options.hideExit) {
popup.appendChild(exitButton);
}
// Wrapper element
var wrapperElement;
// Focus capturing
var focusPredator;
// Maintains hidden state of elements
var wrapperSiblingsHidden = [];
var popupSiblingsHidden = [];
// Element with focus before dialog
var previouslyFocused;
/**
* Set parent of confirmation dialog
* @param {HTMLElement} wrapper
* @returns {H5P.ConfirmationDialog}
*/
this.appendTo = function (wrapper) {
wrapperElement = wrapper;
return this;
};
/**
* Capture the focus element, send it to confirmation button
* @param {Event} e Original focus event
*/
var captureFocus = function (e) {
if (!popupBackground.contains(e.target)) {
e.preventDefault();
confirmButton.focus();
}
};
/**
* Hide siblings of element from assistive technology
*
* @param {HTMLElement} element
* @returns {Array} The previous hidden state of all siblings
*/
var hideSiblings = function (element) {
var hiddenSiblings = [];
var siblings = element.parentNode.children;
var i;
for (i = 0; i < siblings.length; i += 1) {
// Preserve hidden state
hiddenSiblings[i] = siblings[i].getAttribute('aria-hidden') ?
true : false;
if (siblings[i] !== element) {
siblings[i].setAttribute('aria-hidden', true);
}
}
return hiddenSiblings;
};
/**
* Restores assistive technology state of element's siblings
*
* @param {HTMLElement} element
* @param {Array} hiddenSiblings Hidden state of all siblings
*/
var restoreSiblings = function (element, hiddenSiblings) {
var siblings = element.parentNode.children;
var i;
for (i = 0; i < siblings.length; i += 1) {
if (siblings[i] !== element && !hiddenSiblings[i]) {
siblings[i].removeAttribute('aria-hidden');
}
}
};
/**
* Start capturing focus of parent and send it to dialog
*/
var startCapturingFocus = function () {
focusPredator = wrapperElement.parentNode || wrapperElement;
focusPredator.addEventListener('focus', captureFocus, true);
};
/**
* Clean up event listener for capturing focus
*/
var stopCapturingFocus = function () {
focusPredator.removeAttribute('aria-hidden');
focusPredator.removeEventListener('focus', captureFocus, true);
};
/**
* Hide siblings in underlay from assistive technologies
*/
var disableUnderlay = function () {
wrapperSiblingsHidden = hideSiblings(wrapperElement);
popupSiblingsHidden = hideSiblings(popupBackground);
};
/**
* Restore state of underlay for assistive technologies
*/
var restoreUnderlay = function () {
restoreSiblings(wrapperElement, wrapperSiblingsHidden);
restoreSiblings(popupBackground, popupSiblingsHidden);
};
/**
* Fit popup to container. Makes sure it doesn't overflow.
* @params {number} [offsetTop] Offset of popup
*/
var fitToContainer = function (offsetTop) {
var popupOffsetTop = parseInt(popup.style.top, 10);
if (offsetTop !== undefined) {
popupOffsetTop = offsetTop;
}
if (!popupOffsetTop) {
popupOffsetTop = 0;
}
// Overflows height
if (popupOffsetTop + popup.offsetHeight > wrapperElement.offsetHeight) {
popupOffsetTop = wrapperElement.offsetHeight - popup.offsetHeight - shadowOffset;
}
if (popupOffsetTop - exitButtonOffset <= 0) {
popupOffsetTop = exitButtonOffset + shadowOffset;
// We are too big and must resize
resizeIFrame = true;
}
popup.style.top = popupOffsetTop + 'px';
};
/**
* Show confirmation dialog
* @params {number} offsetTop Offset top
* @returns {H5P.ConfirmationDialog}
*/
this.show = function (offsetTop) {
// Capture focused item
previouslyFocused = document.activeElement;
wrapperElement.appendChild(popupBackground);
startCapturingFocus();
disableUnderlay();
popupBackground.classList.remove('hidden');
fitToContainer(offsetTop);
setTimeout(function () {
popup.classList.remove('hidden');
popupBackground.classList.remove('hiding');
setTimeout(function () {
// Focus confirm button
confirmButton.focus();
// Resize iFrame if necessary
if (resizeIFrame && options.instance) {
var minHeight = parseInt(popup.offsetHeight, 10) +
exitButtonOffset + (2 * shadowOffset);
self.setViewPortMinimumHeight(minHeight);
options.instance.trigger('resize');
resizeIFrame = false;
}
}, 100);
}, 0);
return this;
};
/**
* Hide confirmation dialog
* @returns {H5P.ConfirmationDialog}
*/
this.hide = function () {
popupBackground.classList.add('hiding');
popup.classList.add('hidden');
// Restore focus
stopCapturingFocus();
if (!options.skipRestoreFocus) {
previouslyFocused.focus();
}
restoreUnderlay();
setTimeout(function () {
popupBackground.classList.add('hidden');
wrapperElement.removeChild(popupBackground);
self.setViewPortMinimumHeight(null);
}, 100);
return this;
};
/**
* Retrieve element
*
* @return {HTMLElement}
*/
this.getElement = function () {
return popup;
};
/**
* Get previously focused element
* @return {HTMLElement}
*/
this.getPreviouslyFocused = function () {
return previouslyFocused;
};
/**
* Sets the minimum height of the view port
*
* @param {number|null} minHeight
*/
this.setViewPortMinimumHeight = function (minHeight) {
var container = document.querySelector('.h5p-container') || document.body;
container.style.minHeight = (typeof minHeight === 'number') ? (minHeight + 'px') : minHeight;
};
}
ConfirmationDialog.prototype = Object.create(EventDispatcher.prototype);
ConfirmationDialog.prototype.constructor = ConfirmationDialog;
return ConfirmationDialog;
}(H5P.EventDispatcher));
H5P.ConfirmationDialog.uniqueId = -1;

41
js/h5p-content-type.js Normal file
View File

@ -0,0 +1,41 @@
/**
* H5P.ContentType is a base class for all content types. Used by newRunnable()
*
* Functions here may be overridable by the libraries. In special cases,
* it is also possible to override H5P.ContentType on a global level.
*
* NOTE that this doesn't actually 'extend' the event dispatcher but instead
* it creates a single instance which all content types shares as their base
* prototype. (in some cases this may be the root of strange event behavior)
*
* @class
* @augments H5P.EventDispatcher
*/
H5P.ContentType = function (isRootLibrary) {
function ContentType() {}
// Inherit from EventDispatcher.
ContentType.prototype = new H5P.EventDispatcher();
/**
* Is library standalone or not? Not beeing standalone, means it is
* included in another library
*
* @return {Boolean}
*/
ContentType.prototype.isRoot = function () {
return isRootLibrary;
};
/**
* Returns the file path of a file in the current library
* @param {string} filePath The path to the file relative to the library folder
* @return {string} The full path to the file
*/
ContentType.prototype.getLibraryFilePath = function (filePath) {
return H5P.getLibraryPath(this.libraryInfo.versionedNameNoSpaces) + '/' + filePath;
};
return ContentType;
};

View File

@ -0,0 +1,313 @@
/*jshint -W083 */
var H5PUpgrades = H5PUpgrades || {};
H5P.ContentUpgradeProcess = (function (Version) {
/**
* @class
* @namespace H5P
*/
function ContentUpgradeProcess(name, oldVersion, newVersion, params, id, loadLibrary, done) {
var self = this;
// Make params possible to work with
try {
params = JSON.parse(params);
if (!(params instanceof Object)) {
throw true;
}
}
catch (event) {
return done({
type: 'errorParamsBroken',
id: id
});
}
self.loadLibrary = loadLibrary;
self.upgrade(name, oldVersion, newVersion, params.params, params.metadata, function (err, upgradedParams, upgradedMetadata) {
if (err) {
err.id = id;
return done(err);
}
done(null, JSON.stringify({params: upgradedParams, metadata: upgradedMetadata}));
});
}
/**
* Run content upgrade.
*
* @public
* @param {string} name
* @param {Version} oldVersion
* @param {Version} newVersion
* @param {Object} params
* @param {Object} metadata
* @param {Function} done
*/
ContentUpgradeProcess.prototype.upgrade = function (name, oldVersion, newVersion, params, metadata, done) {
var self = this;
// Load library details and upgrade routines
self.loadLibrary(name, newVersion, function (err, library) {
if (err) {
return done(err);
}
if (library.semantics === null) {
return done({
type: 'libraryMissing',
library: library.name + ' ' + library.version.major + '.' + library.version.minor
});
}
// Run upgrade routines on params
self.processParams(library, oldVersion, newVersion, params, metadata, function (err, params, metadata) {
if (err) {
return done(err);
}
// Check if any of the sub-libraries need upgrading
asyncSerial(library.semantics, function (index, field, next) {
self.processField(field, params[field.name], function (err, upgradedParams) {
if (upgradedParams) {
params[field.name] = upgradedParams;
}
next(err);
});
}, function (err) {
done(err, params, metadata);
});
});
});
};
/**
* Run upgrade hooks on params.
*
* @public
* @param {Object} library
* @param {Version} oldVersion
* @param {Version} newVersion
* @param {Object} params
* @param {Function} next
*/
ContentUpgradeProcess.prototype.processParams = function (library, oldVersion, newVersion, params, metadata, next) {
if (H5PUpgrades[library.name] === undefined) {
if (library.upgradesScript) {
// Upgrades script should be loaded so the upgrades should be here.
return next({
type: 'scriptMissing',
library: library.name + ' ' + newVersion
});
}
// No upgrades script. Move on
return next(null, params, metadata);
}
// Run upgrade hooks. Start by going through major versions
asyncSerial(H5PUpgrades[library.name], function (major, minors, nextMajor) {
if (major < oldVersion.major || major > newVersion.major) {
// Older than the current version or newer than the selected
nextMajor();
}
else {
// Go through the minor versions for this major version
asyncSerial(minors, function (minor, upgrade, nextMinor) {
minor =+ minor;
if (minor <= oldVersion.minor || minor > newVersion.minor) {
// Older than or equal to the current version or newer than the selected
nextMinor();
}
else {
// We found an upgrade hook, run it
var unnecessaryWrapper = (upgrade.contentUpgrade !== undefined ? upgrade.contentUpgrade : upgrade);
try {
unnecessaryWrapper(params, function (err, upgradedParams, upgradedExtras) {
params = upgradedParams;
if (upgradedExtras && upgradedExtras.metadata) { // Optional
metadata = upgradedExtras.metadata;
}
nextMinor(err);
}, {metadata: metadata});
}
catch (err) {
if (console && console.error) {
console.error("Error", err.stack);
console.error("Error", err.name);
console.error("Error", err.message);
}
next(err);
}
}
}, nextMajor);
}
}, function (err) {
next(err, params, metadata);
});
};
/**
* Process parameter fields to find and upgrade sub-libraries.
*
* @public
* @param {Object} field
* @param {Object} params
* @param {Function} done
*/
ContentUpgradeProcess.prototype.processField = function (field, params, done) {
var self = this;
if (params === undefined) {
return done();
}
switch (field.type) {
case 'library':
if (params.library === undefined || params.params === undefined) {
return done();
}
// Look for available upgrades
var usedLib = params.library.split(' ', 2);
for (var i = 0; i < field.options.length; i++) {
var availableLib = (typeof field.options[i] === 'string') ? field.options[i].split(' ', 2) : field.options[i].name.split(' ', 2);
if (availableLib[0] === usedLib[0]) {
if (availableLib[1] === usedLib[1]) {
return done(); // Same version
}
// We have different versions
var usedVer = new Version(usedLib[1]);
var availableVer = new Version(availableLib[1]);
if (usedVer.major > availableVer.major || (usedVer.major === availableVer.major && usedVer.minor >= availableVer.minor)) {
return done({
type: 'errorTooHighVersion',
used: usedLib[0] + ' ' + usedVer,
supported: availableLib[0] + ' ' + availableVer
}); // Larger or same version that's available
}
// A newer version is available, upgrade params
return self.upgrade(availableLib[0], usedVer, availableVer, params.params, params.metadata, function (err, upgradedParams, upgradedMetadata) {
if (!err) {
params.library = availableLib[0] + ' ' + availableVer.major + '.' + availableVer.minor;
params.params = upgradedParams;
if (upgradedMetadata) {
params.metadata = upgradedMetadata;
}
}
done(err, params);
});
}
}
// Content type was not supporte by the higher version
done({
type: 'errorNotSupported',
used: usedLib[0] + ' ' + usedVer
});
break;
case 'group':
if (field.fields.length === 1 && field.isSubContent !== true) {
// Single field to process, wrapper will be skipped
self.processField(field.fields[0], params, function (err, upgradedParams) {
if (upgradedParams) {
params = upgradedParams;
}
done(err, params);
});
}
else {
// Go through all fields in the group
asyncSerial(field.fields, function (index, subField, next) {
var paramsToProcess = params ? params[subField.name] : null;
self.processField(subField, paramsToProcess, function (err, upgradedParams) {
if (upgradedParams) {
params[subField.name] = upgradedParams;
}
next(err);
});
}, function (err) {
done(err, params);
});
}
break;
case 'list':
// Go trough all params in the list
asyncSerial(params, function (index, subParams, next) {
self.processField(field.field, subParams, function (err, upgradedParams) {
if (upgradedParams) {
params[index] = upgradedParams;
}
next(err);
});
}, function (err) {
done(err, params);
});
break;
default:
done();
}
};
/**
* Helps process each property on the given object asynchronously in serial order.
*
* @private
* @param {Object} obj
* @param {Function} process
* @param {Function} finished
*/
var asyncSerial = function (obj, process, finished) {
var id, isArray = obj instanceof Array;
// Keep track of each property that belongs to this object.
if (!isArray) {
var ids = [];
for (id in obj) {
if (obj.hasOwnProperty(id)) {
ids.push(id);
}
}
}
var i = -1; // Keeps track of the current property
/**
* Private. Process the next property
*/
var next = function () {
id = isArray ? i : ids[i];
process(id, obj[id], check);
};
/**
* Private. Check if we're done or have an error.
*
* @param {String} err
*/
var check = function (err) {
// We need to use a real async function in order for the stack to clear.
setTimeout(function () {
i++;
if (i === (isArray ? obj.length : ids.length) || (err !== undefined && err !== null)) {
finished(err);
}
else {
next();
}
}, 0);
};
check(); // Start
};
return ContentUpgradeProcess;
})(H5P.Version);

View File

@ -0,0 +1,63 @@
/* global importScripts */
var H5P = H5P || {};
importScripts('h5p-version.js', 'h5p-content-upgrade-process.js');
var libraryLoadedCallback;
/**
* Register message handlers
*/
var messageHandlers = {
newJob: function (job) {
// Start new job
new H5P.ContentUpgradeProcess(job.name, new H5P.Version(job.oldVersion), new H5P.Version(job.newVersion), job.params, job.id, function loadLibrary(name, version, next) {
// TODO: Cache?
postMessage({
action: 'loadLibrary',
name: name,
version: version.toString()
});
libraryLoadedCallback = next;
}, function done(err, result) {
if (err) {
// Return error
postMessage({
action: 'error',
id: job.id,
err: err.message ? err.message : err
});
return;
}
// Return upgraded content
postMessage({
action: 'done',
id: job.id,
params: result
});
});
},
libraryLoaded: function (data) {
var library = data.library;
if (library.upgradesScript) {
try {
importScripts(library.upgradesScript);
}
catch (err) {
libraryLoadedCallback(err);
return;
}
}
libraryLoadedCallback(null, data.library);
}
};
/**
* Handle messages from our master
*/
onmessage = function (event) {
if (event.data.action !== undefined && messageHandlers[event.data.action]) {
messageHandlers[event.data.action].call(this, event.data);
}
};

View File

@ -1,16 +1,17 @@
/*jshint -W083 */
var H5PUpgrades = H5PUpgrades || {};
/* global H5PAdminIntegration H5PUtils */
(function ($) {
var info, $container, librariesCache = {};
(function ($, Version) {
var info, $log, $container, librariesCache = {}, scriptsCache = {};
// Initialize
$(document).ready(function () {
// Get library info
info = H5PIntegration.getLibraryInfo();
info = H5PAdminIntegration.libraryInfo;
// Get and reset container
$container = $('#h5p-admin-container').html('<p>' + info.message + '</p>');
const $wrapper = $('#h5p-admin-container').html('');
$log = $('<ul class="content-upgrade-log"></ul>').appendTo($wrapper);
$container = $('<div><p>' + info.message + '</p></div>').appendTo($wrapper);
// Make it possible to select version
var $version = $(getVersionSelect(info.versions)).appendTo($container);
@ -43,87 +44,6 @@ var H5PUpgrades = H5PUpgrades || {};
}
};
/**
* Private. Helps process each property on the given object asynchronously in serial order.
*
* @param {Object} obj
* @param {Function} process
* @param {Function} finished
*/
var asyncSerial = function (obj, process, finished) {
var id, isArray = obj instanceof Array;
// Keep track of each property that belongs to this object.
if (!isArray) {
var ids = [];
for (id in obj) {
if (obj.hasOwnProperty(id)) {
ids.push(id);
}
}
}
var i = -1; // Keeps track of the current property
/**
* Private. Process the next property
*/
var next = function () {
id = isArray ? i : ids[i];
process(id, obj[id], check);
};
/**
* Private. Check if we're done or have an error.
*
* @param {String} err
*/
var check = function (err) {
// We need to use a real async function in order for the stack to clear.
setTimeout(function () {
i++;
if (i === (isArray ? obj.length : ids.length) || (err !== undefined && err !== null)) {
finished(err);
}
else {
next();
}
}, 0);
};
check(); // Start
};
/**
* Make it easy to keep track of version details.
*
* @param {String} version
* @param {Number} libraryId
* @returns {_L1.Version}
*/
function Version(version, libraryId) {
if (libraryId !== undefined) {
version = info.versions[libraryId];
// Public
this.libraryId = libraryId;
}
var versionSplit = version.split('.', 3);
// Public
this.major = versionSplit[0];
this.minor = versionSplit[1];
/**
* Public. Custom string for this object.
*
* @returns {String}
*/
this.toString = function () {
return version;
};
}
/**
* Displays a throbber in the status field.
*
@ -154,17 +74,81 @@ var H5PUpgrades = H5PUpgrades || {};
var self = this;
// Get selected version
self.version = new Version(null, libraryId);
self.version = new Version(info.versions[libraryId]);
self.version.libraryId = libraryId;
// Create throbber with loading text and progress
self.throbber = new Throbber(info.inProgress.replace('%ver', self.version));
self.started = new Date().getTime();
self.io = 0;
// Track number of working
self.working = 0;
var start = function () {
// Get the next batch
self.nextBatch({
libraryId: libraryId,
token: info.token
});
};
if (window.Worker !== undefined) {
// Prepare our workers
self.initWorkers();
start();
}
else {
// No workers, do the job ourselves
self.loadScript(info.scriptBaseUrl + '/h5p-content-upgrade-process.js' + info.buster, start);
}
}
/**
* Initialize workers
*/
ContentUpgrade.prototype.initWorkers = function () {
var self = this;
// Determine number of workers (defaults to 4)
var numWorkers = (window.navigator !== undefined && window.navigator.hardwareConcurrency ? window.navigator.hardwareConcurrency : 4);
self.workers = new Array(numWorkers);
// Register message handlers
var messageHandlers = {
done: function (result) {
self.workDone(result.id, result.params, this);
},
error: function (error) {
self.printError(error.err);
self.workDone(error.id, null, this);
},
loadLibrary: function (details) {
var worker = this;
self.loadLibrary(details.name, new Version(details.version), function (err, library) {
if (err) {
// Reset worker?
return;
}
worker.postMessage({
action: 'libraryLoaded',
library: library
});
});
}
};
for (var i = 0; i < numWorkers; i++) {
self.workers[i] = new Worker(info.scriptBaseUrl + '/h5p-content-upgrade-worker.js' + info.buster);
self.workers[i].onmessage = function (event) {
if (event.data.action !== undefined && messageHandlers[event.data.action]) {
messageHandlers[event.data.action].call(this, event.data);
}
};
}
};
/**
* Get the next batch and start processing it.
@ -174,12 +158,24 @@ var H5PUpgrades = H5PUpgrades || {};
ContentUpgrade.prototype.nextBatch = function (outData) {
var self = this;
// Track time spent on IO
var start = new Date().getTime();
$.post(info.infoUrl, outData, function (inData) {
self.io += new Date().getTime() - start;
if (!(inData instanceof Object)) {
// Print errors from backend
return self.setStatus(inData);
}
if (inData.left === 0) {
var total = new Date().getTime() - self.started;
if (window.console && console.log) {
console.log('The upgrade process took ' + (total / 1000) + ' seconds. (' + (Math.round((self.io / (total / 100)) * 100) / 100) + ' % IO)' );
}
// Terminate workers
self.terminate();
// Nothing left to process
return self.setStatus(info.done);
}
@ -188,7 +184,7 @@ var H5PUpgrades = H5PUpgrades || {};
self.token = inData.token;
// Start processing
self.processBatch(inData.params);
self.processBatch(inData.params, inData.skipped);
});
};
@ -206,118 +202,65 @@ var H5PUpgrades = H5PUpgrades || {};
*
* @param {Object} parameters
*/
ContentUpgrade.prototype.processBatch = function (parameters) {
ContentUpgrade.prototype.processBatch = function (parameters, skipped) {
var self = this;
var upgraded = {}; // Track upgraded params
var current = 0; // Track progress
asyncSerial(parameters, function (id, params, next) {
// Track upgraded params
self.upgraded = {};
self.skipped = skipped;
try {
// Make params possible to work with
params = JSON.parse(params);
if (!(params instanceof Object)) {
throw true;
// Track current batch
self.parameters = parameters;
// Create id mapping
self.ids = [];
for (var id in parameters) {
if (parameters.hasOwnProperty(id)) {
self.ids.push(id);
}
}
catch (event) {
return next(info.errorContent.replace('%id', id) + ' ' + info.errorParamsBroken);
// Keep track of current content
self.current = -1;
if (self.workers !== undefined) {
// Assign each worker content to upgrade
for (var i = 0; i < self.workers.length; i++) {
self.assignWork(self.workers[i]);
}
// Upgrade this content.
self.upgrade(info.library.name, new Version(info.library.version), self.version, params, function (err, params) {
if (err) {
return next(info.errorContent.replace('%id', id) + ' ' + err);
}
else {
upgraded[id] = JSON.stringify(params);
current++;
self.throbber.setProgress(Math.round((info.total - self.left + current) / (info.total / 100)) + ' %');
next();
});
}, function (err) {
// Finished with all parameters that came in
if (err) {
return self.setStatus('<p>' + info.error + '<br/>' + err + '</p>');
self.assignWork();
}
// Save upgraded content and get next round of data to process
self.nextBatch({
libraryId: self.version.libraryId,
token: self.token,
params: JSON.stringify(upgraded)
});
});
};
/**
* Upgade the given content.
*
* @param {String} name
* @param {Version} oldVersion
* @param {Version} newVersion
* @param {Object} params
* @param {Function} next
* @returns {undefined}
*/
ContentUpgrade.prototype.upgrade = function (name, oldVersion, newVersion, params, next) {
ContentUpgrade.prototype.assignWork = function (worker) {
var self = this;
// Load library details and upgrade routines
self.loadLibrary(name, newVersion, function (err, library) {
if (err) {
return next(err);
var id = self.ids[self.current + 1];
if (id === undefined) {
return false; // Out of work
}
self.current++;
self.working++;
// Run upgrade routines on params
self.processParams(library, oldVersion, newVersion, params, function (err, params) {
if (err) {
return next(err);
if (worker) {
worker.postMessage({
action: 'newJob',
id: id,
name: info.library.name,
oldVersion: info.library.version,
newVersion: self.version.toString(),
params: self.parameters[id]
});
}
// Check if any of the sub-libraries need upgrading
asyncSerial(library.semantics, function (index, field, next) {
self.processField(field, params[field.name], function (err, upgradedParams) {
if (upgradedParams) {
params[field.name] = upgradedParams;
}
next(err);
});
}, function (err) {
next(err, params);
});
});
});
};
/**
* Load library data needed for content upgrade.
*
* @param {String} name
* @param {Version} version
* @param {Function} next
*/
ContentUpgrade.prototype.loadLibrary = function (name, version, next) {
var self = this;
var key = name + '/' + version.major + '/' + version.minor;
if (librariesCache[key] !== undefined) {
// Library has been loaded before. Return cache.
next(null, librariesCache[key]);
return;
}
$.ajax({
dataType: 'json',
cache: true,
url: info.libraryBaseUrl + '/' + key
}).fail(function () {
next(info.errorData.replace('%lib', name + ' ' + version));
}).done(function (library) {
librariesCache[key] = library;
else {
new H5P.ContentUpgradeProcess(info.library.name, new Version(info.library.version), self.version, self.parameters[id], id, function loadLibrary(name, version, next) {
self.loadLibrary(name, version, function (err, library) {
if (library.upgradesScript) {
self.loadScript(library.upgradesScript, function (err) {
if (err) {
@ -330,6 +273,112 @@ var H5PUpgrades = H5PUpgrades || {};
next(null, library);
}
});
}, function done(err, result) {
if (err) {
self.printError(err);
result = null;
}
self.workDone(id, result);
});
}
};
/**
*
*/
ContentUpgrade.prototype.workDone = function (id, result, worker) {
var self = this;
self.working--;
if (result === null) {
self.skipped.push(id);
}
else {
self.upgraded[id] = result;
}
// Update progress message
self.throbber.setProgress(Math.round((info.total - self.left + self.current) / (info.total / 100)) + ' %');
// Assign next job
if (self.assignWork(worker) === false && self.working === 0) {
// All workers have finsihed.
self.nextBatch({
libraryId: self.version.libraryId,
token: self.token,
skipped: JSON.stringify(self.skipped),
params: JSON.stringify(self.upgraded)
});
}
};
/**
*
*/
ContentUpgrade.prototype.terminate = function () {
var self = this;
if (self.workers) {
// Stop all workers
for (var i = 0; i < self.workers.length; i++) {
self.workers[i].terminate();
}
}
};
var librariesLoadedCallbacks = {};
/**
* Load library data needed for content upgrade.
*
* @param {String} name
* @param {Version} version
* @param {Function} next
*/
ContentUpgrade.prototype.loadLibrary = function (name, version, next) {
var self = this;
var key = name + '/' + version.major + '/' + version.minor;
if (librariesCache[key] === true) {
// Library is being loaded, que callback
if (librariesLoadedCallbacks[key] === undefined) {
librariesLoadedCallbacks[key] = [next];
return;
}
librariesLoadedCallbacks[key].push(next);
return;
}
else if (librariesCache[key] !== undefined) {
// Library has been loaded before. Return cache.
next(null, librariesCache[key]);
return;
}
// Track time spent loading
var start = new Date().getTime();
librariesCache[key] = true;
$.ajax({
dataType: 'json',
cache: true,
url: info.libraryBaseUrl + '/' + key
}).fail(function () {
self.io += new Date().getTime() - start;
next(info.errorData.replace('%lib', name + ' ' + version));
}).done(function (library) {
self.io += new Date().getTime() - start;
librariesCache[key] = library;
next(null, library);
if (librariesLoadedCallbacks[key] !== undefined) {
for (var i = 0; i < librariesLoadedCallbacks[key].length; i++) {
librariesLoadedCallbacks[key][i](null, library);
}
}
delete librariesLoadedCallbacks[key];
});
};
/**
@ -339,162 +388,58 @@ var H5PUpgrades = H5PUpgrades || {};
* @param {Function} next
*/
ContentUpgrade.prototype.loadScript = function (url, next) {
var self = this;
if (scriptsCache[url] !== undefined) {
next();
return;
}
// Track time spent loading
var start = new Date().getTime();
$.ajax({
dataType: 'script',
cache: true,
url: url
}).fail(function () {
self.io += new Date().getTime() - start;
next(true);
}).done(function () {
scriptsCache[url] = true;
self.io += new Date().getTime() - start;
next();
});
};
/**
* Run upgrade hooks on params.
*
* @param {Object} library
* @param {Version} oldVersion
* @param {Version} newVersion
* @param {Object} params
* @param {Function} next
*/
ContentUpgrade.prototype.processParams = function (library, oldVersion, newVersion, params, next) {
if (H5PUpgrades[library.name] === undefined) {
if (library.upgradesScript) {
// Upgrades script should be loaded so the upgrades should be here.
return next(info.errorScript.replace('%lib', library.name + ' ' + newVersion));
}
// No upgrades script. Move on
return next(null, params);
}
// Run upgrade hooks. Start by going through major versions
asyncSerial(H5PUpgrades[library.name], function (major, minors, nextMajor) {
if (major < oldVersion.major || major > newVersion.major) {
// Older than the current version or newer than the selected
nextMajor();
}
else {
// Go through the minor versions for this major version
asyncSerial(minors, function (minor, upgrade, nextMinor) {
if (minor <= oldVersion.minor || minor > newVersion.minor) {
// Older than or equal to the current version or newer than the selected
nextMinor();
}
else {
// We found an upgrade hook, run it
var unnecessaryWrapper = (upgrade.contentUpgrade !== undefined ? upgrade.contentUpgrade : upgrade);
try {
unnecessaryWrapper(params, function (err, upgradedParams) {
params = upgradedParams;
nextMinor(err);
});
}
catch (err) {
next(err);
}
}
}, nextMajor);
}
}, function (err) {
next(err, params);
});
};
/**
* Process parameter fields to find and upgrade sub-libraries.
*
* @param {Object} field
* @param {Object} params
* @param {Function} next
*/
ContentUpgrade.prototype.processField = function (field, params, next) {
ContentUpgrade.prototype.printError = function (error) {
var self = this;
if (params === undefined) {
return next();
}
switch (field.type) {
case 'library':
if (params.library === undefined || params.params === undefined) {
return next();
}
// Look for available upgrades
var usedLib = params.library.split(' ', 2);
for (var i = 0; i < field.options.length; i++) {
var availableLib = field.options[i].split(' ', 2);
if (availableLib[0] === usedLib[0]) {
if (availableLib[1] === usedLib[1]) {
return next(); // Same version
}
// We have different versions
var usedVer = new Version(usedLib[1]);
var availableVer = new Version(availableLib[1]);
if (usedVer.major > availableVer.major || (usedVer.major === availableVer.major && usedVer.minor >= availableVer.minor)) {
return next(); // Larger or same version that's available
}
// A newer version is available, upgrade params
return self.upgrade(availableLib[0], usedVer, availableVer, params.params, function (err, upgraded) {
if (!err) {
params.library = availableLib[0] + ' ' + availableVer.major + '.' + availableVer.minor;
params.params = upgraded;
}
next(err, params);
});
}
}
next();
switch (error.type) {
case 'errorParamsBroken':
error = info.errorContent.replace('%id', error.id) + ' ' + info.errorParamsBroken;
break;
case 'group':
if (field.fields.length === 1) {
// Single field to process, wrapper will be skipped
self.processField(field.fields[0], params, function (err, upgradedParams) {
if (upgradedParams) {
params = upgradedParams;
}
next(err, params);
});
}
else {
// Go through all fields in the group
asyncSerial(field.fields, function (index, subField, next) {
self.processField(subField, params[subField.name], function (err, upgradedParams) {
if (upgradedParams) {
params[subField.name] = upgradedParams;
}
next(err);
});
}, function (err) {
next(err, params);
});
}
case 'libraryMissing':
error = info.errorLibrary.replace('%lib', error.library);
break;
case 'list':
// Go trough all params in the list
asyncSerial(params, function (index, subParams, next) {
self.processField(field.field, subParams, function (err, upgradedParams) {
if (upgradedParams) {
params[index] = upgradedParams;
}
next(err);
});
}, function (err) {
next(err, params);
});
case 'scriptMissing':
error = info.errorScript.replace('%lib', error.library);
break;
default:
next();
case 'errorTooHighVersion':
error = info.errorContent.replace('%id', error.id) + ' ' + info.errorTooHighVersion.replace('%used', error.used).replace('%supported', error.supported);
break;
case 'errorNotSupported':
error = info.errorContent.replace('%id', error.id) + ' ' + info.errorNotSupported.replace('%used', error.used);
break;
}
$('<li>' + info.error + '<br/>' + error + '</li>').appendTo($log);
};
})(H5P.jQuery);
})(H5P.jQuery, H5P.Version);

View File

@ -1,3 +1,4 @@
/* global H5PUtils */
var H5PDataView = (function ($) {
/**
@ -32,8 +33,9 @@ var H5PDataView = (function ($) {
* search in column 2.
* @param {Function} loaded
* Callback for when data has been loaded.
* @param {Object} order
*/
function H5PDataView(container, source, headers, l10n, classes, filters, loaded) {
function H5PDataView(container, source, headers, l10n, classes, filters, loaded, order) {
var self = this;
self.$container = $(container).addClass('h5p-data-view').html('');
@ -44,18 +46,28 @@ var H5PDataView = (function ($) {
self.classes = (classes === undefined ? {} : classes);
self.filters = (filters === undefined ? [] : filters);
self.loaded = loaded;
self.order = order;
self.limit = 20;
self.offset = 0;
self.filterOn = [];
self.facets = {};
// Index of column with author name; could be made more general by passing database column names and checking for position
self.columnIdAuthor = 2;
// Future option: Create more general solution for filter presets
if (H5PIntegration.user && parseInt(H5PIntegration.user.canToggleViewOthersH5PContents) === 1) {
self.updateTable([]);
self.filterByFacet(self.columnIdAuthor, H5PIntegration.user.id, H5PIntegration.user.name || '');
}
else {
self.loadData();
}
}
/**
* Load data from source URL.
*
* @public
*/
H5PDataView.prototype.loadData = function () {
var self = this;
@ -68,8 +80,8 @@ var H5PDataView = (function ($) {
url += (url.indexOf('?') === -1 ? '?' : '&') + 'offset=' + self.offset + '&limit=' + self.limit;
// Add sorting
if (self.sortBy !== undefined && self.sortDir !== undefined) {
url += '&sortBy=' + self.sortBy + '&sortDir=' + self.sortDir;
if (self.order !== undefined) {
url += '&sortBy=' + self.order.by + '&sortDir=' + self.order.dir;
}
// Add filters
@ -83,6 +95,15 @@ var H5PDataView = (function ($) {
url += '&filters[' + i + ']=' + encodeURIComponent(self.filterOn[i]);
}
// Add facets
for (var col in self.facets) {
if (!self.facets.hasOwnProperty(col)) {
continue;
}
url += '&facets[' + col + ']=' + self.facets[col].id;
}
// Fire ajax request
$.ajax({
dataType: 'json',
@ -112,7 +133,6 @@ var H5PDataView = (function ($) {
/**
* Display the given message to the user.
*
* @public
* @param {jQuery} $message wrapper with message
*/
H5PDataView.prototype.setMessage = function ($message) {
@ -129,7 +149,6 @@ var H5PDataView = (function ($) {
/**
* Update table data.
*
* @public
* @param {Array} rows
*/
H5PDataView.prototype.updateTable = function (rows) {
@ -142,31 +161,158 @@ var H5PDataView = (function ($) {
// Add filters
self.addFilters();
// Add toggler for others' content
if (H5PIntegration.user && parseInt(H5PIntegration.user.canToggleViewOthersH5PContents) > 0) {
// canToggleViewOthersH5PContents = 1 is setting for only showing current user's contents
self.addOthersContentToggler(parseInt(H5PIntegration.user.canToggleViewOthersH5PContents) === 1);
}
// Add facets
self.$facets = $('<div/>', {
'class': 'h5p-facet-wrapper',
appendTo: self.$container
});
// Create new table
self.table = new H5PUtils.Table(self.classes, self.headers);
self.table.setHeaders(self.headers, function (col, dir) {
// Sorting column or direction has changed callback.
self.sortBy = col;
self.sortDir = dir;
self.table.setHeaders(self.headers, function (order) {
// Sorting column or direction has changed.
self.order = order;
self.loadData();
});
}, self.order);
self.table.appendTo(self.$container);
}
// Process cell data before updating table
for (var i = 0; i < self.headers.length; i++) {
if (self.headers[i].facet === true) {
// Process rows for col, expect object or array
for (var j = 0; j < rows.length; j++) {
rows[j][i] = self.createFacets(rows[j][i], i);
}
}
}
// Add/update rows
self.table.setRows(rows);
var $tbody = self.table.setRows(rows);
// Add event handlers for facets
$('.h5p-facet', $tbody).click(function () {
var $facet = $(this);
self.filterByFacet($facet.data('col'), $facet.data('id'), $facet.text());
}).keypress(function (event) {
if (event.which === 32) {
var $facet = $(this);
self.filterByFacet($facet.data('col'), $facet.data('id'), $facet.text());
}
});
};
/**
* Create button for adding facet to filter.
*
* @param (object|Array) input
* @param number col ID of column
*/
H5PDataView.prototype.createFacets = function (input, col) {
var facets = '';
if (input instanceof Array) {
// Facet can be filtered on multiple values at the same time
for (var i = 0; i < input.length; i++) {
if (facets !== '') {
facets += ', ';
}
facets += '<span class="h5p-facet" role="button" tabindex="0" data-id="' + input[i].id + '" data-col="' + col + '">' + input[i].title + '</span>';
}
}
else {
// Single value facet filtering
facets += '<span class="h5p-facet" role="button" tabindex="0" data-id="' + input.id + '" data-col="' + col + '">' + input.title + '</span>';
}
return facets === '' ? '—' : facets;
};
/**
* Adds a filter based on the given facet.
*
* @param number col ID of column we're filtering
* @param number id ID to filter on
* @param string text Human readable label for the filter
*/
H5PDataView.prototype.filterByFacet = function (col, id, text) {
var self = this;
if (self.facets[col] !== undefined) {
if (self.facets[col].id === id) {
return; // Don't use the same filter again
}
// Remove current filter for this col
self.facets[col].$tag.remove();
}
// Add to UI
self.facets[col] = {
id: id,
'$tag': $('<span/>', {
'class': 'h5p-facet-tag',
text: text,
appendTo: self.$facets,
})
};
/**
* Callback for removing filter.
*
* @private
*/
var remove = function () {
// Uncheck toggler for others' H5P contents
if ( self.$othersContentToggler && self.facets.hasOwnProperty( self.columnIdAuthor ) ) {
self.$othersContentToggler.prop('checked', false );
}
self.facets[col].$tag.remove();
delete self.facets[col];
self.loadData();
};
// Remove button
$('<span/>', {
role: 'button',
tabindex: 0,
appendTo: self.facets[col].$tag,
text: self.l10n.remove,
title: self.l10n.remove,
on: {
click: remove,
keypress: function (event) {
if (event.which === 32) {
remove();
}
}
}
});
// Load data with new filter
self.loadData();
};
/**
* Update pagination widget.
*
* @public
* @param {Number} num size of data collection
*/
H5PDataView.prototype.updatePagination = function (num) {
var self = this;
if (self.pagination === undefined) {
if (self.table === undefined) {
// No table, no pagination
return;
}
// Create new widget
var $pagerContainer = $('<div/>', {'class': 'h5p-pagination'});
self.pagination = new H5PUtils.Pagination(num, self.limit, function (offset) {
@ -186,8 +332,6 @@ var H5PDataView = (function ($) {
/**
* Add filters.
*
* @public
*/
H5PDataView.prototype.addFilters = function () {
var self = this;
@ -202,8 +346,7 @@ var H5PDataView = (function ($) {
/**
* Add text filter for given col num.
* @public
*
* @param {Number} col
*/
H5PDataView.prototype.addTextFilter = function (col) {
@ -251,5 +394,49 @@ var H5PDataView = (function ($) {
}).appendTo(self.$container);
};
/**
* Add toggle for others' H5P content.
* @param {boolean} [checked=false] Initial check setting.
*/
H5PDataView.prototype.addOthersContentToggler = function (checked) {
var self = this;
checked = (typeof checked === 'undefined') ? false : checked;
// Checkbox
this.$othersContentToggler = $('<input/>', {
type: 'checkbox',
'class': 'h5p-others-contents-toggler',
'id': 'h5p-others-contents-toggler',
'checked': checked,
'click': function () {
if ( this.checked ) {
// Add filter on current user
self.filterByFacet( self.columnIdAuthor, H5PIntegration.user.id, H5PIntegration.user.name );
}
else {
// Remove facet indicator and reload full data view
if ( self.facets.hasOwnProperty( self.columnIdAuthor ) && self.facets[self.columnIdAuthor].$tag ) {
self.facets[self.columnIdAuthor].$tag.remove();
}
delete self.facets[self.columnIdAuthor];
self.loadData();
}
}
});
// Label
var $label = $('<label>', {
'class': 'h5p-others-contents-toggler-label',
'text': this.l10n.showOwnContentOnly,
'for': 'h5p-others-contents-toggler'
}).prepend(this.$othersContentToggler);
$('<div>', {
'class': 'h5p-others-contents-toggler-wrapper'
}).append($label)
.appendTo(this.$container);
};
return H5PDataView;
})(H5P.jQuery);

54
js/h5p-display-options.js Normal file
View File

@ -0,0 +1,54 @@
/**
* Utility that makes it possible to hide fields when a checkbox is unchecked
*/
(function ($) {
function setupHiding() {
var $toggler = $(this);
// Getting the field which should be hidden:
var $subject = $($toggler.data('h5p-visibility-subject-selector'));
var toggle = function () {
$subject.toggle($toggler.is(':checked'));
};
$toggler.change(toggle);
toggle();
}
function setupRevealing() {
var $button = $(this);
// Getting the field which should have the value:
var $input = $('#' + $button.data('control'));
if (!$input.data('value')) {
$button.remove();
return;
}
// Setup button action
var revealed = false;
var text = $button.html();
$button.click(function () {
if (revealed) {
$input.val('');
$button.html(text);
revealed = false;
}
else {
$input.val($input.data('value'));
$button.html($button.data('hide'));
revealed = true;
}
});
}
$(document).ready(function () {
// Get the checkboxes making other fields being hidden:
$('.h5p-visibility-toggler').each(setupHiding);
// Get the buttons making other fields have hidden values:
$('.h5p-reveal-value').each(setupRevealing);
});
})(H5P.jQuery);

View File

@ -1,69 +1,27 @@
/*jshint multistr: true */
/**
*
* Converts old script tag embed to iframe
*/
var H5P = H5P || (function () {
var H5POldEmbed = H5POldEmbed || (function () {
var head = document.getElementsByTagName('head')[0];
var contentId = 0;
var contents = {};
var resizer = false;
/**
* Wraps multiple content between a prefix and a suffix.
* Loads the resizing script
*/
var wrap = function (prefix, content, suffix) {
var result = '';
for (var i = 0; i < content.length; i++) {
result += prefix + content[i] + suffix;
}
return result;
};
/**
*
*/
var loadContent = function (id, script) {
var url = script.getAttribute('data-h5p');
var data, callback = 'H5P' + id;
// Prevent duplicate loading.
script.removeAttribute('data-h5p');
var loadResizer = function (url) {
var data, callback = 'H5POldEmbed';
resizer = true;
// Callback for when content data is loaded.
window[callback] = function (content) {
contents[id] = content;
var iframe = document.createElement('iframe');
var parent = script.parentNode;
parent.insertBefore(iframe, script);
iframe.id = 'h5p-iframe-' + id;
iframe.style.display = 'block';
iframe.style.width = '100%';
iframe.style.height = '1px';
iframe.style.border = 'none';
iframe.style.zIndex = 101;
iframe.style.top = 0;
iframe.style.left = 0;
iframe.className = 'h5p-iframe';
iframe.setAttribute('frameBorder', '0');
iframe.contentDocument.open();
iframe.contentDocument.write('\
<!doctype html><html class="h5p-iframe">\
<head>\
<script>\
var H5PIntegration = window.parent.H5P.getIntegration(' + id + ');\
</script>\
' + wrap('<link rel="stylesheet" href="', content.styles, '">') + '\
' + wrap('<script src="', content.scripts, '"></script>') + '\
</head><body>\
<div class="h5p-content" data-class="' + content.library + '" data-content-id="' + id + '"/>\
</body></html>');
iframe.contentDocument.close();
iframe.contentDocument.documentElement.style.overflow = 'hidden';
// Add resizing script to head
var resizer = document.createElement('script');
resizer.src = content;
head.appendChild(resizer);
// Clean up
parent.removeChild(script);
head.removeChild(data);
delete window[callback];
};
@ -74,183 +32,44 @@ var H5P = H5P || (function () {
head.appendChild(data);
};
/**
* Replaced script tag with iframe
*/
var addIframe = function (script) {
// Add iframe
var iframe = document.createElement('iframe');
iframe.src = script.getAttribute('data-h5p');
iframe.frameBorder = false;
iframe.allowFullscreen = true;
var parent = script.parentNode;
parent.insertBefore(iframe, script);
parent.removeChild(script);
};
/**
* Go throught all script tags with the data-h5p attribute and load content.
*/
function H5P() {
function H5POldEmbed() {
var scripts = document.getElementsByTagName('script');
var h5ps = []; // Use seperate array since scripts grow in size.
for (var i = 0; i < scripts.length; i++) {
var script = scripts[i];
if (script.hasAttribute('data-h5p')) {
if (script.src.indexOf('/h5p-resizer.js') !== -1) {
resizer = true;
}
else if (script.hasAttribute('data-h5p')) {
h5ps.push(script);
}
}
for (i = 0; i < h5ps.length; i++) {
loadContent(contentId, h5ps[i]);
contentId++;
if (!resizer) {
loadResizer(h5ps[i].getAttribute('data-h5p'));
}
};
/**
* Return integration object
*/
H5P.getIntegration = function (id) {
var content = contents[id];
return {
getJsonContent: function () {
return content.params;
},
getContentPath: function () {
return content.path + 'content/' + content.id + '/';
},
getFullscreen: function () {
return content.fullscreen;
},
getLibraryPath: function (library) {
return content.path + 'libraries/' + library;
},
getContentData: function () {
return {
library: content.library,
jsonContent: content.params,
fullScreen: content.fullscreen,
exportUrl: content.exportUrl,
embedCode: content.embedCode
};
},
i18n: content.i18n,
showH5PIconInActionBar: function () {
// Always show H5P-icon when embedding
return true;
}
};
};
// Detect if we support fullscreen, and what prefix to use.
var fullScreenBrowserPrefix, safariBrowser;
if (document.documentElement.requestFullScreen) {
fullScreenBrowserPrefix = '';
}
else if (document.documentElement.webkitRequestFullScreen &&
navigator.userAgent.indexOf('Android') === -1 // Skip Android
) {
safariBrowser = navigator.userAgent.match(/Version\/(\d)/);
safariBrowser = (safariBrowser === null ? 0 : parseInt(safariBrowser[1]));
// Do not allow fullscreen for safari < 7.
if (safariBrowser === 0 || safariBrowser > 6) {
fullScreenBrowserPrefix = 'webkit';
addIframe(h5ps[i]);
}
}
else if (document.documentElement.mozRequestFullScreen) {
fullScreenBrowserPrefix = 'moz';
}
else if (document.documentElement.msRequestFullscreen) {
fullScreenBrowserPrefix = 'ms';
}
/**
* Enter fullscreen mode.
*/
H5P.fullScreen = function ($element, instance, exitCallback, body) {
var iframe = document.getElementById('h5p-iframe-' + $element.parent().data('content-id'));
var $classes = $element.add(body);
var $body = $classes.eq(1);
/**
* Prepare for resize by setting the correct styles.
*
* @param {String} classes CSS
*/
var before = function (classes) {
$classes.addClass(classes);
iframe.style.height = '100%';
};
/**
* Gets called when fullscreen mode has been entered.
* Resizes and sets focus on content.
*/
var entered = function () {
// Do not rely on window resize events.
instance.$.trigger('resize');
instance.$.trigger('focus');
};
/**
* Gets called when fullscreen mode has been exited.
* Resizes and sets focus on content.
*
* @param {String} classes CSS
*/
var done = function (classes) {
H5P.isFullscreen = false;
$classes.removeClass(classes);
// Do not rely on window resize events.
instance.$.trigger('resize');
instance.$.trigger('focus');
if (exitCallback !== undefined) {
exitCallback();
}
};
H5P.isFullscreen = true;
if (fullScreenBrowserPrefix === undefined) {
// Create semi fullscreen.
before('h5p-semi-fullscreen');
iframe.style.position = 'fixed';
var $disable = $element.prepend('<a href="#" class="h5p-disable-fullscreen" title="Disable fullscreen"></a>').children(':first');
var keyup, disableSemiFullscreen = function () {
$disable.remove();
$body.unbind('keyup', keyup);
iframe.style.position = 'static';
done('h5p-semi-fullscreen');
return false;
};
keyup = function (event) {
if (event.keyCode === 27) {
disableSemiFullscreen();
}
};
$disable.click(disableSemiFullscreen);
$body.keyup(keyup); // TODO: Does not work with iframe's $!
entered();
}
else {
// Create real fullscreen.
before('h5p-fullscreen');
var first, eventName = (fullScreenBrowserPrefix === 'ms' ? 'MSFullscreenChange' : fullScreenBrowserPrefix + 'fullscreenchange');
document.addEventListener(eventName, function () {
if (first === undefined) {
// We are entering fullscreen mode
first = false;
entered();
return;
}
// We are exiting fullscreen
done('h5p-fullscreen');
document.removeEventListener(eventName, arguments.callee, false);
});
if (fullScreenBrowserPrefix === '') {
iframe.requestFullScreen();
}
else {
var method = (fullScreenBrowserPrefix === 'ms' ? 'msRequestFullscreen' : fullScreenBrowserPrefix + 'RequestFullScreen');
var params = (fullScreenBrowserPrefix === 'webkit' && safariBrowser === 0 ? Element.ALLOW_KEYBOARD_INPUT : undefined);
iframe[method](params);
}
}
};
return H5P;
return H5POldEmbed;
})();
new H5P();
new H5POldEmbed();

258
js/h5p-event-dispatcher.js Normal file
View File

@ -0,0 +1,258 @@
var H5P = window.H5P = window.H5P || {};
/**
* The Event class for the EventDispatcher.
*
* @class
* @param {string} type
* @param {*} data
* @param {Object} [extras]
* @param {boolean} [extras.bubbles]
* @param {boolean} [extras.external]
*/
H5P.Event = function (type, data, extras) {
this.type = type;
this.data = data;
var bubbles = false;
// Is this an external event?
var external = false;
// Is this event scheduled to be sent externally?
var scheduledForExternal = false;
if (extras === undefined) {
extras = {};
}
if (extras.bubbles === true) {
bubbles = true;
}
if (extras.external === true) {
external = true;
}
/**
* Prevent this event from bubbling up to parent
*/
this.preventBubbling = function () {
bubbles = false;
};
/**
* Get bubbling status
*
* @returns {boolean}
* true if bubbling false otherwise
*/
this.getBubbles = function () {
return bubbles;
};
/**
* Try to schedule an event for externalDispatcher
*
* @returns {boolean}
* true if external and not already scheduled, otherwise false
*/
this.scheduleForExternal = function () {
if (external && !scheduledForExternal) {
scheduledForExternal = true;
return true;
}
return false;
};
};
/**
* Callback type for event listeners.
*
* @callback H5P.EventCallback
* @param {H5P.Event} event
*/
H5P.EventDispatcher = (function () {
/**
* The base of the event system.
* Inherit this class if you want your H5P to dispatch events.
*
* @class
* @memberof H5P
*/
function EventDispatcher() {
var self = this;
/**
* Keep track of listeners for each event.
*
* @private
* @type {Object}
*/
var triggers = {};
/**
* Add new event listener.
*
* @throws {TypeError}
* listener must be a function
* @param {string} type
* Event type
* @param {H5P.EventCallback} listener
* Event listener
* @param {Object} [thisArg]
* Optionally specify the this value when calling listener.
*/
this.on = function (type, listener, thisArg) {
if (typeof listener !== 'function') {
throw TypeError('listener must be a function');
}
// Trigger event before adding to avoid recursion
self.trigger('newListener', {'type': type, 'listener': listener});
var trigger = {'listener': listener, 'thisArg': thisArg};
if (!triggers[type]) {
// First
triggers[type] = [trigger];
}
else {
// Append
triggers[type].push(trigger);
}
};
/**
* Add new event listener that will be fired only once.
*
* @throws {TypeError}
* listener must be a function
* @param {string} type
* Event type
* @param {H5P.EventCallback} listener
* Event listener
* @param {Object} thisArg
* Optionally specify the this value when calling listener.
*/
this.once = function (type, listener, thisArg) {
if (!(listener instanceof Function)) {
throw TypeError('listener must be a function');
}
var once = function (event) {
self.off(event.type, once);
listener.call(this, event);
};
self.on(type, once, thisArg);
};
/**
* Remove event listener.
* If no listener is specified, all listeners will be removed.
*
* @throws {TypeError}
* listener must be a function
* @param {string} type
* Event type
* @param {H5P.EventCallback} listener
* Event listener
*/
this.off = function (type, listener) {
if (listener !== undefined && !(listener instanceof Function)) {
throw TypeError('listener must be a function');
}
if (triggers[type] === undefined) {
return;
}
if (listener === undefined) {
// Remove all listeners
delete triggers[type];
self.trigger('removeListener', type);
return;
}
// Find specific listener
for (var i = 0; i < triggers[type].length; i++) {
if (triggers[type][i].listener === listener) {
triggers[type].splice(i, 1);
self.trigger('removeListener', type, {'listener': listener});
break;
}
}
// Clean up empty arrays
if (!triggers[type].length) {
delete triggers[type];
}
};
/**
* Try to call all event listeners for the given event type.
*
* @private
* @param {string} Event type
*/
var call = function (type, event) {
if (triggers[type] === undefined) {
return;
}
// Clone array (prevents triggers from being modified during the event)
var handlers = triggers[type].slice();
// Call all listeners
for (var i = 0; i < handlers.length; i++) {
var trigger = handlers[i];
var thisArg = (trigger.thisArg ? trigger.thisArg : this);
trigger.listener.call(thisArg, event);
}
};
/**
* Dispatch event.
*
* @param {string|H5P.Event} event
* Event object or event type as string
* @param {*} [eventData]
* Custom event data(used when event type as string is used as first
* argument).
* @param {Object} [extras]
* @param {boolean} [extras.bubbles]
* @param {boolean} [extras.external]
*/
this.trigger = function (event, eventData, extras) {
if (event === undefined) {
return;
}
if (event instanceof String || typeof event === 'string') {
event = new H5P.Event(event, eventData, extras);
}
else if (eventData !== undefined) {
event.data = eventData;
}
// Check to see if this event should go externally after all triggering and bubbling is done
var scheduledForExternal = event.scheduleForExternal();
// Call all listeners
call.call(this, event.type, event);
// Call all * listeners
call.call(this, '*', event);
// Bubble
if (event.getBubbles() && self.parent instanceof H5P.EventDispatcher &&
(self.parent.trigger instanceof Function || typeof self.parent.trigger === 'function')) {
self.parent.trigger(event);
}
if (scheduledForExternal) {
H5P.externalDispatcher.trigger.call(this, event);
}
};
}
return EventDispatcher;
})();

File diff suppressed because one or more lines are too long

54
js/h5p-hub-sharing.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,5 @@
var H5PLibraryDetails= H5PLibraryDetails || {};
/* global H5PAdminIntegration H5PUtils */
var H5PLibraryDetails = H5PLibraryDetails || {};
(function ($) {
@ -7,8 +8,8 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
* Initializing
*/
H5PLibraryDetails.init = function () {
H5PLibraryDetails.$adminContainer = H5PIntegration.getAdminContainer();
H5PLibraryDetails.library = H5PIntegration.getLibraryInfo();
H5PLibraryDetails.$adminContainer = H5P.jQuery(H5PAdminIntegration.containerSelector);
H5PLibraryDetails.library = H5PAdminIntegration.libraryInfo;
// currentContent holds the current list if data (relevant for filtering)
H5PLibraryDetails.currentContent = H5PLibraryDetails.library.content;
@ -68,7 +69,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
*/
H5PLibraryDetails.createContentTable = function () {
// Remove it if it exists:
if(H5PLibraryDetails.$contentTable) {
if (H5PLibraryDetails.$contentTable) {
H5PLibraryDetails.$contentTable.remove();
}
@ -77,10 +78,10 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
var i = (H5PLibraryDetails.currentPage*H5PLibraryDetails.PAGER_SIZE);
var lastIndex = (i+H5PLibraryDetails.PAGER_SIZE);
if(lastIndex > H5PLibraryDetails.currentContent.length) {
if (lastIndex > H5PLibraryDetails.currentContent.length) {
lastIndex = H5PLibraryDetails.currentContent.length;
}
for(; i<lastIndex; i++) {
for (; i<lastIndex; i++) {
var content = H5PLibraryDetails.currentContent[i];
H5PLibraryDetails.$contentTable.append(H5PUtils.createTableRow(['<a href="' + content.url + '">' + content.title + '</a>']));
}
@ -93,15 +94,11 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
* Creates the pager element on the bottom of the list
*/
H5PLibraryDetails.createPagerElement = function () {
// Only create pager if needed:
if(H5PLibraryDetails.currentContent.length > H5PLibraryDetails.PAGER_SIZE) {
H5PLibraryDetails.$previous = $('<button type="button" class="previous h5p-admin"><</button>');
H5PLibraryDetails.$next = $('<button type="button" class="next h5p-admin">></button>');
H5PLibraryDetails.$previous.on('click', function () {
if(H5PLibraryDetails.$previous.hasClass('disabled')) {
if (H5PLibraryDetails.$previous.hasClass('disabled')) {
return;
}
@ -111,7 +108,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
});
H5PLibraryDetails.$next.on('click', function () {
if(H5PLibraryDetails.$next.hasClass('disabled')) {
if (H5PLibraryDetails.$next.hasClass('disabled')) {
return;
}
@ -131,7 +128,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
H5PLibraryDetails.$pagerInfo.hide();
// User has updated the pageNumber
var pageNumerUpdated = function() {
var pageNumerUpdated = function () {
var newPageNum = $gotoInput.val()-1;
var intRegex = /^\d+$/;
@ -139,7 +136,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
H5PLibraryDetails.$pagerInfo.css({display: 'inline-block'});
// Check if input value is valid, and that it has actually changed
if(!(intRegex.test(newPageNum) && newPageNum >= 0 && newPageNum < H5PLibraryDetails.getNumPages() && newPageNum != H5PLibraryDetails.currentPage)) {
if (!(intRegex.test(newPageNum) && newPageNum >= 0 && newPageNum < H5PLibraryDetails.getNumPages() && newPageNum != H5PLibraryDetails.currentPage)) {
return;
}
@ -174,7 +171,6 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
});
H5PLibraryDetails.updatePager();
}
};
/**
@ -190,7 +186,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
H5PLibraryDetails.updatePager = function () {
H5PLibraryDetails.$pagerInfo.css({display: 'inline-block'});
if(H5PLibraryDetails.getNumPages() > 0) {
if (H5PLibraryDetails.getNumPages() > 0) {
var message = H5PUtils.translateReplace(H5PLibraryDetails.library.translations.pageXOfY, {
'$x': (H5PLibraryDetails.currentPage+1),
'$y': H5PLibraryDetails.getNumPages()
@ -216,7 +212,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
var searchString = $('.h5p-content-search > input').val();
// If search string same as previous, just do nothing
if(H5PLibraryDetails.currentFilter === searchString) {
if (H5PLibraryDetails.currentFilter === searchString) {
return;
}
@ -224,7 +220,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
// If empty search, use the complete list
H5PLibraryDetails.currentContent = H5PLibraryDetails.library.content;
}
else if(H5PLibraryDetails.filterCache[searchString]) {
else if (H5PLibraryDetails.filterCache[searchString]) {
// If search is cached, no need to filter
H5PLibraryDetails.currentContent = H5PLibraryDetails.filterCache[searchString];
}
@ -232,10 +228,10 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
var listToFilter = H5PLibraryDetails.library.content;
// Check if we can filter the already filtered results (for performance)
if(searchString.length > 1 && H5PLibraryDetails.currentFilter === searchString.substr(0, H5PLibraryDetails.currentFilter.length)) {
if (searchString.length > 1 && H5PLibraryDetails.currentFilter === searchString.substr(0, H5PLibraryDetails.currentFilter.length)) {
listToFilter = H5PLibraryDetails.currentContent;
}
H5PLibraryDetails.currentContent = $.grep(listToFilter, function(content) {
H5PLibraryDetails.currentContent = $.grep(listToFilter, function (content) {
return content.title && content.title.match(new RegExp(searchString, 'i'));
});
}
@ -261,7 +257,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
$('input', H5PLibraryDetails.$search).on('change keypress paste input', function () {
// Here we start the filtering
// We wait at least 500 ms after last input to perform search
if(inputTimer) {
if (inputTimer) {
clearTimeout(inputTimer);
}

View File

@ -1,4 +1,4 @@
/*jshint multistr: true */
/* global H5PAdminIntegration H5PUtils */
var H5PLibraryList = H5PLibraryList || {};
(function ($) {
@ -7,15 +7,15 @@ var H5PLibraryList = H5PLibraryList || {};
* Initializing
*/
H5PLibraryList.init = function () {
var $adminContainer = H5PIntegration.getAdminContainer();
var $adminContainer = H5P.jQuery(H5PAdminIntegration.containerSelector).html('');
var libraryList = H5PIntegration.getLibraryList();
var libraryList = H5PAdminIntegration.libraryList;
if (libraryList.notCached) {
$adminContainer.append(H5PUtils.getRebuildCache(libraryList.notCached));
}
// Create library list
$adminContainer.append(H5PLibraryList.createLibraryList(H5PIntegration.getLibraryList()));
$adminContainer.append(H5PLibraryList.createLibraryList(H5PAdminIntegration.libraryList));
};
/**
@ -24,8 +24,8 @@ var H5PLibraryList = H5PLibraryList || {};
* @param {object} libraries List of libraries and headers
*/
H5PLibraryList.createLibraryList = function (libraries) {
var t = H5PIntegration.i18n.H5P;
if(libraries.listData === undefined || libraries.listData.length === 0) {
var t = H5PAdminIntegration.l10n;
if (libraries.listData === undefined || libraries.listData.length === 0) {
return $('<div>' + t.NA + '</div>');
}
@ -50,11 +50,11 @@ var H5PLibraryList = H5PLibraryList || {};
text: library.numLibraryDependencies,
class: 'h5p-admin-center'
},
'<div class="h5p-admin-buttons-wrapper">\
<button class="h5p-admin-upgrade-library"></button>\
<button class="h5p-admin-view-library" title="' + t.viewLibrary + '"></button>\
<button class="h5p-admin-delete-library"></button>\
</div>'
'<div class="h5p-admin-buttons-wrapper">' +
'<button class="h5p-admin-upgrade-library"></button>' +
(library.detailsUrl ? '<button class="h5p-admin-view-library" title="' + t.viewLibrary + '"></button>' : '') +
(library.deleteUrl ? '<button class="h5p-admin-delete-library"></button>' : '') +
'</div>'
]);
H5PLibraryList.addRestricted($('.h5p-admin-restricted', $libraryRow), library.restrictedUrl, library.restricted);
@ -78,7 +78,12 @@ var H5PLibraryList = H5PLibraryList || {};
});
var $deleteButton = $('.h5p-admin-delete-library', $libraryRow);
if (libraries.notCached !== undefined || hasContent || (library.numContentDependencies !== '' && library.numContentDependencies !== 0) || (library.numLibraryDependencies !== '' && library.numLibraryDependencies !== 0)) {
if (libraries.notCached !== undefined ||
hasContent ||
(library.numContentDependencies !== '' &&
library.numContentDependencies !== 0) ||
(library.numLibraryDependencies !== '' &&
library.numLibraryDependencies !== 0)) {
// Disabled delete if content.
$deleteButton.attr('disabled', true);
}

131
js/h5p-resizer.js Normal file
View File

@ -0,0 +1,131 @@
// H5P iframe Resizer
(function () {
if (!window.postMessage || !window.addEventListener || window.h5pResizerInitialized) {
return; // Not supported
}
window.h5pResizerInitialized = true;
// Map actions to handlers
var actionHandlers = {};
/**
* Prepare iframe resize.
*
* @private
* @param {Object} iframe Element
* @param {Object} data Payload
* @param {Function} respond Send a response to the iframe
*/
actionHandlers.hello = function (iframe, data, respond) {
// Make iframe responsive
iframe.style.width = '100%';
// Bugfix for Chrome: Force update of iframe width. If this is not done the
// document size may not be updated before the content resizes.
iframe.getBoundingClientRect();
// Tell iframe that it needs to resize when our window resizes
var resize = function () {
if (iframe.contentWindow) {
// Limit resize calls to avoid flickering
respond('resize');
}
else {
// Frame is gone, unregister.
window.removeEventListener('resize', resize);
}
};
window.addEventListener('resize', resize, false);
// Respond to let the iframe know we can resize it
respond('hello');
};
/**
* Prepare iframe resize.
*
* @private
* @param {Object} iframe Element
* @param {Object} data Payload
* @param {Function} respond Send a response to the iframe
*/
actionHandlers.prepareResize = function (iframe, data, respond) {
// Do not resize unless page and scrolling differs
if (iframe.clientHeight !== data.scrollHeight ||
data.scrollHeight !== data.clientHeight) {
// Reset iframe height, in case content has shrinked.
iframe.style.height = data.clientHeight + 'px';
respond('resizePrepared');
}
};
/**
* Resize parent and iframe to desired height.
*
* @private
* @param {Object} iframe Element
* @param {Object} data Payload
* @param {Function} respond Send a response to the iframe
*/
actionHandlers.resize = function (iframe, data) {
// Resize iframe so all content is visible. Use scrollHeight to make sure we get everything
iframe.style.height = data.scrollHeight + 'px';
};
/**
* Keyup event handler. Exits full screen on escape.
*
* @param {Event} event
*/
var escape = function (event) {
if (event.keyCode === 27) {
exitFullScreen();
}
};
// Listen for messages from iframes
window.addEventListener('message', function receiveMessage(event) {
if (event.data.context !== 'h5p') {
return; // Only handle h5p requests.
}
// Find out who sent the message
var iframe, iframes = document.getElementsByTagName('iframe');
for (var i = 0; i < iframes.length; i++) {
if (iframes[i].contentWindow === event.source) {
iframe = iframes[i];
break;
}
}
if (!iframe) {
return; // Cannot find sender
}
// Find action handler handler
if (actionHandlers[event.data.action]) {
actionHandlers[event.data.action](iframe, event.data, function respond(action, data) {
if (data === undefined) {
data = {};
}
data.action = action;
data.context = 'h5p';
event.source.postMessage(data, event.origin);
});
}
}, false);
// Let h5p iframes know we're ready!
var iframes = document.getElementsByTagName('iframe');
var ready = {
context: 'h5p',
action: 'ready'
};
for (var i = 0; i < iframes.length; i++) {
if (iframes[i].src.indexOf('h5p') !== -1) {
iframes[i].contentWindow.postMessage(ready, '*');
}
}
})();

View File

@ -1,3 +1,4 @@
/* global H5PAdminIntegration*/
var H5PUtils = H5PUtils || {};
(function ($) {
@ -7,9 +8,9 @@ var H5PUtils = H5PUtils || {};
* @param {array} headers List of headers
*/
H5PUtils.createTable = function (headers) {
var $table = $('<table class="h5p-admin-table' + (H5PIntegration.extraTableClasses !== undefined ? ' ' + H5PIntegration.extraTableClasses : '') + '"></table>');
var $table = $('<table class="h5p-admin-table' + (H5PAdminIntegration.extraTableClasses !== undefined ? ' ' + H5PAdminIntegration.extraTableClasses : '') + '"></table>');
if(headers) {
if (headers) {
var $thead = $('<thead></thead>');
var $tr = $('<tr></tr>');
@ -182,18 +183,30 @@ var H5PUtils = H5PUtils || {};
if (sortByCol !== undefined && col.sortable === true) {
// Make sortable
options.role = 'button';
options.tabIndex = 1;
options.tabIndex = 0;
// This is the first sortable column, use as default sort
if (sortCol === undefined) {
sortCol = id;
sortDir = 0;
}
// This is the sort column
if (sortCol === id) {
options['class'] = 'h5p-sort';
if (sortDir === 1) {
options['class'] += ' h5p-reverse';
}
}
options.on.click = function () {
sort($th, id);
};
options.on.keypress = function (event) {
if ((event.charCode || event.keyCode) === 32) { // Space
sort($th, id);
}
};
}
}
@ -232,7 +245,10 @@ var H5PUtils = H5PUtils || {};
sortDir = 0;
}
sortByCol(sortCol, sortDir);
sortByCol({
by: sortCol,
dir: sortDir
});
};
/**
@ -244,11 +260,17 @@ var H5PUtils = H5PUtils || {};
* "text" and "sortable". E.g.
* [{text: 'Col 1', sortable: true}, 'Col 2', 'Col 3']
* @param {Function} sort Callback which is runned when sorting changes
* @param {Object} [order]
*/
this.setHeaders = function (cols, sort) {
this.setHeaders = function (cols, sort, order) {
numCols = cols.length;
sortByCol = sort;
if (order) {
sortCol = order.by;
sortDir = order.dir;
}
// Create new head
var $newThead = $('<thead/>');
var $tr = $('<tr/>').appendTo($newThead);
@ -282,6 +304,8 @@ var H5PUtils = H5PUtils || {};
$tbody.replaceWith($newTbody);
$tbody = $newTbody;
return $tbody;
};
/**

40
js/h5p-version.js Normal file
View File

@ -0,0 +1,40 @@
H5P.Version = (function () {
/**
* Make it easy to keep track of version details.
*
* @class
* @namespace H5P
* @param {String} version
*/
function Version(version) {
if (typeof version === 'string') {
// Name version string (used by content upgrade)
var versionSplit = version.split('.', 3);
this.major =+ versionSplit[0];
this.minor =+ versionSplit[1];
}
else {
// Library objects (used by editor)
if (version.localMajorVersion !== undefined) {
this.major =+ version.localMajorVersion;
this.minor =+ version.localMinorVersion;
}
else {
this.major =+ version.majorVersion;
this.minor =+ version.minorVersion;
}
}
/**
* Public. Custom string for this object.
*
* @returns {String}
*/
this.toString = function () {
return version;
};
}
return Version;
})();

331
js/h5p-x-api-event.js Normal file
View File

@ -0,0 +1,331 @@
var H5P = window.H5P = window.H5P || {};
/**
* Used for xAPI events.
*
* @class
* @extends H5P.Event
*/
H5P.XAPIEvent = function () {
H5P.Event.call(this, 'xAPI', {'statement': {}}, {bubbles: true, external: true});
};
H5P.XAPIEvent.prototype = Object.create(H5P.Event.prototype);
H5P.XAPIEvent.prototype.constructor = H5P.XAPIEvent;
/**
* Set scored result statements.
*
* @param {number} score
* @param {number} maxScore
* @param {object} instance
* @param {boolean} completion
* @param {boolean} success
*/
H5P.XAPIEvent.prototype.setScoredResult = function (score, maxScore, instance, completion, success) {
this.data.statement.result = {};
if (typeof score !== 'undefined') {
if (typeof maxScore === 'undefined') {
this.data.statement.result.score = {'raw': score};
}
else {
this.data.statement.result.score = {
'min': 0,
'max': maxScore,
'raw': score
};
if (maxScore > 0) {
this.data.statement.result.score.scaled = Math.round(score / maxScore * 10000) / 10000;
}
}
}
if (typeof completion === 'undefined') {
this.data.statement.result.completion = (this.getVerb() === 'completed' || this.getVerb() === 'answered');
}
else {
this.data.statement.result.completion = completion;
}
if (typeof success !== 'undefined') {
this.data.statement.result.success = success;
}
if (instance && instance.activityStartTime) {
var duration = Math.round((Date.now() - instance.activityStartTime ) / 10) / 100;
// xAPI spec allows a precision of 0.01 seconds
this.data.statement.result.duration = 'PT' + duration + 'S';
}
};
/**
* Set a verb.
*
* @param {string} verb
* Verb in short form, one of the verbs defined at
* {@link http://adlnet.gov/expapi/verbs/|ADL xAPI Vocabulary}
*
*/
H5P.XAPIEvent.prototype.setVerb = function (verb) {
if (H5P.jQuery.inArray(verb, H5P.XAPIEvent.allowedXAPIVerbs) !== -1) {
this.data.statement.verb = {
'id': 'http://adlnet.gov/expapi/verbs/' + verb,
'display': {
'en-US': verb
}
};
}
else if (verb.id !== undefined) {
this.data.statement.verb = verb;
}
};
/**
* Get the statements verb id.
*
* @param {boolean} full
* if true the full verb id prefixed by http://adlnet.gov/expapi/verbs/
* will be returned
* @returns {string}
* Verb or null if no verb with an id has been defined
*/
H5P.XAPIEvent.prototype.getVerb = function (full) {
var statement = this.data.statement;
if ('verb' in statement) {
if (full === true) {
return statement.verb;
}
return statement.verb.id.slice(31);
}
else {
return null;
}
};
/**
* Set the object part of the statement.
*
* The id is found automatically (the url to the content)
*
* @param {Object} instance
* The H5P instance
*/
H5P.XAPIEvent.prototype.setObject = function (instance) {
if (instance.contentId) {
this.data.statement.object = {
'id': this.getContentXAPIId(instance),
'objectType': 'Activity',
'definition': {
'extensions': {
'http://h5p.org/x-api/h5p-local-content-id': instance.contentId
}
}
};
if (instance.subContentId) {
this.data.statement.object.definition.extensions['http://h5p.org/x-api/h5p-subContentId'] = instance.subContentId;
// Don't set titles on main content, title should come from publishing platform
if (typeof instance.getTitle === 'function') {
this.data.statement.object.definition.name = {
"en-US": instance.getTitle()
};
}
}
else {
var content = H5P.getContentForInstance(instance.contentId);
if (content && content.metadata && content.metadata.title) {
this.data.statement.object.definition.name = {
"en-US": H5P.createTitle(content.metadata.title)
};
}
}
}
else {
// Content types view always expect to have a contentId when they are displayed.
// This is not the case if they are displayed in the editor as part of a preview.
// The fix is to set an empty object with definition for the xAPI event, so all
// the content types that rely on this does not have to handle it. This means
// that content types that are being previewed will send xAPI completed events,
// but since there are no scripts that catch these events in the editor,
// this is not a problem.
this.data.statement.object = {
definition: {}
};
}
};
/**
* Set the context part of the statement.
*
* @param {Object} instance
* The H5P instance
*/
H5P.XAPIEvent.prototype.setContext = function (instance) {
if (instance.parent && (instance.parent.contentId || instance.parent.subContentId)) {
this.data.statement.context = {
"contextActivities": {
"parent": [
{
"id": this.getContentXAPIId(instance.parent),
"objectType": "Activity"
}
]
}
};
}
if (instance.libraryInfo) {
if (this.data.statement.context === undefined) {
this.data.statement.context = {"contextActivities":{}};
}
this.data.statement.context.contextActivities.category = [
{
"id": "http://h5p.org/libraries/" + instance.libraryInfo.versionedNameNoSpaces,
"objectType": "Activity"
}
];
}
};
/**
* Set the actor. Email and name will be added automatically.
*/
H5P.XAPIEvent.prototype.setActor = function () {
if (H5PIntegration.user !== undefined) {
this.data.statement.actor = {
'name': H5PIntegration.user.name,
'mbox': 'mailto:' + H5PIntegration.user.mail,
'objectType': 'Agent'
};
}
else {
var uuid;
try {
if (localStorage.H5PUserUUID) {
uuid = localStorage.H5PUserUUID;
}
else {
uuid = H5P.createUUID();
localStorage.H5PUserUUID = uuid;
}
}
catch (err) {
// LocalStorage and Cookies are probably disabled. Do not track the user.
uuid = 'not-trackable-' + H5P.createUUID();
}
this.data.statement.actor = {
'account': {
'name': uuid,
'homePage': H5PIntegration.siteUrl
},
'objectType': 'Agent'
};
}
};
/**
* Get the max value of the result - score part of the statement
*
* @returns {number}
* The max score, or null if not defined
*/
H5P.XAPIEvent.prototype.getMaxScore = function () {
return this.getVerifiedStatementValue(['result', 'score', 'max']);
};
/**
* Get the raw value of the result - score part of the statement
*
* @returns {number}
* The score, or null if not defined
*/
H5P.XAPIEvent.prototype.getScore = function () {
return this.getVerifiedStatementValue(['result', 'score', 'raw']);
};
/**
* Get content xAPI ID.
*
* @param {Object} instance
* The H5P instance
*/
H5P.XAPIEvent.prototype.getContentXAPIId = function (instance) {
var xAPIId;
if (instance.contentId && H5PIntegration && H5PIntegration.contents && H5PIntegration.contents['cid-' + instance.contentId]) {
xAPIId = H5PIntegration.contents['cid-' + instance.contentId].url;
if (instance.subContentId) {
xAPIId += '?subContentId=' + instance.subContentId;
}
}
return xAPIId;
};
/**
* Check if this event is sent from a child (i.e not from grandchild)
*
* @return {Boolean}
*/
H5P.XAPIEvent.prototype.isFromChild = function () {
var parentId = this.getVerifiedStatementValue(['context', 'contextActivities', 'parent', 0, 'id']);
return !parentId || parentId.indexOf('subContentId') === -1;
};
/**
* Figure out if a property exists in the statement and return it
*
* @param {string[]} keys
* List describing the property we're looking for. For instance
* ['result', 'score', 'raw'] for result.score.raw
* @returns {*}
* The value of the property if it is set, null otherwise.
*/
H5P.XAPIEvent.prototype.getVerifiedStatementValue = function (keys) {
var val = this.data.statement;
for (var i = 0; i < keys.length; i++) {
if (val[keys[i]] === undefined) {
return null;
}
val = val[keys[i]];
}
return val;
};
/**
* List of verbs defined at {@link http://adlnet.gov/expapi/verbs/|ADL xAPI Vocabulary}
*
* @type Array
*/
H5P.XAPIEvent.allowedXAPIVerbs = [
'answered',
'asked',
'attempted',
'attended',
'commented',
'completed',
'exited',
'experienced',
'failed',
'imported',
'initialized',
'interacted',
'launched',
'mastered',
'passed',
'preferred',
'progressed',
'registered',
'responded',
'resumed',
'scored',
'shared',
'suspended',
'terminated',
'voided',
// Custom verbs used for action toolbar below content
'downloaded',
'copied',
'accessed-reuse',
'accessed-embed',
'accessed-copyright'
];

119
js/h5p-x-api.js Normal file
View File

@ -0,0 +1,119 @@
var H5P = window.H5P = window.H5P || {};
/**
* The external event dispatcher. Others, outside of H5P may register and
* listen for H5P Events here.
*
* @type {H5P.EventDispatcher}
*/
H5P.externalDispatcher = new H5P.EventDispatcher();
// EventDispatcher extensions
/**
* Helper function for triggering xAPI added to the EventDispatcher.
*
* @param {string} verb
* The short id of the verb we want to trigger
* @param {Oject} [extra]
* Extra properties for the xAPI statement
*/
H5P.EventDispatcher.prototype.triggerXAPI = function (verb, extra) {
this.trigger(this.createXAPIEventTemplate(verb, extra));
};
/**
* Helper function to create event templates added to the EventDispatcher.
*
* Will in the future be used to add representations of the questions to the
* statements.
*
* @param {string} verb
* Verb id in short form
* @param {Object} [extra]
* Extra values to be added to the statement
* @returns {H5P.XAPIEvent}
* Instance
*/
H5P.EventDispatcher.prototype.createXAPIEventTemplate = function (verb, extra) {
var event = new H5P.XAPIEvent();
event.setActor();
event.setVerb(verb);
if (extra !== undefined) {
for (var i in extra) {
event.data.statement[i] = extra[i];
}
}
if (!('object' in event.data.statement)) {
event.setObject(this);
}
if (!('context' in event.data.statement)) {
event.setContext(this);
}
return event;
};
/**
* Helper function to create xAPI completed events
*
* DEPRECATED - USE triggerXAPIScored instead
*
* @deprecated
* since 1.5, use triggerXAPIScored instead.
* @param {number} score
* Will be set as the 'raw' value of the score object
* @param {number} maxScore
* will be set as the "max" value of the score object
* @param {boolean} success
* will be set as the "success" value of the result object
*/
H5P.EventDispatcher.prototype.triggerXAPICompleted = function (score, maxScore, success) {
this.triggerXAPIScored(score, maxScore, 'completed', true, success);
};
/**
* Helper function to create scored xAPI events
*
* @param {number} score
* Will be set as the 'raw' value of the score object
* @param {number} maxScore
* Will be set as the "max" value of the score object
* @param {string} verb
* Short form of adl verb
* @param {boolean} completion
* Is this a statement from a completed activity?
* @param {boolean} success
* Is this a statement from an activity that was done successfully?
*/
H5P.EventDispatcher.prototype.triggerXAPIScored = function (score, maxScore, verb, completion, success) {
var event = this.createXAPIEventTemplate(verb);
event.setScoredResult(score, maxScore, this, completion, success);
this.trigger(event);
};
H5P.EventDispatcher.prototype.setActivityStarted = function () {
if (this.activityStartTime === undefined) {
// Don't trigger xAPI events in the editor
if (this.contentId !== undefined &&
H5PIntegration.contents !== undefined &&
H5PIntegration.contents['cid-' + this.contentId] !== undefined) {
this.triggerXAPI('attempted');
}
this.activityStartTime = Date.now();
}
};
/**
* Internal H5P function listening for xAPI completed events and stores scores
*
* @param {H5P.XAPIEvent} event
*/
H5P.xAPICompletedListener = function (event) {
if ((event.getVerb() === 'completed' || event.getVerb() === 'answered') && !event.getVerifiedStatementValue(['context', 'contextActivities', 'parent'])) {
var score = event.getScore();
var maxScore = event.getMaxScore();
var contentId = event.getVerifiedStatementValue(['object', 'definition', 'extensions', 'http://h5p.org/x-api/h5p-local-content-id']);
H5P.setFinished(contentId, score, maxScore);
}
};

2295
js/h5p.js

File diff suppressed because it is too large Load Diff

29
js/jquery.js vendored

File diff suppressed because one or more lines are too long

436
js/request-queue.js Normal file
View File

@ -0,0 +1,436 @@
/**
* Queue requests and handle them at your convenience
*
* @type {RequestQueue}
*/
H5P.RequestQueue = (function ($, EventDispatcher) {
/**
* A queue for requests, will be automatically processed when regaining connection
*
* @param {boolean} [options.showToast] Show toast when losing or regaining connection
* @constructor
*/
const RequestQueue = function (options) {
EventDispatcher.call(this);
this.processingQueue = false;
options = options || {};
this.showToast = options.showToast;
this.itemName = 'requestQueue';
};
/**
* Add request to queue. Only supports posts currently.
*
* @param {string} url
* @param {Object} data
* @returns {boolean}
*/
RequestQueue.prototype.add = function (url, data) {
if (!window.localStorage) {
return false;
}
let storedStatements = this.getStoredRequests();
if (!storedStatements) {
storedStatements = [];
}
storedStatements.push({
url: url,
data: data,
});
window.localStorage.setItem(this.itemName, JSON.stringify(storedStatements));
this.trigger('requestQueued', {
storedStatements: storedStatements,
processingQueue: this.processingQueue,
});
return true;
};
/**
* Get stored requests
*
* @returns {boolean|Array} Stored requests
*/
RequestQueue.prototype.getStoredRequests = function () {
if (!window.localStorage) {
return false;
}
const item = window.localStorage.getItem(this.itemName);
if (!item) {
return [];
}
return JSON.parse(item);
};
/**
* Clear stored requests
*
* @returns {boolean} True if the storage was successfully cleared
*/
RequestQueue.prototype.clearQueue = function () {
if (!window.localStorage) {
return false;
}
window.localStorage.removeItem(this.itemName);
return true;
};
/**
* Start processing of requests queue
*
* @return {boolean} Returns false if it was not possible to resume processing queue
*/
RequestQueue.prototype.resumeQueue = function () {
// Not supported
if (!H5PIntegration || !window.navigator || !window.localStorage) {
return false;
}
// Already processing
if (this.processingQueue) {
return false;
}
// Attempt to send queued requests
const queue = this.getStoredRequests();
const queueLength = queue.length;
// Clear storage, failed requests will be re-added
this.clearQueue();
// No items left in queue
if (!queueLength) {
this.trigger('emptiedQueue', queue);
return true;
}
// Make sure requests are not changed while they're being handled
this.processingQueue = true;
// Process queue in original order
this.processQueue(queue);
return true
};
/**
* Process first item in the request queue
*
* @param {Array} queue Request queue
*/
RequestQueue.prototype.processQueue = function (queue) {
if (!queue.length) {
return;
}
this.trigger('processingQueue');
// Make sure the requests are processed in a FIFO order
const request = queue.shift();
const self = this;
$.post(request.url, request.data)
.fail(self.onQueuedRequestFail.bind(self, request))
.always(self.onQueuedRequestProcessed.bind(self, queue))
};
/**
* Request fail handler
*
* @param {Object} request
*/
RequestQueue.prototype.onQueuedRequestFail = function (request) {
// Queue the failed request again if we're offline
if (!window.navigator.onLine) {
this.add(request.url, request.data);
}
};
/**
* An item in the queue was processed
*
* @param {Array} queue Queue that was processed
*/
RequestQueue.prototype.onQueuedRequestProcessed = function (queue) {
if (queue.length) {
this.processQueue(queue);
return;
}
// Finished processing this queue
this.processingQueue = false;
// Run empty queue callback with next request queue
const requestQueue = this.getStoredRequests();
this.trigger('queueEmptied', requestQueue);
};
/**
* Display toast message on the first content of current page
*
* @param {string} msg Message to display
* @param {boolean} [forceShow] Force override showing the toast
* @param {Object} [configOverride] Override toast message config
*/
RequestQueue.prototype.displayToastMessage = function (msg, forceShow, configOverride) {
if (!this.showToast && !forceShow) {
return;
}
const config = H5P.jQuery.extend(true, {}, {
position: {
horizontal : 'centered',
vertical: 'centered',
noOverflowX: true,
}
}, configOverride);
H5P.attachToastTo(H5P.jQuery('.h5p-content:first')[0], msg, config);
};
return RequestQueue;
})(H5P.jQuery, H5P.EventDispatcher);
/**
* Request queue for retrying failing requests, will automatically retry them when you come online
*
* @type {offlineRequestQueue}
*/
H5P.OfflineRequestQueue = (function (RequestQueue, Dialog) {
/**
* Constructor
*
* @param {Object} [options] Options for offline request queue
* @param {Object} [options.instance] The H5P instance which UI components are placed within
*/
const offlineRequestQueue = function (options) {
const requestQueue = new RequestQueue();
// We could handle requests from previous pages here, but instead we throw them away
requestQueue.clearQueue();
let startTime = null;
const retryIntervals = [10, 20, 40, 60, 120, 300, 600];
let intervalIndex = -1;
let currentInterval = null;
let isAttached = false;
let isShowing = false;
let isLoading = false;
const instance = options.instance;
const offlineDialog = new Dialog({
headerText: H5P.t('offlineDialogHeader'),
dialogText: H5P.t('offlineDialogBody'),
confirmText: H5P.t('offlineDialogRetryButtonLabel'),
hideCancel: true,
hideExit: true,
classes: ['offline'],
instance: instance,
skipRestoreFocus: true,
});
const dialog = offlineDialog.getElement();
// Add retry text to body
const countDownText = document.createElement('div');
countDownText.classList.add('count-down');
countDownText.innerHTML = H5P.t('offlineDialogRetryMessage')
.replace(':num', '<span class="count-down-num">0</span>');
dialog.querySelector('.h5p-confirmation-dialog-text').appendChild(countDownText);
const countDownNum = countDownText.querySelector('.count-down-num');
// Create throbber
const throbberWrapper = document.createElement('div');
throbberWrapper.classList.add('throbber-wrapper');
const throbber = document.createElement('div');
throbber.classList.add('sending-requests-throbber');
throbberWrapper.appendChild(throbber);
requestQueue.on('requestQueued', function (e) {
// Already processing queue, wait until queue has finished processing before showing dialog
if (e.data && e.data.processingQueue) {
return;
}
if (!isAttached) {
const rootContent = document.body.querySelector('.h5p-content');
if (!rootContent) {
return;
}
offlineDialog.appendTo(rootContent);
rootContent.appendChild(throbberWrapper);
isAttached = true;
}
startCountDown();
}.bind(this));
requestQueue.on('queueEmptied', function (e) {
if (e.data && e.data.length) {
// New requests were added while processing queue or requests failed again. Re-queue requests.
startCountDown(true);
return;
}
// Successfully emptied queue
clearInterval(currentInterval);
toggleThrobber(false);
intervalIndex = -1;
if (isShowing) {
offlineDialog.hide();
isShowing = false;
}
requestQueue.displayToastMessage(
H5P.t('offlineSuccessfulSubmit'),
true,
{
position: {
vertical: 'top',
offsetVertical: '100',
}
}
);
}.bind(this));
offlineDialog.on('confirmed', function () {
// Show dialog on next render in case it is being hidden by the 'confirm' button
isShowing = false;
setTimeout(function () {
retryRequests();
}, 100);
}.bind(this));
// Initialize listener for when requests are added to queue
window.addEventListener('online', function () {
retryRequests();
}.bind(this));
// Listen for queued requests outside the iframe
window.addEventListener('message', function (event) {
const isValidQueueEvent = window.parent === event.source
&& event.data.context === 'h5p'
&& event.data.action === 'queueRequest';
if (!isValidQueueEvent) {
return;
}
this.add(event.data.url, event.data.data);
}.bind(this));
/**
* Toggle throbber visibility
*
* @param {boolean} [forceShow] Will force throbber visibility if set
*/
const toggleThrobber = function (forceShow) {
isLoading = !isLoading;
if (forceShow !== undefined) {
isLoading = forceShow;
}
if (isLoading && isShowing) {
offlineDialog.hide();
isShowing = false;
}
if (isLoading) {
throbberWrapper.classList.add('show');
}
else {
throbberWrapper.classList.remove('show');
}
};
/**
* Retries the failed requests
*/
const retryRequests = function () {
clearInterval(currentInterval);
toggleThrobber(true);
requestQueue.resumeQueue();
};
/**
* Increments retry interval
*/
const incrementRetryInterval = function () {
intervalIndex += 1;
if (intervalIndex >= retryIntervals.length) {
intervalIndex = retryIntervals.length - 1;
}
};
/**
* Starts counting down to retrying queued requests.
*
* @param forceDelayedShow
*/
const startCountDown = function (forceDelayedShow) {
// Already showing, wait for retry
if (isShowing) {
return;
}
toggleThrobber(false);
if (!isShowing) {
if (forceDelayedShow) {
// Must force delayed show since dialog may be hiding, and confirmation dialog does not
// support this.
setTimeout(function () {
offlineDialog.show(0);
}, 100);
}
else {
offlineDialog.show(0);
}
}
isShowing = true;
startTime = new Date().getTime();
incrementRetryInterval();
clearInterval(currentInterval);
currentInterval = setInterval(updateCountDown, 100);
};
/**
* Updates the count down timer. Retries requests when time expires.
*/
const updateCountDown = function () {
const time = new Date().getTime();
const timeElapsed = Math.floor((time - startTime) / 1000);
const timeLeft = retryIntervals[intervalIndex] - timeElapsed;
countDownNum.textContent = timeLeft.toString();
// Retry interval reached, retry requests
if (timeLeft <= 0) {
retryRequests();
}
};
/**
* Add request to offline request queue. Only supports posts for now.
*
* @param {string} url The request url
* @param {Object} data The request data
*/
this.add = function (url, data) {
// Only queue request if it failed because we are offline
if (window.navigator.onLine) {
return false;
}
requestQueue.add(url, data);
};
};
return offlineRequestQueue;
})(H5P.RequestQueue, H5P.ConfirmationDialog);

View File

@ -0,0 +1,68 @@
/* global H5PDisableHubData */
/**
* Global data for disable hub functionality
*
* @typedef {object} H5PDisableHubData Data passed in from the backend
*
* @property {string} selector Selector for the disable hub check-button
* @property {string} overlaySelector Selector for the element that the confirmation dialog will mask
* @property {Array} errors Errors found with the current server setup
*
* @property {string} header Header of the confirmation dialog
* @property {string} confirmationDialogMsg Body of the confirmation dialog
* @property {string} cancelLabel Cancel label of the confirmation dialog
* @property {string} confirmLabel Confirm button label of the confirmation dialog
*
*/
/**
* Utility that makes it possible to force the user to confirm that he really
* wants to use the H5P hub without proper server settings.
*/
(function ($) {
$(document).on('ready', function () {
// No data found
if (!H5PDisableHubData) {
return;
}
// No errors found, no need for confirmation dialog
if (!H5PDisableHubData.errors || !H5PDisableHubData.errors.length) {
return;
}
H5PDisableHubData.selector = H5PDisableHubData.selector ||
'.h5p-settings-disable-hub-checkbox';
H5PDisableHubData.overlaySelector = H5PDisableHubData.overlaySelector ||
'.h5p-settings-container';
var dialogHtml = '<div>' +
'<p>' + H5PDisableHubData.errors.join('</p><p>') + '</p>' +
'<p>' + H5PDisableHubData.confirmationDialogMsg + '</p>';
// Create confirmation dialog, make sure to include translations
var confirmationDialog = new H5P.ConfirmationDialog({
headerText: H5PDisableHubData.header,
dialogText: dialogHtml,
cancelText: H5PDisableHubData.cancelLabel,
confirmText: H5PDisableHubData.confirmLabel
}).appendTo($(H5PDisableHubData.overlaySelector).get(0));
confirmationDialog.on('confirmed', function () {
enableButton.get(0).checked = true;
});
confirmationDialog.on('canceled', function () {
enableButton.get(0).checked = false;
});
var enableButton = $(H5PDisableHubData.selector);
enableButton.change(function () {
if ($(this).is(':checked')) {
confirmationDialog.show(enableButton.offset().top);
}
});
});
})(H5P.jQuery);

View File

@ -1,143 +0,0 @@
[
{
"machineName": "H5P.CoursePresentation",
"downloadUrl": "http://h5p.org/presentation",
"minimumVersions": [
{
"major": 1,
"minor": 0,
"patch": 64
},
{
"major": 1,
"minor": 1,
"patch": 10
}
]
},
{
"machineName": "H5P.Blanks",
"downloadUrl": "http://h5p.org/fill-in-the-blanks",
"minimumVersions": [
{
"major": 1,
"minor": 0,
"patch": 65
}
]
},
{
"machineName": "H5P.Dialogcards",
"downloadUrl": "http://h5p.org/dialog-cards",
"minimumVersions": [
{
"major": 1,
"minor": 0,
"patch": 28
}
]
},
{
"machineName": "H5P.DragQuestion",
"downloadUrl": "http://h5p.org/drag-and-drop",
"minimumVersions": [
{
"major": 1,
"minor": 0,
"patch": 61
}
]
},
{
"machineName": "H5P.InteractiveVideo",
"downloadUrl": "http://h5p.org/interactive-video",
"minimumVersions": [
{
"major": 1,
"minor": 0,
"patch": 31
},
{
"major": 1,
"minor": 1,
"patch": 10
},
{
"major": 1,
"minor": 2,
"patch": 10
}
]
},
{
"machineName": "H5P.Flashcards",
"downloadUrl": "http://h5p.org/flashcards",
"minimumVersions": [
{
"major": 1,
"minor": 0,
"patch": 37
}
]
},
{
"machineName": "H5P.ImageHotspots",
"downloadUrl": "http://h5p.org/image-hotspots",
"minimumVersions": [
{
"major": 1,
"minor": 0,
"patch": 5
}
]
},
{
"machineName": "H5P.JoubelUI",
"downloadUrl": "http://h5p.org/fill-in-the-blanks",
"minimumVersions": [
{
"major": 1,
"minor": 0,
"patch": 6
}
]
},
{
"machineName": "H5P.MultiChoice",
"downloadUrl": "http://h5p.org/multichoice",
"minimumVersions": [
{
"major": 1,
"minor": 0,
"patch": 51
}
]
},
{
"machineName": "H5P.QuestionSet",
"downloadUrl": "http://h5p.org/question-set",
"minimumVersions": [
{
"major": 1,
"minor": 0,
"patch": 53
}
]
},
{
"machineName": "H5P.Summary",
"downloadUrl": "http://h5p.org/summary",
"minimumVersions": [
{
"major": 1,
"minor": 0,
"patch": 38
},
{
"major": 1,
"minor": 1,
"patch": 4
}
]
}
]

View File

@ -9,6 +9,7 @@
.h5p-admin-table,
.h5p-admin-table > tbody {
border: none;
width: 100%;
}
.h5p-admin-table tr:nth-child(odd),
@ -203,7 +204,7 @@ button.h5p-admin.disabled:hover {
line-height: 130%;
border: none;
background: none;
font-family: 'H5P'; /* TODO: Find content */
font-family: 'H5P';
font-size: 1.4em;
}
.h5p-content-pager > button:focus {
@ -231,7 +232,8 @@ button.h5p-admin.disabled:hover {
.h5p-admin-header {
margin-top: 1.5em;
}
#h5p-library-upload-form.h5p-admin-upload-libraries-form {
#h5p-library-upload-form.h5p-admin-upload-libraries-form,
#h5p-content-type-cache-update-form.h5p-admin-upload-libraries-form {
position: relative;
margin: 0;
@ -257,11 +259,27 @@ button.h5p-admin.disabled:hover {
}
.h5p-data-view input[type="text"] {
margin-bottom: 0.5em;
margin-right: 0.5em;
float: left;
}
.h5p-data-view input[type="text"]::-ms-clear {
display: none;
}
.h5p-data-view .h5p-others-contents-toggler-wrapper {
float: right;
line-height: 2;
margin-right: 0.5em;
}
.h5p-data-view .h5p-others-contents-toggler-label {
font-size: 14px;
}
.h5p-data-view .h5p-others-contents-toggler {
margin-right: 0.5em;
}
.h5p-data-view th[role="button"] {
cursor: pointer;
}
@ -283,3 +301,58 @@ button.h5p-admin.disabled:hover {
.h5p-data-view th[role="button"].h5p-sort:hover:after {
color: #999;
}
.h5p-data-view .h5p-facet {
cursor: pointer;
color: #0073aa;
outline: none;
}
.h5p-data-view .h5p-facet:hover,
.h5p-data-view .h5p-facet:active {
color: #00a0d2;
}
.h5p-data-view .h5p-facet:focus {
color: #124964;
box-shadow: 0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8);
}
.h5p-data-view .h5p-facet-wrapper {
line-height: 23px;
}
.h5p-data-view .h5p-facet-tag {
margin: 2px 0 0 0.5em;
font-size: 12px;
background: #e8e8e8;
border: 1px solid #cbcbcc;
border-radius: 5px;
color: #5d5d5d;
padding: 0 24px 0 10px;
display: inline-block;
position: relative;
}
.h5p-data-view .h5p-facet-tag > span {
position: absolute;
right: 0;
top: auto;
bottom: auto;
font-size: 18px;
color: #a2a2a2;
outline: none;
width: 21px;
text-indent: 4px;
letter-spacing: 10px;
overflow: hidden;
cursor: pointer;
}
.h5p-data-view .h5p-facet-tag > span:before {
content: "×";
font-weight: bold;
}
.h5p-data-view .h5p-facet-tag > span:hover,
.h5p-data-view .h5p-facet-tag > span:focus {
color: #a20000;
}
.h5p-data-view .h5p-facet-tag > span:active {
color: #d20000;
}
.content-upgrade-log {
color: red;
}

View File

@ -0,0 +1,183 @@
.h5p-confirmation-dialog-background {
position: fixed;
height: 100%;
width: 100%;
left: 0;
top: 0;
background: rgba(44, 44, 44, 0.9);
opacity: 1;
visibility: visible;
-webkit-transition: opacity 0.1s, linear 0s, visibility 0s linear 0s;
transition: opacity 0.1s linear 0s, visibility 0s linear 0s;
z-index: 201;
}
.h5p-confirmation-dialog-background.hidden {
display: none;
}
.h5p-confirmation-dialog-background.hiding {
opacity: 0;
visibility: hidden;
-webkit-transition: opacity 0.1s, linear 0s, visibility 0s linear 0.1s;
transition: opacity 0.1s linear 0s, visibility 0s linear 0.1s;
}
.h5p-confirmation-dialog-popup:focus {
outline: none;
}
.h5p-confirmation-dialog-popup {
position: absolute;
display: flex;
flex-direction: column;
justify-content: center;
box-sizing: border-box;
max-width: 35em;
min-width: 25em;
top: 2em;
left: 50%;
-webkit-transform: translate(-50%, 0%);
-ms-transform: translate(-50%, 0%);
transform: translate(-50%, 0%);
color: #555;
box-shadow: 0 0 6px 6px rgba(10,10,10,0.3);
-webkit-transition: transform 0.1s ease-in;
transition: transform 0.1s ease-in;
}
.h5p-confirmation-dialog-popup.hidden {
-webkit-transform: translate(-50%, 50%);
-ms-transform: translate(-50%, 50%);
transform: translate(-50%, 50%);
}
.h5p-confirmation-dialog-header {
padding: 1.5em;
background: #fff;
color: #356593;
}
.h5p-confirmation-dialog-header-text {
font-size: 1.25em;
}
.h5p-confirmation-dialog-body {
background: #fafbfc;
border-top: solid 1px #dde0e9;
padding: 1.25em 1.5em;
}
.h5p-confirmation-dialog-text {
margin-bottom: 1.5em;
}
.h5p-confirmation-dialog-buttons {
float: right;
}
button.h5p-confirmation-dialog-exit:visited,
button.h5p-confirmation-dialog-exit:link,
button.h5p-confirmation-dialog-exit {
position: absolute;
background: none;
border: none;
font-size: 2.5em;
top: -0.9em;
right: -1.15em;
color: #fff;
cursor: pointer;
text-decoration: none;
}
button.h5p-confirmation-dialog-exit:focus,
button.h5p-confirmation-dialog-exit:hover {
color: #E4ECF5;
}
.h5p-confirmation-dialog-exit:before {
font-family: "H5P";
content: "\e890";
}
.h5p-core-button.h5p-confirmation-dialog-confirm-button {
padding-left: 0.75em;
margin-bottom: 0;
}
.h5p-core-button.h5p-confirmation-dialog-confirm-button:before {
content: "\e601";
margin-top: -6px;
display: inline-block;
}
.h5p-confirmation-dialog-popup.offline .h5p-confirmation-dialog-buttons {
float: none;
text-align: center;
}
.h5p-confirmation-dialog-popup.offline .count-down {
font-family: Arial;
margin-top: 0.15em;
color: #000;
}
.h5p-confirmation-dialog-popup.offline .h5p-confirmation-dialog-confirm-button:before {
content: "\e90b";
font-weight: normal;
vertical-align: text-bottom;
}
.throbber-wrapper {
display: none;
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
z-index: 1;
background: rgba(44, 44, 44, 0.9);
}
.throbber-wrapper.show {
display: block;
}
.throbber-wrapper .throbber-container {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.throbber-wrapper .sending-requests-throbber{
position: absolute;
top: 7em;
left: 50%;
transform: translateX(-50%);
}
.throbber-wrapper .sending-requests-throbber:before {
display: block;
font-family: 'H5P';
content: "\e90b";
color: white;
font-size: 10em;
animation: request-throbber 1.5s infinite linear;
}
@keyframes request-throbber {
from {
transform: rotate(0);
}
to {
transform: rotate(359deg);
}
}

View File

@ -0,0 +1,60 @@
button.h5p-core-button:visited,
button.h5p-core-button:link,
button.h5p-core-button {
font-family: "Open Sans", sans-serif;
font-weight: 600;
font-size: 1em;
line-height: 1.2;
padding: 0.5em 1.25em;
border-radius: 2em;
background: #2579c6;
color: #fff;
cursor: pointer;
border: none;
box-shadow: none;
outline: none;
display: inline-block;
text-align: center;
text-shadow: none;
vertical-align: baseline;
text-decoration: none;
-webkit-transition: initial;
transition: initial;
}
button.h5p-core-button:focus {
background: #1f67a8;
}
button.h5p-core-button:hover {
background: rgba(31, 103, 168, 0.83);
}
button.h5p-core-button:active {
background: #104888;
}
button.h5p-core-button:before {
font-family: 'H5P';
padding-right: 0.15em;
font-size: 1.5em;
vertical-align: middle;
line-height: 0.7;
}
button.h5p-core-cancel-button:visited,
button.h5p-core-cancel-button:link,
button.h5p-core-cancel-button {
border: none;
background: none;
color: #a00;
margin-right: 1em;
font-size: 1em;
text-decoration: none;
cursor: pointer;
}
button.h5p-core-cancel-button:hover,
button.h5p-core-cancel-button:focus {
background: none;
border: none;
color: #e40000;
}

File diff suppressed because one or more lines are too long

401
styles/h5p-hub-sharing.css Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long