Compare commits

...

217 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
thomasmars 579ba96b49 HFP-1942 Add crossorigin api call.
Update minor version of core since interface changes
2018-07-11 14:44:45 +02:00
36 changed files with 3557 additions and 446 deletions

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

Binary file not shown.

View File

@ -1,54 +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>
<![CDATA[
{
"fontFamily": "h5p-core-18",
"description": "Font generated by IcoMoon.",
"majorVersion": 1,
"minorVersion": 1,
"version": "Version 1.1",
"fontId": "h5p-core-18",
"psName": "h5p-core-18",
"subFamily": "Regular",
"fullName": "h5p-core-18"
}
]]>
</json>
</metadata>
<defs>
<font id="h5p-core-18" 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="&#xe565;" glyph-name="arrow-down" data-tags="arrow-down" d="M234 432.335h556l-278-278z" />
<glyph unicode="&#xe566;" glyph-name="arrow-left" data-tags="arrow-left" d="M381 31.335v524l262-262z" />
<glyph unicode="&#xe58e;" glyph-name="colapse" data-tags="colapse" d="M512 490.002l256-256-60-60-196 196-196-196-60 60z" />
<glyph unicode="&#xe58f;" glyph-name="expand" data-tags="expand" d="M708 466.002l60-60-256-256-256 256 60 60 196-196z" />
<glyph unicode="&#xe600;" glyph-name="move" data-tags="move" d="M386.662 767.729h71.27v-71.27h-71.27v71.27zM566.067 767.729h71.27v-71.27h-71.27v71.27zM386.662 611.466h71.27v-71.27h-71.27v71.27zM566.067 611.466h71.27v-71.27h-71.27v71.27zM386.662 455.101h71.27v-71.27h-71.27v71.27zM566.067 455.101h71.27v-71.27h-71.27v71.27zM386.662 298.839h71.27v-71.27h-71.27v71.27zM566.067 298.839h71.27v-71.27h-71.27v71.27zM386.662 142.474h71.27v-71.27h-71.27v71.27zM566.067 142.474h71.27v-71.27h-71.27v71.27zM386.662-13.788h71.27v-71.27h-71.27v71.27zM566.067-13.788h71.27v-71.27h-71.27v71.27z" />
<glyph unicode="&#xe601;" glyph-name="check-mark" data-tags="check-mark" d="M454.299 288.59l-116.917 116.917-84.781-84.707 201.696-201.697 317.097 317.097-84.781 84.706z" />
<glyph unicode="&#xe888;" glyph-name="arrow-up-circle" data-tags="arrow-up-circle" d="M512 648.723c-148.616 0-264.722-120.75-260.077-269.367 0-125.395 88.241-232.212 208.991-255.434v213.636h-92.885c-13.933 0-13.933 9.288-9.288 18.577l139.327 171.838c4.645 9.288 13.933 9.288 23.221 4.645 0 0 4.645-4.645 4.645-4.645l139.327-171.838c9.288-9.288 4.645-18.577-9.288-18.577h-92.885v-213.636c143.972 32.51 232.212 171.838 199.703 315.808-23.221 120.75-130.039 204.347-250.789 208.991z" />
<glyph unicode="&#xe889;" glyph-name="info-circle" data-tags="info-circle" d="M512 644.267c-144.077 0-260.266-116.191-260.266-260.266s116.191-260.266 260.266-260.266 260.266 116.191 260.266 260.266v0c0 139.429-116.191 255.619-260.266 260.266zM470.171 593.144h88.305v-69.714h-88.305v69.714zM600.305 202.744h-181.257v51.123h51.123v162.666h-51.123v51.123h139.429v-218.438h46.477l-4.648-46.477z" />
<glyph unicode="&#xe88a;" glyph-name="search" data-tags="search" d="M772.098 168.176l-110.68 110.68c71.943 99.612 49.806 243.494-49.806 315.437s-243.494 44.27-315.437-55.339c-71.943-99.612-49.806-243.494 49.806-315.437 77.475-55.339 182.623-55.339 260.098 0l110.68-110.68c5.533-5.533 11.068-5.533 16.601 0 0 0 0 0 0 0l33.205 33.205c11.068 5.533 11.068 16.601 5.533 22.137 0 0 0 0 0 0zM478.795 245.651c-88.544 0-160.486 71.943-160.486 160.486s71.943 160.486 160.486 160.486 160.486-71.943 160.486-160.486-71.943-160.486-160.486-160.486v0z" />
<glyph unicode="&#xe88c;" glyph-name="fullscreen" data-tags="fullscreen" d="M368.55 533.187c5.737 5.737 0 5.737-5.737 5.737l-103.284 11.476c-5.737 5.737-11.476 0-11.476-5.737l11.476-109.021c0-5.737 5.737-5.737 5.737-5.737l103.284 103.284zM293.959 470.069l63.118-63.118c5.737-5.737 11.476-5.737 17.213 0l22.953 22.953c5.737 5.737 5.737 11.476 0 17.213l-63.118 57.379-40.166-34.429zM787.42 429.903c5.737-5.737 5.737 0 5.737 5.737l11.476 109.021c0 5.737-5.737 11.476-11.476 11.476l-109.021-11.476c-5.737 0-5.737-5.737-5.737-5.737l109.021-109.021zM724.305 504.498l-63.118-63.118c-5.737-5.737-5.737-11.476 0-17.213l22.953-22.953c5.737-5.737 11.476-5.737 17.213 0l63.118 63.118-40.166 40.166zM689.876 223.338c-5.737-5.737 0-5.737 5.737-5.737l109.021-11.476c5.737 0 11.476 5.737 11.476 11.476l-17.213 103.284c0 5.737-5.737 5.737-5.737 5.737l-103.284-103.284zM758.731 292.193l-63.118 63.118c-5.737 5.737-11.476 5.737-17.213 0l-22.953-22.953c-5.737-5.737-5.737-11.476 0-17.213l63.118-63.118 40.166 40.166zM265.269 326.622c-5.737 5.737-5.737 0-5.737-5.737l-11.476-109.021c0-5.737 5.737-11.476 11.476-11.476l109.021 11.476c5.737 0 5.737 5.737 5.737 5.737l-109.021 109.021zM334.124 252.028l63.118 63.118c5.737 5.737 5.737 11.476 0 17.213l-22.953 22.953c-5.737 5.737-11.476 5.737-17.213 0l-63.118-63.118 40.166-40.166zM161.985 636.471v-499.201h722.979v499.201h-722.979zM844.799 177.436h-636.911v413.13h636.911v-413.13z" />
<glyph unicode="&#xe88e;" glyph-name="h5p" data-tags="h5p" d="M934.072 531.858c-22.319 16.738-50.216 27.897-89.273 27.897h-139.487v-66.954h-156.225l-11.159-55.795c11.159 5.579 27.897 11.159 39.057 11.159s22.319 0 33.476 0c33.476 0 66.954-11.159 89.273-33.476s33.476-50.216 33.476-83.692c0-22.319-5.579-44.635-16.738-66.954s-27.897-39.057-50.216-50.216c-5.579-5.579-16.738 0-22.319-11.159h117.17v133.908h66.954c44.635 0 78.113 11.159 100.43 27.897 22.319 22.319 33.476 50.216 33.476 83.692 0 39.057-11.159 66.954-27.897 83.692v0zM839.221 420.269c-11.159-5.579-22.319-11.159-44.635-11.159h-33.476v83.692h39.057c22.319 0 33.476-5.579 44.635-11.159 5.579-5.579 11.159-16.738 11.159-27.897 0-16.738-5.579-27.897-16.738-33.476v0zM565.826 381.212c-16.738 0-33.476-11.159-44.635-27.897l-94.851 16.738 44.635 195.281h-94.851v-150.646h-117.17v150.646h-111.589v-362.667h111.589v133.908h117.17v-133.908h139.487c-16.738 11.159-33.476 11.159-44.635 22.319s-22.319 22.319-27.897 33.476c-5.579 11.159-11.159 22.319-16.738 39.057l94.851 16.738c5.579-16.738 22.319-27.897 44.635-27.897 27.897 0 50.216 22.319 50.216 50.216 0 22.319-22.319 44.635-50.216 44.635v0z" />
<glyph unicode="&#xe88f;" glyph-name="rights-of-use" data-tags="rights-of-use" d="M899.611 372.185c0-5.907 0-5.907 0-5.907-23.631-23.631-47.261-35.448-76.799-41.355-11.813 0-23.631-5.907-35.448-5.907s-17.724 0-29.537 0c0 0-5.907 0-5.907 5.907-64.985 59.079-135.877 118.153-200.863 183.139 0 0-5.907 0-5.907 0-23.631-5.907-47.261-11.813-70.892-17.724s-53.168 0-76.799 11.813c-17.724 11.813-23.631 17.724-29.537 35.448-5.907 5.907 0 23.631 11.813 23.631 41.355 11.813 88.616 29.537 129.971 47.261 11.813 5.907 29.537 5.907 41.355 5.907 5.907 0 11.813-5.907 11.813-5.907 41.355-17.724 82.709-29.537 124.060-47.261 0 0 5.907 0 5.907 0 29.537 5.907 64.985 17.724 94.523 23.631 5.907 0 5.907 0 5.907 0l106.34-212.676zM291.12 378.095c17.724 11.813 35.448 5.907 53.168-11.813 11.813-11.813 11.813-29.537 5.907-47.261 17.724 5.907 35.448-5.907 41.355-17.724 11.813-17.724 5.907-35.448-5.907-47.261 5.907 0 11.813 0 17.724 0 11.813-5.907 23.631-11.813 29.537-29.537s0-29.537-5.907-35.448c-5.907-5.907-11.813-11.813-17.724-17.724s-11.813-11.813-17.724-17.724-35.448-17.724-53.168 0c-29.537 29.537-53.168 64.985-82.709 94.523-17.724 23.631-35.448 41.355-47.261 64.985-5.907 11.813-11.813 17.724-11.813 29.537 0 5.907 0 17.724 5.907 23.631 11.813 11.813 17.724 17.724 29.537 29.537 17.724 17.724 47.261 11.813 64.985-5.907-5.907 0-5.907-5.907-5.907-11.813v0zM438.811 171.326l29.537-29.537c17.724-17.724 47.261-11.813 59.079 5.907l-5.907 5.907c-23.631 23.631-47.261 47.261-70.892 70.892-5.907 5.907-5.907 5.907-5.907 11.813s5.907 5.907 11.813 11.813c5.907 0 11.813 0 11.813-5.907 11.813-11.813 29.537-29.537 47.261-47.261 11.813-11.813 29.537-29.537 47.261-47.261 5.907-11.813 17.724-11.813 29.537-11.813 11.813 5.907 23.631 11.813 29.537 23.631 0 5.907 0 5.907 0 5.907-41.355 41.355-88.616 82.709-129.971 129.971-5.907 5.907-5.907 5.907-5.907 11.813 0 11.813 11.813 11.813 23.631 5.907 0 0 5.907 0 5.907-5.907 41.355-41.355 88.616-88.616 129.971-129.971 5.907-5.907 5.907-5.907 5.907-5.907 17.724 0 35.448 17.724 35.448 35.448 0 5.907 0 5.907 0 5.907-47.261 47.261-100.429 100.429-147.691 147.691-5.907 5.907-5.907 5.907-5.907 11.813s5.907 11.813 5.907 11.813c5.907 0 11.813 0 11.813-5.907 5.907-5.907 5.907-5.907 11.813-11.813 35.448-35.448 70.892-70.892 106.34-106.34 11.813-11.813 23.631-23.631 29.537-29.537 0 0 5.907-5.907 5.907 0 23.631 5.907 35.448 29.537 29.537 53.168h35.448c0 0 0 0 0 0 0-5.907 0-17.724 0-23.631-5.907-29.537-23.631-47.261-53.168-59.079 0 0-5.907 0-5.907-5.907-11.813-29.537-35.448-53.168-64.985-53.168-5.907 0-5.907 0-5.907-5.907-17.724-35.448-59.079-47.261-88.616-35.448-5.907 0-11.813 5.907-11.813 5.907-5.907-5.907-11.813-11.813-23.631-17.724-29.537-11.813-59.079-5.907-76.799 11.813-11.813 11.813-17.724 17.724-29.537 29.537 17.724 23.631 23.631 29.537 29.537 41.355v0 0zM273.396 685.294c29.537-11.813 64.985-23.631 94.523-29.537 35.448-11.813 64.985-23.631 100.429-29.537 0 0 0 0 5.907 0-17.724-5.907-35.448-11.813-47.261-17.724 0 0-5.907 0-5.907 0-47.261 11.813-94.523 23.631-135.877 41.355-5.907 0-5.907 0-5.907 0l-76.799-183.139c0-11.813 5.907-17.724 11.813-23.631s5.907-5.907 5.907-11.813c-5.907-5.907-11.813-17.724-23.631-23.631-17.724 17.724-29.537 35.448-29.537 64.985l88.616 212.676c-5.907-11.813 5.907 5.907 17.724 0v0z" />
<glyph unicode="&#xe890;" glyph-name="delete-circle" data-tags="delete-circle" d="M512 644.267c-147.107 0-260.266-118.817-260.266-260.266s118.817-260.266 260.266-260.266 260.266 118.817 260.266 260.266-113.158 260.266-260.266 260.266zM653.449 304.789c5.659-5.659 5.659-16.973 0-28.29l-33.949-33.949c-5.659-5.659-16.973-5.659-28.29 0l-79.212 79.212-79.212-79.212c-5.659-5.659-16.973-5.659-28.29 0l-33.949 33.949c-5.659 5.659-5.659 16.973 0 28.29l84.871 79.212-79.212 79.212c-5.659 5.659-5.659 16.973 0 28.29l33.949 33.949c5.659 5.659 16.973 5.659 28.29 0l73.554-84.871 79.212 79.212c5.659 5.659 16.973 5.659 28.29 0l33.949-33.949c5.659-5.659 5.659-16.973 0-28.29l-79.212-73.554 79.212-79.212z" />
<glyph unicode="&#xe891;" glyph-name="window" data-tags="window" d="M203.936 503.802c-5.704-5.704 0-5.704 5.704-5.704l108.394-11.41c5.704 0 11.41 5.704 11.41 11.41l-17.114 102.687c0 5.704-5.704 5.704-5.704 5.704l-102.687-102.687zM272.395 566.557l-62.752 62.752c-5.704 5.704-11.41 5.704-17.114 0l-17.114-22.821c-5.704-5.704-5.704-11.41 0-17.114l62.752-62.752 34.228 39.935zM751.605 600.785c-5.704 5.704-5.704 0-5.704-5.704l-11.41-108.394c0-5.704 5.704-11.41 11.41-11.41l108.394 11.41c5.704 0 5.704 5.704 5.704 5.704l-108.394 108.394zM814.357 526.623l62.752 62.752c5.704 5.704 5.704 11.41 0 17.114l-22.821 22.821c-5.704 5.704-11.41 5.704-17.114 0l-62.752-62.752 39.935-39.935zM848.588 264.2c5.704 5.704 0 5.704-5.704 5.704l-102.687 17.114c-5.704 0-11.41-5.704-11.41-11.41l11.41-108.394c0-5.704 5.704-5.704 5.704-5.704l102.687 102.687zM780.129 201.445l62.752-62.752c5.704-5.704 11.41-5.704 17.114 0l22.821 22.821c5.704 5.704 5.704 11.41 0 17.114l-62.752 62.752-39.935-39.935zM300.919 167.217c5.704-5.704 5.704 0 5.704 5.704l11.41 108.394c0 5.704-5.704 11.41-11.41 11.41l-108.394-11.41c-5.704 0-5.704-5.704-5.704-5.704l108.394-108.394zM238.167 235.676l-62.752-62.752c-5.704-5.704-5.704-11.41 0-17.114l22.821-22.821c5.704-5.704 11.41-5.704 17.114 0l62.752 62.752-39.935 39.935zM352.264 509.509v-239.605h347.998v239.605h-347.998zM654.622 309.838h-262.424v154.032h262.424v-154.032z" />
<glyph unicode="&#xe892;" glyph-name="code" data-tags="code" d="M449.641 277.991c6.235-6.235 6.235-12.472 6.235-18.707v-62.359c0-6.235-6.235-6.235-6.235-6.235l-230.728 155.897c-6.235 6.235-6.235 12.472-6.235 18.707v49.886c0 6.235 6.235 12.472 6.235 18.707l230.728 155.897c6.235 6.235 6.235 0 6.235-6.235v-62.359c0-6.235-6.235-12.472-6.235-18.707l-162.134-112.245c-6.235-6.235-6.235-6.235 0-12.472l162.134-99.776zM736.493 384.001c6.235 6.235 6.235 6.235 0 12.472l-155.897 112.245c-6.235 6.235-6.235 12.472-6.235 18.707v62.359c0 6.235 6.235 6.235 6.235 6.235l230.728-155.897c6.235-6.235 6.235-12.472 6.235-18.707v-49.886c0-6.235-6.235-12.472-6.235-18.707l-230.728-155.897c-6.235-6.235-6.235 0-6.235 6.235v62.359c0 6.235 6.235 12.472 6.235 18.707l155.897 99.776z" />
<glyph unicode="&#xe893;" glyph-name="download" data-tags="download" d="M358.941 478.191c-11.773 0-17.66-5.887-5.887-17.66l153.059-188.382c5.887-11.773 23.547-11.773 29.433 0l153.059 188.382c5.887 11.773 5.887 17.66-5.887 17.66h-323.782zM576.756 466.417v135.399c0 11.773-11.773 23.547-23.547 23.547h-70.643c-11.773 0-23.547-11.773-23.547-23.547v-141.286h117.739zM653.286 331.018c-5.887 0-17.66-5.887-23.547-11.773l-76.53-94.19c-5.887-5.887-17.66-17.66-23.547-23.547 0 0-5.887-5.887-11.773-5.887s-17.66 11.773-17.66 11.773c-5.887 5.887-17.66 17.66-23.547 23.547l-76.53 94.19c-5.887 5.887-17.66 11.773-23.547 11.773h-123.626c-5.887 0-17.66-5.887-17.66-17.66v-141.286c0-5.887 5.887-17.66 17.66-17.66h529.824c5.887 0 17.66 5.887 17.66 17.66v141.286c0 5.887-5.887 17.66-17.66 17.66l-129.513-5.887zM305.958 219.168c-17.66 0-29.433 11.773-29.433 29.433s11.773 29.433 29.433 29.433c17.66 0 29.433-11.773 29.433-29.433s-11.773-29.433-29.433-29.433v0z" />
<glyph unicode="&#xe894;" glyph-name="delete" data-tags="delete" d="M620.266 384.001l134.045 134.045c10.311 10.311 10.311 30.934 0 41.245l-61.866 61.866c-10.311 10.311-30.934 10.311-41.245 0l-134.045-134.045-134.045 134.045c-10.311 10.311-30.934 10.311-41.245 0l-61.866-61.866c-10.311-10.311-10.311-30.934 0-41.245l134.045-134.045-134.045-134.045c-10.311-10.311-10.311-30.934 0-41.245l61.866-61.866c10.311-10.311 30.934-10.311 41.245 0l134.045 134.045 134.045-134.045c10.311-10.311 30.934-10.311 41.245 0l61.866 61.866c10.311 10.311 10.311 30.934 0 41.245l-134.045 134.045z" />
<glyph unicode="&#xe900;" glyph-name="edit-image" data-tags="edit-image" d="M300.237 664.305c69.018 23.142 133.325 14.234 189.133-33.28 56.627-48.128 77.619-110.592 63.181-183.808-2.355-12.186 0.307-19.456 8.704-27.853 93.901-93.389 156.774-156.467 250.47-250.163 5.427-5.427 10.957-10.854 15.667-16.896 39.424-50.278 16.794-124.006-44.237-142.029-36.966-10.957-68.403 0-95.334 27.034-95.642 96.051-160.973 160.973-256.614 257.024-6.963 6.963-12.8 8.909-22.63 6.758-117.76-26.317-229.171 60.826-231.731 181.453-0.614 26.419 3.584 52.326 15.974 77.926 34.816-34.816 68.506-67.789 101.274-101.786 10.445-10.752 20.992-15.36 36.045-15.36 14.643 0 25.19 3.891 34.816 14.848 10.752 12.39 23.040 23.347 34.611 35.021 14.336 14.438 14.336 46.080-0.205 60.518-35.123 35.226-70.349 70.349-106.598 106.496 3.891 2.253 5.632 3.482 7.475 4.096zM703.386 106.225c-0.41-24.269 20.685-45.466 44.851-45.158 23.757 0.41 44.032 20.992 43.93 44.544-0.102 23.757-20.275 44.032-44.237 44.134-23.859 0.307-44.237-19.661-44.544-43.52z" />
<glyph unicode="&#xe901;" glyph-name="hourglass" data-tags="hourglass" d="M733.286 32.087c-147.763 0-295.526 0-443.29 0 0 2.048 0.102 4.096 0 6.144-0.307 13.824-1.024 32.666-0.922 46.49 0.41 39.731 6.861 78.131 19.046 115.2 17.203 52.224 43.725 96.256 81.306 130.355 4.506 4.096 9.216 7.885 13.722 11.776-0.205 0.717-0.307 1.126-0.41 1.229-1.331 1.229-2.765 2.355-4.198 3.584-28.058 22.63-50.688 51.405-68.403 85.606-30.618 59.085-43.52 123.597-41.165 192.614 0.205 7.168 0.614 18.33 0.922 25.498 147.763 0 295.526 0 443.29 0 0.205-1.331 0.512-2.662 0.614-3.994 2.662-36.966 1.229-77.722-5.939-113.869-14.336-72.909-44.544-133.837-95.027-179.405-4.096-3.686-8.294-7.066-12.39-10.547 0.205-0.717 0.307-1.126 0.512-1.331 0.819-0.717 1.638-1.434 2.458-2.15 42.189-33.894 71.68-79.872 90.931-135.782 11.776-34.202 18.637-69.837 20.070-106.701 0.819-19.763-0.614-44.851-1.126-64.717zM687.309 75.3c0 6.554 0.205 12.493 0 18.432-1.331 37.581-7.27 74.138-19.866 108.749-17.92 49.562-45.568 88.269-88.678 108.646-2.458 1.126-2.97 3.072-2.97 5.837 0.102 16.691 0.102 33.485 0 50.176 0 3.994 1.331 5.427 4.096 6.963 9.114 5.325 18.432 10.24 26.829 16.896 29.696 23.552 49.152 56.934 62.362 95.744 10.342 30.413 15.77 62.259 17.818 94.822 0.614 9.114 0.102 18.227 0.102 27.546-116.634 0-233.574 0-351.027 0 0.307-8.704 0.614-16.998 1.024-25.395 1.946-37.274 8.499-73.216 21.504-107.213 18.125-47.104 45.261-83.558 86.528-103.117 2.253-1.024 2.867-2.662 2.867-5.427-0.102-17.203-0.102-34.509 0-51.712 0-3.072-1.024-4.506-3.277-5.632-5.632-2.867-11.366-5.734-16.691-9.216-34.304-22.733-56.832-57.754-71.987-100.147-12.493-35.123-18.125-71.987-19.661-109.875-0.205-5.325 0-10.752 0-16.282 117.35 0.205 234.189 0.205 351.027 0.205zM410.214 494.628c68.096 0 135.373 0 203.674 0-3.789-6.554-7.168-12.595-10.752-18.227-10.957-16.998-24.269-30.618-39.731-41.472s-27.75-25.293-32.768-46.592c-1.638-6.963-2.765-14.336-2.867-21.606-0.307-17.203-0.205-34.406 0.307-51.712 0.717-28.058 12.493-48.947 32.154-62.566 43.008-30.003 65.843-75.878 75.776-132.506 0.307-1.638 0.307-3.379 0.614-5.53-83.149 0-166.093 0-249.242 0 2.662 20.685 7.885 40.346 15.462 59.085 13.312 32.973 32.768 59.187 59.494 77.722 16.589 11.469 28.365 27.955 32.358 50.995 0.819 4.813 1.331 9.83 1.434 14.746 0.102 18.637 0.614 37.274-0.205 55.808-1.126 24.678-11.981 43.213-28.57 57.139-9.216 7.782-18.944 14.746-27.648 23.142-11.981 11.162-21.197 25.395-29.491 41.574z" />
<glyph unicode="&#xe902;" glyph-name="plus-icon" data-tags="plus-icon" d="M768 327.681c0-19.323-15.664-34.987-34.987-34.987h-151.040v-151.467c0-19.323-15.664-34.987-34.987-34.987h-69.547c-19.323 0-34.987 15.664-34.987 34.987v151.467h-151.467c-19.323 0-34.987 15.664-34.987 34.987v69.547c0 19.323 15.664 34.987 34.987 34.987h151.467v151.467c0 19.323 15.664 34.987 34.987 34.987h69.547c19.323 0 34.987-15.664 34.987-34.987v-151.467h151.467c19.323 0 34.987-15.664 34.987-34.987z" />
<glyph unicode="&#xe903;" glyph-name="video-upload-icon" data-tags="video-upload-icon" d="M384 371.201v-128c0-21.333 21.333-42.667 42.667-42.667h128c21.333 0 42.667 17.067 42.667 42.667v128c0 21.333-17.067 42.667-42.667 42.667h-128c-21.333 0-42.667-17.067-42.667-42.667zM785.067 541.867l-102.4 106.667c-12.8 12.8-38.4 21.333-55.467 21.333h-140.8l21.333-42.667h89.6v-136.533c0-17.067 12.8-29.867 29.867-29.867h140.8v-341.333h-426.667v328.533h-42.667v-341.333c0-17.067 12.8-29.867 29.867-29.867h448c17.067 0 29.867 12.8 29.867 29.867v384c4.267 17.067-8.533 38.4-21.333 51.2zM640 499.201v123.733c4.267 0 12.8-4.267 12.8-8.533l102.4-102.4c4.267-4.267 4.267-8.533 8.533-12.8h-123.733zM725.333 209.067v196.267c0 4.267-4.267 8.533-8.533 8.533s-8.533 0-12.8-4.267l-89.6-89.6v-29.867l89.6-89.6c8.533-4.267 8.533 0 12.8 0 4.267 4.267 8.533 4.267 8.533 8.533zM349.867 516.267v136.533l59.733-59.733c8.533-8.533 17.067-4.267 25.6 0l12.8 12.8c8.533 8.533 8.533 17.067 0 25.6l-115.2 106.667c-8.533 8.533-17.067 8.533-21.333 0l-115.2-110.933c-4.267-8.533-4.267-17.067 0-25.6l12.8-12.8c8.533-8.533 17.067-8.533 21.333 0l59.733 59.733v-136.533c0-8.533 8.533-17.067 17.067-17.067h25.6c0 0 17.067 8.533 17.067 21.333z" />
<glyph unicode="&#xe904;" glyph-name="play-icon" data-tags="play-icon" d="M392.533 640.001c81.067 46.933 187.733 46.933 273.067 0 42.667-25.6 72.533-55.467 98.133-98.133 72.533-128 29.867-294.4-98.133-371.2-128-72.533-294.4-29.867-371.2 98.133-46.933 81.067-46.933 187.733 0 273.067 21.333 42.667 55.467 72.533 98.133 98.133zM661.333 388.267c12.8 8.533 12.8 29.867 0 38.4l-192 110.933c-8.533 4.267-12.8 4.267-21.333 0s-12.8-12.8-12.8-21.333v-226.133c0-8.533 4.267-17.067 12.8-21.333s17.067-4.267 21.333 0l192 119.467z" />
<glyph unicode="&#xe905;" glyph-name="copy" data-tags="copy" d="M722.133 603.867h-247.733c-65.867 0-119.2-53.333-119.2-119.2v-288.533c0-65.867 53.333-119.2 119.2-119.2h247.867c65.867 0 119.2 53.333 119.2 119.2v288.533c-0.267 65.867-53.467 119.2-119.333 119.2zM778.533 199.2c0-31.333-25.067-56.4-56.4-56.4h-247.867c-31.333 0-56.4 25.067-56.4 56.4v285.467c0 31.333 25.067 56.4 56.4 56.4h247.733c31.333 0 56.4-25.067 56.4-56.4v-285.467zM245.2 368.667v288.533c0 31.333 25.067 56.4 56.4 56.4h247.733c31.333 0 56.4-25.067 56.4-56.4v-18.8h62.667v18.8c0 65.867-53.333 119.2-119.2 119.2h-247.467c-65.867 0-119.2-53.333-119.2-119.2v-288.533c0-65.867 53.333-119.2 119.2-119.2h18.8v62.667h-18.8c-31.467-3.067-56.533 22-56.533 56.533zM681.2 403.2h-163.067c-18.8 0-31.333 12.533-31.333 31.333s12.533 31.333 31.333 31.333h163.067c18.8 0 31.333-12.533 31.333-31.333s-15.6-31.333-31.333-31.333zM681.2 309.067h-163.067c-18.8 0-31.333 12.533-31.333 31.333s12.533 31.333 31.333 31.333h163.067c18.8 0 31.333-12.533 31.333-31.333s-15.6-31.333-31.333-31.333zM681.2 214.934h-163.067c-18.8 0-31.333 12.533-31.333 31.333s12.533 31.333 31.333 31.333h163.067c18.8 0 31.333-12.533 31.333-31.333s-15.6-31.333-31.333-31.333z" />
<glyph unicode="&#xe906;" glyph-name="examples-icon" data-tags="examples-icon" d="M213.333 209.068c89.6 38.4 183.467 68.267 273.067 17.067v281.6c-68.267 46.933-157.867 55.467-234.667 12.8l-38.4-311.467zM810.667 209.068l-42.667 315.733c-72.533 38.4-166.4 34.133-234.667-17.067v-285.867c93.867 51.2 187.733 21.333 277.333-12.8zM832 563.201c-51.2 29.867-110.933 46.933-170.667 55.467-51.2 0-102.4-8.533-149.333-29.867-46.933 21.333-98.133 29.867-149.333 29.867-59.733-4.267-119.467-25.6-170.667-55.467l-64-452.267c0 0 29.867-17.067 110.933 21.333 46.933 25.6 102.4 34.133 157.867 25.6 42.667-4.267 85.333-21.333 115.2-55.467v0c29.867 34.133 72.533 51.2 115.2 55.467 55.467 4.267 106.667-4.267 157.867-29.867 81.067-38.4 110.933-21.333 110.933-21.333l-64 456.533zM793.6 157.868c-42.667 21.333-89.6 34.133-140.8 34.133-8.533 0-21.333 0-29.867 0-42.667-4.267-81.067-17.067-115.2-42.667-34.133 25.6-72.533 38.4-115.2 42.667-12.8 0-21.333 0-34.133 0-46.933 0-93.867-8.533-136.533-29.867-21.333-12.8-46.933-21.333-72.533-25.6l64 413.867c46.933 25.6 98.133 38.4 149.333 42.667 46.933 0 93.867-8.533 136.533-25.6l12.8-8.533 12.8 4.267c42.667 17.067 89.6 25.6 136.533 25.6 51.2-4.267 102.4-17.067 149.333-42.667l59.733-418.133c-29.867 8.533-51.2 17.067-76.8 29.867z" />
<glyph unicode="&#xe907;" glyph-name="tutorials-icon" data-tags="tutorials-icon" d="M887.467 473.601l-375.467-110.933h-4.267l-217.6 68.267c-21.333-25.6-34.133-59.733-34.133-98.133 21.333-12.8 25.6-38.4 12.8-59.733-4.267-4.267-8.533-8.533-12.8-12.8l17.067-145.067c0-4.267 0-4.267-4.267-8.533 0 0 0 0-4.267 0h-64c-4.267 0-4.267 0-8.533 4.267 0 4.267-4.267 4.267-4.267 8.533l17.067 145.067c-12.8 8.533-17.067 21.333-17.067 34.133 0 17.067 8.533 29.867 21.333 38.4 0 38.4 12.8 76.8 34.133 110.933l-106.667 29.867c-8.533 4.267-8.533 8.533-8.533 17.067 0 4.267 4.267 4.267 4.267 4.267l375.467 119.467h4.267l375.467-123.733c4.267 0 8.533-4.267 8.533-8.533s-4.267-8.533-8.533-12.8zM725.333 277.335c4.267-46.933-93.867-85.333-213.333-85.333s-213.333 38.4-213.333 85.333l4.267 106.667 192-64c4.267 0 12.8 0 17.067 0s12.8 0 17.067 4.267l192 59.733 4.267-106.667z" />
<glyph unicode="&#xe908;" glyph-name="info-important-description" data-tags="info-important-description" d="M512 740.034c-188.5 0-341.3-152.8-341.3-341.3s152.8-341.4 341.3-341.4 341.3 152.8 341.3 341.3-152.8 341.4-341.3 341.4v0zM512 85.934c-172.7 0-312.7 140-312.7 312.7s140 312.7 312.7 312.7c172.7 0 312.7-140 312.7-312.7-0.2-172.6-140.1-312.5-312.7-312.7v0zM512 648.234c-137.9 0-249.6-111.8-249.6-249.6s111.7-249.6 249.6-249.6 249.6 111.8 249.6 249.6-111.8 249.6-249.6 249.6v0z" />
<glyph unicode="&#xe909;" glyph-name="icon-info" data-tags="icon-info" d="M467.2 502.188h87.467c0.028 0 0.062 0 0.095 0 6.056 0 11.499 2.629 15.248 6.808 3.979 4.15 6.419 9.769 6.419 15.957 0 0.097-0.001 0.194-0.002 0.29v70.385c0.001 0.082 0.002 0.179 0.002 0.276 0 6.188-2.44 11.806-6.409 15.946-3.759 4.19-9.201 6.819-15.257 6.819-0.033 0-0.067 0-0.1 0h-87.462c-0.028 0-0.062 0-0.095 0-6.056 0-11.499-2.629-15.248-6.808-3.979-4.15-6.419-9.769-6.419-15.957 0-0.097 0.001-0.194 0.002-0.29v-69.959c-0.001-0.082-0.002-0.179-0.002-0.276 0-6.188 2.44-11.806 6.409-15.946 3.715-4.373 9.2-7.159 15.338-7.245zM597.333 199.255h-22.187v209.92c0.001 0.082 0.002 0.179 0.002 0.276 0 6.188-2.44 11.806-6.409 15.946-3.759 4.19-9.201 6.819-15.257 6.819-0.033 0-0.067 0-0.1 0h-130.128c-0.028 0-0.062 0-0.095 0-6.056 0-11.499-2.629-15.248-6.808-3.979-4.15-6.419-9.769-6.419-15.957 0-0.097 0.001-0.194 0.002-0.29v-46.492c-0.001-0.082-0.002-0.179-0.002-0.276 0-6.188 2.44-11.806 6.409-15.946 3.759-4.19 9.201-6.819 15.257-6.819 0.033 0 0.067 0 0.1 0h22.182v-139.947h-22.187c-0.028 0-0.062 0-0.095 0-6.056 0-11.499-2.629-15.248-6.808-3.979-4.15-6.419-9.769-6.419-15.957 0-0.097 0.001-0.194 0.002-0.29v-46.492c-0.001-0.082-0.002-0.179-0.002-0.276 0-6.188 2.44-11.806 6.409-15.946 3.759-4.19 9.201-6.819 15.257-6.819 0.033 0 0.067 0 0.1 0h174.075c0.028 0 0.062 0 0.095 0 6.056 0 11.499 2.629 15.248 6.808 3.979 4.15 6.419 9.769 6.419 15.957 0 0.097-0.001 0.194-0.002 0.29v46.065c0.043 0.527 0.067 1.141 0.067 1.761 0 5.302-1.791 10.185-4.8 14.079-3.742 4.424-9.36 7.247-15.636 7.247-0.489 0-0.975-0.017-1.456-0.051z" />
<glyph unicode="&#xe90a;" glyph-name="paste" data-tags="paste" d="M394.402 745.066h-75.333c-65.867 0-119.2-53.333-119.2-119.2v-288.533c0-56.4 37.6-100.4 87.867-116v69.067c-15.733 9.467-25.067 25.067-25.067 47.067v288.4c0 31.333 25.067 56.4 56.4 56.4h131.733c0 0 0 0 3.2 3.2v0c0 31.333-28.267 59.6-59.6 59.6zM704.802 635.199c0 0-28.267 0-40.8 0-12.533 34.533-43.867 59.6-84.667 59.6s-69.067-25.067-81.6-59.6c-12.533 0-40.8 0-40.8 0-65.867 0-119.2-53.333-119.2-119.2v-288.533c0-65.867 53.333-119.2 119.2-119.2h247.867c65.867 0 119.2 53.333 119.2 119.2v285.467c3.2 65.867-53.2 122.267-119.2 122.267zM582.535 647.866c22 0 40.8-18.8 40.8-40.8s-18.8-40.8-40.8-40.8c-22 0-40.8 18.8-40.8 40.8s15.733 40.8 40.8 40.8zM764.402 224.399c0-31.333-25.067-56.4-56.4-56.4h-250.933c-31.333 0-56.4 25.067-56.4 56.4v288.533c0 18.8 9.467 37.6 25.067 47.067v0c0-43.867 34.533-78.4 78.4-78.4h160c43.867 0 78.4 34.533 78.4 78.4v0c12.533-9.467 22-28.267 22-47.067v-288.533z" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Binary file not shown.

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.

View File

@ -311,13 +311,7 @@ class H5PDefaultStorage implements \H5PFileStorage {
// Add filename to path // Add filename to path
$path .= '/' . $file->getName(); $path .= '/' . $file->getName();
$fileData = $file->getData();
if ($fileData) {
file_put_contents($path, $fileData);
}
else {
copy($_FILES['file']['tmp_name'], $path); copy($_FILES['file']['tmp_name'], $path);
}
return $file; return $file;
} }
@ -363,15 +357,14 @@ class H5PDefaultStorage implements \H5PFileStorage {
* content from the current temporary upload folder to the editor path. * content from the current temporary upload folder to the editor path.
* *
* @param string $source path to source directory * @param string $source path to source directory
* @param string $contentId Id of content * @param string $contentId Id of contentarray
*
* @return object Object containing h5p json and content json data
*/ */
public function moveContentDirectory($source, $contentId = NULL) { public function moveContentDirectory($source, $contentId = NULL) {
if ($source === NULL) { if ($source === NULL) {
return NULL; return NULL;
} }
// TODO: Remove $contentId and never copy temporary files into content folder. JI-366
if ($contentId === NULL || $contentId == 0) { if ($contentId === NULL || $contentId == 0) {
$target = $this->getEditorPath(); $target = $this->getEditorPath();
} }
@ -380,7 +373,7 @@ class H5PDefaultStorage implements \H5PFileStorage {
$target = "{$this->path}/content/{$contentId}"; $target = "{$this->path}/content/{$contentId}";
} }
$contentSource = $source . DIRECTORY_SEPARATOR . 'content'; $contentSource = $source . '/' . 'content';
$contentFiles = array_diff(scandir($contentSource), array('.','..', 'content.json')); $contentFiles = array_diff(scandir($contentSource), array('.','..', 'content.json'));
foreach ($contentFiles as $file) { foreach ($contentFiles as $file) {
if (is_dir("{$contentSource}/{$file}")) { if (is_dir("{$contentSource}/{$file}")) {
@ -391,14 +384,7 @@ class H5PDefaultStorage implements \H5PFileStorage {
} }
} }
// Successfully loaded content json of file into editor // TODO: Return list of all files so that they can be marked as temporary. JI-366
$h5pJson = $this->getContent($source . DIRECTORY_SEPARATOR . 'h5p.json');
$contentJson = $this->getContent($contentSource . DIRECTORY_SEPARATOR . 'content.json');
return (object) array(
'h5pJson' => $h5pJson,
'contentJson' => $contentJson
);
} }
/** /**
@ -459,11 +445,49 @@ class H5PDefaultStorage implements \H5PFileStorage {
* @return bool * @return bool
*/ */
public function hasPresave($libraryFolder, $developmentPath = null) { public function hasPresave($libraryFolder, $developmentPath = null) {
$path = is_null($developmentPath) ? 'libraries' . DIRECTORY_SEPARATOR . $libraryFolder : $developmentPath; $path = is_null($developmentPath) ? 'libraries' . '/' . $libraryFolder : $developmentPath;
$filePath = realpath($this->path . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . 'presave.js'); $filePath = realpath($this->path . '/' . $path . '/' . 'presave.js');
return file_exists($filePath); 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. * Recursive function for copying directories.
* *

View File

@ -67,7 +67,7 @@ class H5PDevelopment {
$contents = scandir($path); $contents = scandir($path);
for ($i = 0, $s = count($contents); $i < $s; $i++) { for ($i = 0, $s = count($contents); $i < $s; $i++) {
if ($contents[$i]{0} === '.') { if ($contents[$i][0] === '.') {
continue; // Skip hidden stuff. continue; // Skip hidden stuff.
} }

View File

@ -199,4 +199,24 @@ interface H5PFileStorage {
* @return bool * @return bool
*/ */
public function hasPresave($libraryName, $developmentPath = null); 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);
} }

View File

@ -9,6 +9,10 @@ abstract class H5PMetadata {
'type' => 'text', 'type' => 'text',
'maxLength' => 255 'maxLength' => 255
), ),
'a11yTitle' => array(
'type' => 'text',
'maxLength' => 255,
),
'authors' => array( 'authors' => array(
'type' => 'json' 'type' => 'json'
), ),
@ -40,6 +44,10 @@ abstract class H5PMetadata {
), ),
'yearTo' => array( 'yearTo' => array(
'type' => 'int' 'type' => 'int'
),
'defaultLanguage' => array(
'type' => 'text',
'maxLength' => 32,
) )
); );
@ -53,6 +61,7 @@ abstract class H5PMetadata {
// Note: deliberatly creating JSON string "manually" to improve performance // Note: deliberatly creating JSON string "manually" to improve performance
return return
'{"title":' . (isset($content->title) ? json_encode($content->title) : 'null') . '{"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') . ',"authors":' . (isset($content->authors) ? $content->authors : 'null') .
',"source":' . (isset($content->source) ? '"' . $content->source . '"' : 'null') . ',"source":' . (isset($content->source) ? '"' . $content->source . '"' : 'null') .
',"license":' . (isset($content->license) ? '"' . $content->license . '"' : 'null') . ',"license":' . (isset($content->license) ? '"' . $content->license . '"' : 'null') .
@ -61,18 +70,20 @@ abstract class H5PMetadata {
',"yearFrom":' . (isset($content->year_from) ? $content->year_from : 'null') . ',"yearFrom":' . (isset($content->year_from) ? $content->year_from : 'null') .
',"yearTo":' . (isset($content->year_to) ? $content->year_to : 'null') . ',"yearTo":' . (isset($content->year_to) ? $content->year_to : 'null') .
',"changes":' . (isset($content->changes) ? $content->changes : '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') . '}'; ',"authorComments":' . (isset($content->author_comments) ? json_encode($content->author_comments) : 'null') . '}';
} }
/** /**
* Make the metadata into an associative array keyed by the property names * Make the metadata into an associative array keyed by the property names
* @param mixed $metadata Array or object containing metadata * @param mixed $metadata Array or object containing metadata
* @param bool $include_title * @param bool $include_title
* @param bool $include_missing For metadata fields not being set, skip 'em.
* Relevant for content upgrade
* @param array $types * @param array $types
* @return array * @return array
*/ */
public static function toDBArray($metadata, $include_title = true, &$types = array()) { public static function toDBArray($metadata, $include_title = true, $include_missing = true, &$types = array()) {
$fields = array(); $fields = array();
if (!is_array($metadata)) { if (!is_array($metadata)) {
@ -81,36 +92,44 @@ abstract class H5PMetadata {
foreach (self::$fields as $key => $config) { foreach (self::$fields as $key => $config) {
// Ignore title?
if ($key === 'title' && !$include_title) { if ($key === 'title' && !$include_title) {
continue; continue;
} }
if (isset($metadata[$key])) { $exists = array_key_exists($key, $metadata);
$value = $metadata[$key];
// 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)); $db_field_name = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $key));
switch ($config['type']) { switch ($config['type']) {
case 'text': case 'text':
if (strlen($value) > $config['maxLength']) { if ($value !== null && strlen($value) > $config['maxLength']) {
$value = mb_substr($value, 0, $config['maxLength']); $value = mb_substr($value, 0, $config['maxLength']);
} }
$types[] = '%s'; $types[] = '%s';
break; break;
case 'int': case 'int':
$value = ($value !== null) ? intval($value): null; $value = ($value !== null) ? intval($value) : null;
$types[] = '%d'; $types[] = '%d';
break; break;
case 'json': case 'json':
$value = json_encode($value); $value = ($value !== null) ? json_encode($value) : null;
$types[] = '%s'; $types[] = '%s';
break; break;
} }
$fields[$db_field_name] = $value; $fields[$db_field_name] = $value;
} }
}
return $fields; return $fields;
} }

File diff suppressed because it is too large Load Diff

View File

@ -57,9 +57,9 @@ H5P.ActionBar = (function ($, EventDispatcher) {
}; };
// Register action bar buttons // Register action bar buttons
if (displayOptions.export) { if (displayOptions.export || displayOptions.copy) {
// Add export button // Add export button
addActionButton('download', 'export'); addActionButton('reuse', 'export');
} }
if (displayOptions.copyright) { if (displayOptions.copyright) {
addActionButton('copyrights'); addActionButton('copyrights');

View File

@ -11,6 +11,10 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
* @param [options.dialogText] Dialog text * @param [options.dialogText] Dialog text
* @param [options.cancelText] Cancel dialog button text * @param [options.cancelText] Cancel dialog button text
* @param [options.confirmText] Confirm 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 * @constructor
*/ */
function ConfirmationDialog(options) { function ConfirmationDialog(options) {
@ -73,6 +77,12 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
// Create outer popup // Create outer popup
var popup = document.createElement('div'); var popup = document.createElement('div');
popup.classList.add('h5p-confirmation-dialog-popup', 'hidden'); 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('role', 'dialog');
popup.setAttribute('aria-labelledby', 'h5p-confirmation-dialog-dialog-text-' + uniqueId); popup.setAttribute('aria-labelledby', 'h5p-confirmation-dialog-dialog-text-' + uniqueId);
popupBackground.appendChild(popup); popupBackground.appendChild(popup);
@ -139,7 +149,14 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
flowTo(confirmButton, e); flowTo(confirmButton, e);
} }
}); });
if (!options.hideCancel) {
buttons.appendChild(cancelButton); buttons.appendChild(cancelButton);
}
else {
// Center buttons
buttons.classList.add('center');
}
// Confirm handler // Confirm handler
confirmButton.addEventListener('click', dialogConfirmed); confirmButton.addEventListener('click', dialogConfirmed);
@ -148,7 +165,8 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
dialogConfirmed(e); dialogConfirmed(e);
} }
else if (e.which === 9 && !e.shiftKey) { // Tab else if (e.which === 9 && !e.shiftKey) { // Tab
flowTo(cancelButton, e); const nextButton = !options.hideCancel ? cancelButton : confirmButton;
flowTo(nextButton, e);
} }
}); });
buttons.appendChild(confirmButton); buttons.appendChild(confirmButton);
@ -160,7 +178,9 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
dialogCanceled(e); dialogCanceled(e);
} }
}); });
if (!options.hideExit) {
popup.appendChild(exitButton); popup.appendChild(exitButton);
}
// Wrapper element // Wrapper element
var wrapperElement; var wrapperElement;
@ -272,10 +292,14 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
*/ */
var fitToContainer = function (offsetTop) { var fitToContainer = function (offsetTop) {
var popupOffsetTop = parseInt(popup.style.top, 10); var popupOffsetTop = parseInt(popup.style.top, 10);
if (offsetTop) { if (offsetTop !== undefined) {
popupOffsetTop = offsetTop; popupOffsetTop = offsetTop;
} }
if (!popupOffsetTop) {
popupOffsetTop = 0;
}
// Overflows height // Overflows height
if (popupOffsetTop + popup.offsetHeight > wrapperElement.offsetHeight) { if (popupOffsetTop + popup.offsetHeight > wrapperElement.offsetHeight) {
popupOffsetTop = wrapperElement.offsetHeight - popup.offsetHeight - shadowOffset; popupOffsetTop = wrapperElement.offsetHeight - popup.offsetHeight - shadowOffset;
@ -335,7 +359,9 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
// Restore focus // Restore focus
stopCapturingFocus(); stopCapturingFocus();
if (!options.skipRestoreFocus) {
previouslyFocused.focus(); previouslyFocused.focus();
}
restoreUnderlay(); restoreUnderlay();
setTimeout(function () { setTimeout(function () {
popupBackground.classList.add('hidden'); popupBackground.classList.add('hidden');
@ -346,6 +372,23 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
return this; 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 * Sets the minimum height of the view port
* *

View File

@ -27,6 +27,7 @@ H5P.ContentUpgradeProcess = (function (Version) {
self.loadLibrary = loadLibrary; self.loadLibrary = loadLibrary;
self.upgrade(name, oldVersion, newVersion, params.params, params.metadata, function (err, upgradedParams, upgradedMetadata) { self.upgrade(name, oldVersion, newVersion, params.params, params.metadata, function (err, upgradedParams, upgradedMetadata) {
if (err) { if (err) {
err.id = id;
return done(err); return done(err);
} }
@ -53,6 +54,12 @@ H5P.ContentUpgradeProcess = (function (Version) {
if (err) { if (err) {
return done(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 // Run upgrade routines on params
self.processParams(library, oldVersion, newVersion, params, metadata, function (err, params, metadata) { self.processParams(library, oldVersion, newVersion, params, metadata, function (err, params, metadata) {
@ -96,7 +103,7 @@ H5P.ContentUpgradeProcess = (function (Version) {
} }
// No upgrades script. Move on // No upgrades script. Move on
return next(null, params); return next(null, params, metadata);
} }
// Run upgrade hooks. Start by going through major versions // Run upgrade hooks. Start by going through major versions
@ -176,7 +183,11 @@ H5P.ContentUpgradeProcess = (function (Version) {
var usedVer = new Version(usedLib[1]); var usedVer = new Version(usedLib[1]);
var availableVer = new Version(availableLib[1]); var availableVer = new Version(availableLib[1]);
if (usedVer.major > availableVer.major || (usedVer.major === availableVer.major && usedVer.minor >= availableVer.minor)) { if (usedVer.major > availableVer.major || (usedVer.major === availableVer.major && usedVer.minor >= availableVer.minor)) {
return done(); // Larger or same version that's available 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 // A newer version is available, upgrade params
@ -192,7 +203,12 @@ H5P.ContentUpgradeProcess = (function (Version) {
}); });
} }
} }
done();
// Content type was not supporte by the higher version
done({
type: 'errorNotSupported',
used: usedLib[0] + ' ' + usedVer
});
break; break;
case 'group': case 'group':

View File

@ -1,7 +1,7 @@
/* global H5PAdminIntegration H5PUtils */ /* global H5PAdminIntegration H5PUtils */
(function ($, Version) { (function ($, Version) {
var info, $container, librariesCache = {}, scriptsCache = {}; var info, $log, $container, librariesCache = {}, scriptsCache = {};
// Initialize // Initialize
$(document).ready(function () { $(document).ready(function () {
@ -9,7 +9,9 @@
info = H5PAdminIntegration.libraryInfo; info = H5PAdminIntegration.libraryInfo;
// Get and reset container // 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 // Make it possible to select version
var $version = $(getVersionSelect(info.versions)).appendTo($container); var $version = $(getVersionSelect(info.versions)).appendTo($container);
@ -120,9 +122,7 @@
}, },
error: function (error) { error: function (error) {
self.printError(error.err); self.printError(error.err);
self.workDone(error.id, null, this);
// Stop everything
self.terminate();
}, },
loadLibrary: function (details) { loadLibrary: function (details) {
var worker = this; var worker = this;
@ -184,7 +184,7 @@
self.token = inData.token; self.token = inData.token;
// Start processing // Start processing
self.processBatch(inData.params); self.processBatch(inData.params, inData.skipped);
}); });
}; };
@ -202,11 +202,12 @@
* *
* @param {Object} parameters * @param {Object} parameters
*/ */
ContentUpgrade.prototype.processBatch = function (parameters) { ContentUpgrade.prototype.processBatch = function (parameters, skipped) {
var self = this; var self = this;
// Track upgraded params // Track upgraded params
self.upgraded = {}; self.upgraded = {};
self.skipped = skipped;
// Track current batch // Track current batch
self.parameters = parameters; self.parameters = parameters;
@ -276,7 +277,7 @@
}, function done(err, result) { }, function done(err, result) {
if (err) { if (err) {
self.printError(err); self.printError(err);
return ; result = null;
} }
self.workDone(id, result); self.workDone(id, result);
@ -291,7 +292,12 @@
var self = this; var self = this;
self.working--; self.working--;
if (result === null) {
self.skipped.push(id);
}
else {
self.upgraded[id] = result; self.upgraded[id] = result;
}
// Update progress message // Update progress message
self.throbber.setProgress(Math.round((info.total - self.left + self.current) / (info.total / 100)) + ' %'); self.throbber.setProgress(Math.round((info.total - self.left + self.current) / (info.total / 100)) + ' %');
@ -302,6 +308,7 @@
self.nextBatch({ self.nextBatch({
libraryId: self.version.libraryId, libraryId: self.version.libraryId,
token: self.token, token: self.token,
skipped: JSON.stringify(self.skipped),
params: JSON.stringify(self.upgraded) params: JSON.stringify(self.upgraded)
}); });
} }
@ -410,14 +417,29 @@
ContentUpgrade.prototype.printError = function (error) { ContentUpgrade.prototype.printError = function (error) {
var self = this; var self = this;
if (error.type === 'errorParamsBroken') { switch (error.type) {
case 'errorParamsBroken':
error = info.errorContent.replace('%id', error.id) + ' ' + info.errorParamsBroken; error = info.errorContent.replace('%id', error.id) + ' ' + info.errorParamsBroken;
} break;
else if (error.type === 'scriptMissing') {
case 'libraryMissing':
error = info.errorLibrary.replace('%lib', error.library);
break;
case 'scriptMissing':
error = info.errorScript.replace('%lib', error.library); error = info.errorScript.replace('%lib', error.library);
break;
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;
} }
self.setStatus('<p>' + info.error + '<br/>' + error + '</p>'); $('<li>' + info.error + '<br/>' + error + '</li>').appendTo($log);
}; };
})(H5P.jQuery, H5P.Version); })(H5P.jQuery, H5P.Version);

View File

@ -53,8 +53,18 @@ var H5PDataView = (function ($) {
self.filterOn = []; self.filterOn = [];
self.facets = {}; 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(); self.loadData();
} }
}
/** /**
* Load data from source URL. * Load data from source URL.
@ -151,6 +161,12 @@ var H5PDataView = (function ($) {
// Add filters // Add filters
self.addFilters(); 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 // Add facets
self.$facets = $('<div/>', { self.$facets = $('<div/>', {
'class': 'h5p-facet-wrapper', 'class': 'h5p-facet-wrapper',
@ -246,13 +262,17 @@ var H5PDataView = (function ($) {
appendTo: self.$facets, appendTo: self.$facets,
}) })
}; };
/** /**
* Callback for removing filter. * Callback for removing filter.
* *
* @private * @private
*/ */
var remove = function () { 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(); self.facets[col].$tag.remove();
delete self.facets[col]; delete self.facets[col];
self.loadData(); self.loadData();
@ -374,5 +394,49 @@ var H5PDataView = (function ($) {
}).appendTo(self.$container); }).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; return H5PDataView;
})(H5P.jQuery); })(H5P.jQuery);

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

@ -20,6 +20,10 @@
// Make iframe responsive // Make iframe responsive
iframe.style.width = '100%'; 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 // Tell iframe that it needs to resize when our window resizes
var resize = function () { var resize = function () {
if (iframe.contentWindow) { if (iframe.contentWindow) {

View File

@ -7,11 +7,24 @@ H5P.Version = (function () {
* @param {String} version * @param {String} version
*/ */
function Version(version) { function Version(version) {
var versionSplit = version.split('.', 3);
// Public if (typeof version === 'string') {
// Name version string (used by content upgrade)
var versionSplit = version.split('.', 3);
this.major =+ versionSplit[0]; this.major =+ versionSplit[0];
this.minor =+ versionSplit[1]; 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. * Public. Custom string for this object.

View File

@ -141,6 +141,18 @@ H5P.XAPIEvent.prototype.setObject = function (instance) {
} }
} }
} }
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: {}
};
}
}; };
/** /**
@ -239,7 +251,7 @@ H5P.XAPIEvent.prototype.getScore = function () {
*/ */
H5P.XAPIEvent.prototype.getContentXAPIId = function (instance) { H5P.XAPIEvent.prototype.getContentXAPIId = function (instance) {
var xAPIId; var xAPIId;
if (instance.contentId && H5PIntegration && H5PIntegration.contents) { if (instance.contentId && H5PIntegration && H5PIntegration.contents && H5PIntegration.contents['cid-' + instance.contentId]) {
xAPIId = H5PIntegration.contents['cid-' + instance.contentId].url; xAPIId = H5PIntegration.contents['cid-' + instance.contentId].url;
if (instance.subContentId) { if (instance.subContentId) {
xAPIId += '?subContentId=' + instance.subContentId; xAPIId += '?subContentId=' + instance.subContentId;
@ -312,6 +324,8 @@ H5P.XAPIEvent.allowedXAPIVerbs = [
// Custom verbs used for action toolbar below content // Custom verbs used for action toolbar below content
'downloaded', 'downloaded',
'copied',
'accessed-reuse',
'accessed-embed', 'accessed-embed',
'accessed-copyright' 'accessed-copyright'
]; ];

553
js/h5p.js
View File

@ -23,7 +23,7 @@ H5P.$window = H5P.jQuery(window);
H5P.instances = []; H5P.instances = [];
// Detect if we support fullscreen, and what prefix to use. // Detect if we support fullscreen, and what prefix to use.
if (document.documentElement.requestFullScreen) { if (document.documentElement.requestFullscreen) {
/** /**
* Browser prefix to use when entering fullscreen mode. * Browser prefix to use when entering fullscreen mode.
* undefined means no fullscreen support. * undefined means no fullscreen support.
@ -74,9 +74,10 @@ H5P.init = function (target) {
* fullscreen, and the semi-fullscreen solution doesn't work when embedded. * fullscreen, and the semi-fullscreen solution doesn't work when embedded.
* @type {boolean} * @type {boolean}
*/ */
H5P.fullscreenSupported = !(H5P.isFramed && H5P.externalEmbed !== false) || !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled); H5P.fullscreenSupported = !H5PIntegration.fullscreenDisabled && !H5P.fullscreenDisabled && (!(H5P.isFramed && H5P.externalEmbed !== false) || !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled));
// We should consider document.msFullscreenEnabled when they get their // -We should consider document.msFullscreenEnabled when they get their
// element sizing corrected. Ref. https://connect.microsoft.com/IE/feedback/details/838286/ie-11-incorrectly-reports-dom-element-sizes-in-fullscreen-mode-when-fullscreened-element-is-within-an-iframe // -element sizing corrected. Ref. https://connect.microsoft.com/IE/feedback/details/838286/ie-11-incorrectly-reports-dom-element-sizes-in-fullscreen-mode-when-fullscreened-element-is-within-an-iframe
// Update: Seems to be no need as they've moved on to Webkit
} }
// Deprecated variable, kept to maintain backwards compatability // Deprecated variable, kept to maintain backwards compatability
@ -123,6 +124,9 @@ H5P.init = function (target) {
}; };
$dialog.find('.h5p-dialog-ok-button').click(closeDialog).keypress(closeDialog); $dialog.find('.h5p-dialog-ok-button').click(closeDialog).keypress(closeDialog);
H5P.trigger(instance, 'resize');
}).on('dialog-closed', function () {
H5P.trigger(instance, 'resize');
}); });
dialog.open(); dialog.open();
} }
@ -132,6 +136,8 @@ H5P.init = function (target) {
// Create new instance. // Create new instance.
var instance = H5P.newRunnable(library, contentId, $container, true, {standalone: true}); var instance = H5P.newRunnable(library, contentId, $container, true, {standalone: true});
H5P.offlineRequestQueue = new H5P.OfflineRequestQueue({instance: instance});
// Check if we should add and display a fullscreen button for this H5P. // Check if we should add and display a fullscreen button for this H5P.
if (contentData.fullScreen == 1 && H5P.fullscreenSupported) { if (contentData.fullScreen == 1 && H5P.fullscreenSupported) {
H5P.jQuery( H5P.jQuery(
@ -139,6 +145,7 @@ H5P.init = function (target) {
'<div role="button" ' + '<div role="button" ' +
'tabindex="0" ' + 'tabindex="0" ' +
'class="h5p-enable-fullscreen" ' + 'class="h5p-enable-fullscreen" ' +
'aria-label="' + H5P.t('fullscreen') + '" ' +
'title="' + H5P.t('fullscreen') + '">' + 'title="' + H5P.t('fullscreen') + '">' +
'</div>' + '</div>' +
'</div>') '</div>')
@ -174,20 +181,20 @@ H5P.init = function (target) {
var actionBar = new H5P.ActionBar(displayOptions); var actionBar = new H5P.ActionBar(displayOptions);
var $actions = actionBar.getDOMElement(); var $actions = actionBar.getDOMElement();
actionBar.on('download', function () { actionBar.on('reuse', function () {
window.location.href = contentData.exportUrl; H5P.openReuseDialog($actions, contentData, library, instance, contentId);
instance.triggerXAPI('downloaded'); instance.triggerXAPI('accessed-reuse');
}); });
actionBar.on('copyrights', function () { actionBar.on('copyrights', function () {
var dialog = new H5P.Dialog('copyrights', H5P.t('copyrightInformation'), copyrights, $container); var dialog = new H5P.Dialog('copyrights', H5P.t('copyrightInformation'), copyrights, $container);
dialog.open(); dialog.open(true);
instance.triggerXAPI('accessed-copyright'); instance.triggerXAPI('accessed-copyright');
}); });
actionBar.on('embed', function () { actionBar.on('embed', function () {
H5P.openEmbedDialog($actions, contentData.embedCode, contentData.resizeCode, { H5P.openEmbedDialog($actions, contentData.embedCode, contentData.resizeCode, {
width: $element.width(), width: $element.width(),
height: $element.height() height: $element.height()
}); }, instance);
instance.triggerXAPI('accessed-embed'); instance.triggerXAPI('accessed-embed');
}); });
@ -258,6 +265,11 @@ H5P.init = function (target) {
var parentHeight = iframe.parentElement.style.height; var parentHeight = iframe.parentElement.style.height;
iframe.parentElement.style.height = iframe.parentElement.clientHeight + 'px'; iframe.parentElement.style.height = iframe.parentElement.clientHeight + 'px';
// Note: Force layout reflow
// This fixes a flickering bug for embedded content on iPads
// @see https://github.com/h5p/h5p-moodle-plugin/issues/237
iframe.getBoundingClientRect();
// Reset iframe height, in case content has shrinked. // Reset iframe height, in case content has shrinked.
iframe.style.height = '1px'; iframe.style.height = '1px';
@ -351,14 +363,43 @@ H5P.init = function (target) {
// Resize content. // Resize content.
H5P.trigger(instance, 'resize'); H5P.trigger(instance, 'resize');
// Logic for hiding focus effects when using mouse
$element.addClass('using-mouse');
$element.on('mousedown keydown keyup', function (event) {
$element.toggleClass('using-mouse', event.type === 'mousedown');
});
if (H5P.externalDispatcher) {
H5P.externalDispatcher.trigger('initialized');
}
}); });
// Insert H5Ps that should be in iframes. // Insert H5Ps that should be in iframes.
H5P.jQuery('iframe.h5p-iframe:not(.h5p-initialized)', target).each(function () { H5P.jQuery('iframe.h5p-iframe:not(.h5p-initialized)', target).each(function () {
var contentId = H5P.jQuery(this).addClass('h5p-initialized').data('content-id'); const iframe = this;
this.contentDocument.open(); const $iframe = H5P.jQuery(iframe);
this.contentDocument.write('<!doctype html><html class="h5p-iframe"><head>' + H5P.getHeadTags(contentId) + '</head><body><div class="h5p-content" data-content-id="' + contentId + '"/></body></html>');
this.contentDocument.close(); const contentId = $iframe.data('content-id');
const contentData = H5PIntegration.contents['cid-' + contentId];
const contentLanguage = contentData && contentData.metadata && contentData.metadata.defaultLanguage
? contentData.metadata.defaultLanguage : 'en';
const writeDocument = function () {
iframe.contentDocument.open();
iframe.contentDocument.write('<!doctype html><html class="h5p-iframe" lang="' + contentLanguage + '"><head>' + H5P.getHeadTags(contentId) + '</head><body><div class="h5p-content" data-content-id="' + contentId + '"/></body></html>');
iframe.contentDocument.close();
};
$iframe.addClass('h5p-initialized')
if (iframe.contentDocument === null) {
// In some Edge cases the iframe isn't always loaded when the page is ready.
$iframe.on('load', writeDocument);
$iframe.attr('src', 'about:blank');
}
else {
writeDocument();
}
}); });
}; };
@ -569,7 +610,7 @@ H5P.fullScreen = function ($element, instance, exitCallback, body, forceSemiFull
} }
before('h5p-semi-fullscreen'); before('h5p-semi-fullscreen');
var $disable = H5P.jQuery('<div role="button" tabindex="0" class="h5p-disable-fullscreen" title="' + H5P.t('disableFullscreen') + '"></div>').appendTo($container.find('.h5p-content-controls')); var $disable = H5P.jQuery('<div role="button" tabindex="0" class="h5p-disable-fullscreen" title="' + H5P.t('disableFullscreen') + '" aria-label="' + H5P.t('disableFullscreen') + '"></div>').appendTo($container.find('.h5p-content-controls'));
var keyup, disableSemiFullscreen = H5P.exitFullScreen = function () { var keyup, disableSemiFullscreen = H5P.exitFullScreen = function () {
if (prevViewportContent) { if (prevViewportContent) {
// Use content from the previous viewport tag // Use content from the previous viewport tag
@ -635,7 +676,7 @@ H5P.fullScreen = function ($element, instance, exitCallback, body, forceSemiFull
}); });
if (H5P.fullScreenBrowserPrefix === '') { if (H5P.fullScreenBrowserPrefix === '') {
$element[0].requestFullScreen(); $element[0].requestFullscreen();
} }
else { else {
var method = (H5P.fullScreenBrowserPrefix === 'ms' ? 'msRequestFullscreen' : H5P.fullScreenBrowserPrefix + 'RequestFullScreen'); var method = (H5P.fullScreenBrowserPrefix === 'ms' ? 'msRequestFullscreen' : H5P.fullScreenBrowserPrefix + 'RequestFullScreen');
@ -658,7 +699,98 @@ H5P.fullScreen = function ($element, instance, exitCallback, body, forceSemiFull
} }
}; };
/** (function () {
/**
* Helper for adding a query parameter to an existing path that may already
* contain one or a hash.
*
* @param {string} path
* @param {string} parameter
* @return {string}
*/
H5P.addQueryParameter = function (path, parameter) {
let newPath, secondSplit;
const firstSplit = path.split('?');
if (firstSplit[1]) {
// There is already an existing query
secondSplit = firstSplit[1].split('#');
newPath = firstSplit[0] + '?' + secondSplit[0] + '&';
}
else {
// No existing query, just need to take care of the hash
secondSplit = firstSplit[0].split('#');
newPath = secondSplit[0] + '?';
}
newPath += parameter;
if (secondSplit[1]) {
// Add back the hash
newPath += '#' + secondSplit[1];
}
return newPath;
};
/**
* Helper for setting the crossOrigin attribute + the complete correct source.
* Note: This will start loading the resource.
*
* @param {Element} element DOM element, typically img, video or audio
* @param {Object} source File object from parameters/json_content (created by H5PEditor)
* @param {number} contentId Needed to determine the complete correct file path
*/
H5P.setSource = function (element, source, contentId) {
let path = source.path;
const crossOrigin = H5P.getCrossOrigin(source);
if (crossOrigin) {
element.crossOrigin = crossOrigin;
if (H5PIntegration.crossoriginCacheBuster) {
// Some sites may want to add a cache buster in case the same resource
// is used elsewhere without the crossOrigin attribute
path = H5P.addQueryParameter(path, H5PIntegration.crossoriginCacheBuster);
}
}
else {
// In case this element has been used before.
element.removeAttribute('crossorigin');
}
element.src = H5P.getPath(path, contentId);
};
/**
* Check if the given path has a protocol.
*
* @private
* @param {string} path
* @return {string}
*/
var hasProtocol = function (path) {
return path.match(/^[a-z0-9]+:\/\//i);
};
/**
* Get the crossOrigin policy to use for img, video and audio tags on the current site.
*
* @param {Object|string} source File object from parameters/json_content - Can also be URL(deprecated usage)
* @returns {string|null} crossOrigin attribute value required by the source
*/
H5P.getCrossOrigin = function (source) {
if (typeof source !== 'object') {
// Deprecated usage.
return H5PIntegration.crossorigin && H5PIntegration.crossoriginRegex && source.match(H5PIntegration.crossoriginRegex) ? H5PIntegration.crossorigin : null;
}
if (H5PIntegration.crossorigin && !hasProtocol(source.path)) {
// This is a local file, use the local crossOrigin policy.
return H5PIntegration.crossorigin;
// Note: We cannot use this for all external sources since we do not know
// each server's individual policy. We could add support for a list of
// external sources and their policy later on.
}
};
/**
* Find the path to the content files based on the id of the content. * Find the path to the content files based on the id of the content.
* Also identifies and returns absolute paths. * Also identifies and returns absolute paths.
* *
@ -669,11 +801,7 @@ H5P.fullScreen = function ($element, instance, exitCallback, body, forceSemiFull
* @returns {string} * @returns {string}
* Complete URL to path. * Complete URL to path.
*/ */
H5P.getPath = function (path, contentId) { H5P.getPath = function (path, contentId) {
var hasProtocol = function (path) {
return path.match(/^[a-z0-9]+:\/\//i);
};
if (hasProtocol(path)) { if (hasProtocol(path)) {
return path; return path;
} }
@ -703,7 +831,8 @@ H5P.getPath = function (path, contentId) {
} }
return prefix + '/' + path; return prefix + '/' + path;
}; };
})();
/** /**
* THIS FUNCTION IS DEPRECATED, USE getPath INSTEAD * THIS FUNCTION IS DEPRECATED, USE getPath INSTEAD
@ -920,25 +1049,35 @@ H5P.t = function (key, vars, ns) {
H5P.Dialog = function (name, title, content, $element) { H5P.Dialog = function (name, title, content, $element) {
/** @alias H5P.Dialog# */ /** @alias H5P.Dialog# */
var self = this; var self = this;
var $dialog = H5P.jQuery('<div class="h5p-popup-dialog h5p-' + name + '-dialog">\ var $dialog = H5P.jQuery('<div class="h5p-popup-dialog h5p-' + name + '-dialog" role="dialog" tabindex="-1">\
<div class="h5p-inner">\ <div class="h5p-inner">\
<h2>' + title + '</h2>\ <h2>' + title + '</h2>\
<div class="h5p-scroll-content">' + content + '</div>\ <div class="h5p-scroll-content">' + content + '</div>\
<div class="h5p-close" role="button" tabindex="0" title="' + H5P.t('close') + '">\ <div class="h5p-close" role="button" tabindex="0" aria-label="' + H5P.t('close') + '" title="' + H5P.t('close') + '"></div>\
</div>\ </div>\
</div>') </div>')
.insertAfter($element) .insertAfter($element)
.click(function () { .click(function (e) {
if (e && e.originalEvent && e.originalEvent.preventClosing) {
return;
}
self.close(); self.close();
}) })
.children('.h5p-inner') .children('.h5p-inner')
.click(function () { .click(function (e) {
return false; e.originalEvent.preventClosing = true;
}) })
.find('.h5p-close') .find('.h5p-close')
.click(function () { .click(function () {
self.close(); self.close();
}) })
.keypress(function (e) {
if (e.which === 13 || e.which === 32) {
self.close();
return false;
}
})
.end() .end()
.find('a') .find('a')
.click(function (e) { .click(function (e) {
@ -950,11 +1089,15 @@ H5P.Dialog = function (name, title, content, $element) {
/** /**
* Opens the dialog. * Opens the dialog.
*/ */
self.open = function () { self.open = function (scrollbar) {
if (scrollbar) {
$dialog.css('height', '100%');
}
setTimeout(function () { setTimeout(function () {
$dialog.addClass('h5p-open'); // Fade in $dialog.addClass('h5p-open'); // Fade in
// Triggering an event, in case something has to be done after dialog has been opened. // Triggering an event, in case something has to be done after dialog has been opened.
H5P.jQuery(self).trigger('dialog-opened', [$dialog]); H5P.jQuery(self).trigger('dialog-opened', [$dialog]);
$dialog.focus();
}, 1); }, 1);
}; };
@ -965,6 +1108,9 @@ H5P.Dialog = function (name, title, content, $element) {
$dialog.removeClass('h5p-open'); // Fade out $dialog.removeClass('h5p-open'); // Fade out
setTimeout(function () { setTimeout(function () {
$dialog.remove(); $dialog.remove();
H5P.jQuery(self).trigger('dialog-closed', [$dialog]);
$element.attr('tabindex', '-1');
$element.focus();
}, 200); }, 200);
}; };
}; };
@ -1127,6 +1273,65 @@ H5P.buildMetadataCopyrights = function (metadata) {
} }
}; };
/**
* Display a dialog containing the download button and copy button.
*
* @param {H5P.jQuery} $element
* @param {Object} contentData
* @param {Object} library
* @param {Object} instance
* @param {number} contentId
*/
H5P.openReuseDialog = function ($element, contentData, library, instance, contentId) {
let html = '';
if (contentData.displayOptions.export) {
html += '<button type="button" class="h5p-big-button h5p-download-button"><div class="h5p-button-title">Download as an .h5p file</div><div class="h5p-button-description">.h5p files may be uploaded to any web-site where H5P content may be created.</div></button>';
}
if (contentData.displayOptions.export && contentData.displayOptions.copy) {
html += '<div class="h5p-horizontal-line-text"><span>or</span></div>';
}
if (contentData.displayOptions.copy) {
html += '<button type="button" class="h5p-big-button h5p-copy-button"><div class="h5p-button-title">Copy content</div><div class="h5p-button-description">Copied content may be pasted anywhere this content type is supported on this website.</div></button>';
}
const dialog = new H5P.Dialog('reuse', H5P.t('reuseContent'), html, $element);
// Selecting embed code when dialog is opened
H5P.jQuery(dialog).on('dialog-opened', function (e, $dialog) {
H5P.jQuery('<a href="https://h5p.org/node/442225" target="_blank">More Info</a>').click(function (e) {
e.stopPropagation();
}).appendTo($dialog.find('h2'));
$dialog.find('.h5p-download-button').click(function () {
window.location.href = contentData.exportUrl;
instance.triggerXAPI('downloaded');
dialog.close();
});
$dialog.find('.h5p-copy-button').click(function () {
const item = new H5P.ClipboardItem(library);
item.contentId = contentId;
H5P.setClipboard(item);
instance.triggerXAPI('copied');
dialog.close();
H5P.attachToastTo(
H5P.jQuery('.h5p-content:first')[0],
H5P.t('contentCopied'),
{
position: {
horizontal: 'centered',
vertical: 'centered',
noOverflowX: true
}
}
);
});
H5P.trigger(instance, 'resize');
}).on('dialog-closed', function () {
H5P.trigger(instance, 'resize');
});
dialog.open();
};
/** /**
* Display a dialog containing the embed code. * Display a dialog containing the embed code.
* *
@ -1141,9 +1346,9 @@ H5P.buildMetadataCopyrights = function (metadata) {
* @param {number} size.width * @param {number} size.width
* @param {number} size.height * @param {number} size.height
*/ */
H5P.openEmbedDialog = function ($element, embedCode, resizeCode, size) { H5P.openEmbedDialog = function ($element, embedCode, resizeCode, size, instance) {
var fullEmbedCode = embedCode + resizeCode; var fullEmbedCode = embedCode + resizeCode;
var dialog = new H5P.Dialog('embed', H5P.t('embed'), '<textarea class="h5p-embed-code-container" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>' + H5P.t('size') + ': <input type="text" value="' + Math.ceil(size.width) + '" class="h5p-embed-size"/> × <input type="text" value="' + Math.ceil(size.height) + '" class="h5p-embed-size"/> px<br/><div role="button" tabindex="0" class="h5p-expander">' + H5P.t('showAdvanced') + '</div><div class="h5p-expander-content"><p>' + H5P.t('advancedHelp') + '</p><textarea class="h5p-embed-code-container" autocorrect="off" autocapitalize="off" spellcheck="false">' + resizeCode + '</textarea></div>', $element); var dialog = new H5P.Dialog('embed', H5P.t('embed'), '<textarea class="h5p-embed-code-container" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>' + H5P.t('size') + ': <input aria-label="'+ H5P.t('width') +'" type="text" value="' + Math.ceil(size.width) + '" class="h5p-embed-size"/> × <input aria-label="'+ H5P.t('width') +'" type="text" value="' + Math.ceil(size.height) + '" class="h5p-embed-size"/> px<br/><div role="button" tabindex="0" class="h5p-expander">' + H5P.t('showAdvanced') + '</div><div class="h5p-expander-content"><p>' + H5P.t('advancedHelp') + '</p><textarea class="h5p-embed-code-container" autocorrect="off" autocapitalize="off" spellcheck="false">' + resizeCode + '</textarea></div>', $element);
// Selecting embed code when dialog is opened // Selecting embed code when dialog is opened
H5P.jQuery(dialog).on('dialog-opened', function (event, $dialog) { H5P.jQuery(dialog).on('dialog-opened', function (event, $dialog) {
@ -1151,15 +1356,7 @@ H5P.openEmbedDialog = function ($element, embedCode, resizeCode, size) {
var $scroll = $inner.find('.h5p-scroll-content'); var $scroll = $inner.find('.h5p-scroll-content');
var diff = $scroll.outerHeight() - $scroll.innerHeight(); var diff = $scroll.outerHeight() - $scroll.innerHeight();
var positionInner = function () { var positionInner = function () {
var height = $inner.height(); H5P.trigger(instance, 'resize');
if ($scroll[0].scrollHeight + diff > height) {
$inner.css('height', ''); // 100%
}
else {
$inner.css('height', 'auto');
height = $inner.height();
}
$inner.css('marginTop', '-' + (height / 2) + 'px');
}; };
// Handle changing of width/height // Handle changing of width/height
@ -1194,11 +1391,11 @@ H5P.openEmbedDialog = function ($element, embedCode, resizeCode, size) {
var $expander = H5P.jQuery(this); var $expander = H5P.jQuery(this);
var $content = $expander.next(); var $content = $expander.next();
if ($content.is(':visible')) { if ($content.is(':visible')) {
$expander.removeClass('h5p-open').text(H5P.t('showAdvanced')); $expander.removeClass('h5p-open').text(H5P.t('showAdvanced')).attr('aria-expanded', 'true');
$content.hide(); $content.hide();
} }
else { else {
$expander.addClass('h5p-open').text(H5P.t('hideAdvanced')); $expander.addClass('h5p-open').text(H5P.t('hideAdvanced')).attr('aria-expanded', 'false');
$content.show(); $content.show();
} }
$dialog.find('.h5p-embed-code-container').each(function () { $dialog.find('.h5p-embed-code-container').each(function () {
@ -1209,13 +1406,221 @@ H5P.openEmbedDialog = function ($element, embedCode, resizeCode, size) {
$dialog.find('.h5p-expander').click(expand).keypress(function (event) { $dialog.find('.h5p-expander').click(expand).keypress(function (event) {
if (event.keyCode === 32) { if (event.keyCode === 32) {
expand.apply(this); expand.apply(this);
return false;
} }
}); });
}).on('dialog-closed', function () {
H5P.trigger(instance, 'resize');
}); });
dialog.open(); dialog.open();
}; };
/**
* Show a toast message.
*
* The reference element could be dom elements the toast should be attached to,
* or e.g. the document body for general toast messages.
*
* @param {DOM} element Reference element to show toast message for.
* @param {string} message Message to show.
* @param {object} [config] Configuration.
* @param {string} [config.style=h5p-toast] Style name for the tooltip.
* @param {number} [config.duration=3000] Toast message length in ms.
* @param {object} [config.position] Relative positioning of the toast.
* @param {string} [config.position.horizontal=centered] [before|left|centered|right|after].
* @param {string} [config.position.vertical=below] [above|top|centered|bottom|below].
* @param {number} [config.position.offsetHorizontal=0] Extra horizontal offset.
* @param {number} [config.position.offsetVertical=0] Extra vetical offset.
* @param {boolean} [config.position.noOverflowLeft=false] True to prevent overflow left.
* @param {boolean} [config.position.noOverflowRight=false] True to prevent overflow right.
* @param {boolean} [config.position.noOverflowTop=false] True to prevent overflow top.
* @param {boolean} [config.position.noOverflowBottom=false] True to prevent overflow bottom.
* @param {boolean} [config.position.noOverflowX=false] True to prevent overflow left and right.
* @param {boolean} [config.position.noOverflowY=false] True to prevent overflow top and bottom.
* @param {object} [config.position.overflowReference=document.body] DOM reference for overflow.
*/
H5P.attachToastTo = function (element, message, config) {
if (element === undefined || message === undefined) {
return;
}
const eventPath = function (evt) {
var path = (evt.composedPath && evt.composedPath()) || evt.path;
var target = evt.target;
if (path != null) {
// Safari doesn't include Window, but it should.
return (path.indexOf(window) < 0) ? path.concat(window) : path;
}
if (target === window) {
return [window];
}
function getParents(node, memo) {
memo = memo || [];
var parentNode = node.parentNode;
if (!parentNode) {
return memo;
}
else {
return getParents(parentNode, memo.concat(parentNode));
}
}
return [target].concat(getParents(target), window);
};
/**
* Handle click while toast is showing.
*/
const clickHandler = function (event) {
/*
* A common use case will be to attach toasts to buttons that are clicked.
* The click would remove the toast message instantly without this check.
* Children of the clicked element are also ignored.
*/
var path = eventPath(event);
if (path.indexOf(element) !== -1) {
return;
}
clearTimeout(timer);
removeToast();
};
/**
* Remove the toast message.
*/
const removeToast = function () {
document.removeEventListener('click', clickHandler);
if (toast.parentNode) {
toast.parentNode.removeChild(toast);
}
};
/**
* Get absolute coordinates for the toast.
*
* @param {DOM} element Reference element to show toast message for.
* @param {DOM} toast Toast element.
* @param {object} [position={}] Relative positioning of the toast message.
* @param {string} [position.horizontal=centered] [before|left|centered|right|after].
* @param {string} [position.vertical=below] [above|top|centered|bottom|below].
* @param {number} [position.offsetHorizontal=0] Extra horizontal offset.
* @param {number} [position.offsetVertical=0] Extra vetical offset.
* @param {boolean} [position.noOverflowLeft=false] True to prevent overflow left.
* @param {boolean} [position.noOverflowRight=false] True to prevent overflow right.
* @param {boolean} [position.noOverflowTop=false] True to prevent overflow top.
* @param {boolean} [position.noOverflowBottom=false] True to prevent overflow bottom.
* @param {boolean} [position.noOverflowX=false] True to prevent overflow left and right.
* @param {boolean} [position.noOverflowY=false] True to prevent overflow top and bottom.
* @return {object}
*/
const getToastCoordinates = function (element, toast, position) {
position = position || {};
position.offsetHorizontal = position.offsetHorizontal || 0;
position.offsetVertical = position.offsetVertical || 0;
const toastRect = toast.getBoundingClientRect();
const elementRect = element.getBoundingClientRect();
let left = 0;
let top = 0;
// Compute horizontal position
switch (position.horizontal) {
case 'before':
left = elementRect.left - toastRect.width - position.offsetHorizontal;
break;
case 'after':
left = elementRect.left + elementRect.width + position.offsetHorizontal;
break;
case 'left':
left = elementRect.left + position.offsetHorizontal;
break;
case 'right':
left = elementRect.left + elementRect.width - toastRect.width - position.offsetHorizontal;
break;
case 'centered':
left = elementRect.left + elementRect.width / 2 - toastRect.width / 2 + position.offsetHorizontal;
break;
default:
left = elementRect.left + elementRect.width / 2 - toastRect.width / 2 + position.offsetHorizontal;
}
// Compute vertical position
switch (position.vertical) {
case 'above':
top = elementRect.top - toastRect.height - position.offsetVertical;
break;
case 'below':
top = elementRect.top + elementRect.height + position.offsetVertical;
break;
case 'top':
top = elementRect.top + position.offsetVertical;
break;
case 'bottom':
top = elementRect.top + elementRect.height - toastRect.height - position.offsetVertical;
break;
case 'centered':
top = elementRect.top + elementRect.height / 2 - toastRect.height / 2 + position.offsetVertical;
break;
default:
top = elementRect.top + elementRect.height + position.offsetVertical;
}
// Prevent overflow
const overflowElement = document.body;
const bounds = overflowElement.getBoundingClientRect();
if ((position.noOverflowLeft || position.noOverflowX) && (left < bounds.x)) {
left = bounds.x;
}
if ((position.noOverflowRight || position.noOverflowX) && ((left + toastRect.width) > (bounds.x + bounds.width))) {
left = bounds.x + bounds.width - toastRect.width;
}
if ((position.noOverflowTop || position.noOverflowY) && (top < bounds.y)) {
top = bounds.y;
}
if ((position.noOverflowBottom || position.noOverflowY) && ((top + toastRect.height) > (bounds.y + bounds.height))) {
left = bounds.y + bounds.height - toastRect.height;
}
return {left: left, top: top};
};
// Sanitization
config = config || {};
config.style = config.style || 'h5p-toast';
config.duration = config.duration || 3000;
// Build toast
const toast = document.createElement('div');
toast.setAttribute('id', config.style);
toast.classList.add('h5p-toast-disabled');
toast.classList.add(config.style);
const msg = document.createElement('span');
msg.innerHTML = message;
toast.appendChild(msg);
document.body.appendChild(toast);
// The message has to be set before getting the coordinates
const coordinates = getToastCoordinates(element, toast, config.position);
toast.style.left = Math.round(coordinates.left) + 'px';
toast.style.top = Math.round(coordinates.top) + 'px';
toast.classList.remove('h5p-toast-disabled');
const timer = setTimeout(removeToast, config.duration);
// The toast can also be removed by clicking somewhere
document.addEventListener('click', clickHandler);
};
/** /**
* Copyrights for a H5P Content Library. * Copyrights for a H5P Content Library.
* *
@ -1665,7 +2070,13 @@ H5P.libraryFromString = function (library) {
* The full path to the library. * The full path to the library.
*/ */
H5P.getLibraryPath = function (library) { H5P.getLibraryPath = function (library) {
return (H5PIntegration.libraryUrl !== undefined ? H5PIntegration.libraryUrl + '/' : H5PIntegration.url + '/libraries/') + library; if (H5PIntegration.urlLibraries !== undefined) {
// This is an override for those implementations that has a different libraries URL, e.g. Moodle
return H5PIntegration.urlLibraries + '/' + library;
}
else {
return H5PIntegration.url + '/libraries/' + library;
}
}; };
/** /**
@ -1787,13 +2198,17 @@ H5P.setFinished = function (contentId, score, maxScore, time) {
}; };
// Post the results // Post the results
H5P.jQuery.post(H5PIntegration.ajax.setFinished, { const data = {
contentId: contentId, contentId: contentId,
score: score, score: score,
maxScore: maxScore, maxScore: maxScore,
opened: toUnix(H5P.opened[contentId]), opened: toUnix(H5P.opened[contentId]),
finished: toUnix(new Date()), finished: toUnix(new Date()),
time: time time: time
};
H5P.jQuery.post(H5PIntegration.ajax.setFinished, data)
.fail(function () {
H5P.offlineRequestQueue.add(H5PIntegration.ajax.setFinished, data);
}); });
} }
}; };
@ -2024,19 +2439,6 @@ H5P.createTitle = function (rawTitle, maxLength) {
} }
}; };
/**
* Get crossorigin option that is set for site. Usefull for setting crossorigin policy for elements.
*
* @returns {string|null} Returns the string that should be set as crossorigin policy for elements or null if
* no policy is set.
*/
H5P.getCrossOrigin = function (url) {
var crossorigin = H5PIntegration.crossorigin;
var urlRegex = H5PIntegration.crossoriginRegex;
return crossorigin && urlRegex && url.match(urlRegex) ? crossorigin : null;
};
/** /**
* Async error handling. * Async error handling.
* *
@ -2212,23 +2614,13 @@ H5P.createTitle = function (rawTitle, maxLength) {
H5P.setClipboard(clipboardItem); H5P.setClipboard(clipboardItem);
}; };
/**
* This is a cache for pasted data to prevent parsing multiple times.
* @type {Object}
*/
var parsedClipboard = null;
/** /**
* Retrieve parsed clipboard data. * Retrieve parsed clipboard data.
* *
* @return {Object} * @return {Object}
*/ */
H5P.getClipboard = function () { H5P.getClipboard = function () {
if (!parsedClipboard) { return parseClipboard();
parsedClipboard = parseClipboard();
}
return parsedClipboard;
}; };
/** /**
@ -2239,9 +2631,6 @@ H5P.createTitle = function (rawTitle, maxLength) {
H5P.setClipboard = function (clipboardItem) { H5P.setClipboard = function (clipboardItem) {
localStorage.setItem('h5pClipboard', JSON.stringify(clipboardItem)); localStorage.setItem('h5pClipboard', JSON.stringify(clipboardItem));
// Clear cache
parsedClipboard = null;
// Trigger an event so all 'Paste' buttons may be enabled. // Trigger an event so all 'Paste' buttons may be enabled.
H5P.externalDispatcher.trigger('datainclipboard', {reset: false}); H5P.externalDispatcher.trigger('datainclipboard', {reset: false});
}; };
@ -2261,7 +2650,6 @@ H5P.createTitle = function (rawTitle, maxLength) {
* Get item from the H5P Clipboard. * Get item from the H5P Clipboard.
* *
* @private * @private
* @param {boolean} [skipUpdateFileUrls]
* @return {Object} * @return {Object}
*/ */
var parseClipboard = function () { var parseClipboard = function () {
@ -2279,10 +2667,10 @@ H5P.createTitle = function (rawTitle, maxLength) {
return; return;
} }
// Update file URLs // Update file URLs and reset content Ids
updateFileUrls(clipboardData.specific, function (path) { recursiveUpdate(clipboardData.specific, function (path) {
var isTmpFile = (path.substr(-4, 4) === '#tmp'); var isTmpFile = (path.substr(-4, 4) === '#tmp');
if (!isTmpFile && clipboardData.contentId) { if (!isTmpFile && clipboardData.contentId && !path.match(/^https?:\/\//i)) {
// Comes from existing content // Comes from existing content
if (H5PEditor.contentId) { if (H5PEditor.contentId) {
@ -2301,22 +2689,20 @@ H5P.createTitle = function (rawTitle, maxLength) {
if (clipboardData.generic) { if (clipboardData.generic) {
// Use reference instead of key // Use reference instead of key
clipboardData.generic = clipboardData.specific[clipboardData.generic]; clipboardData.generic = clipboardData.specific[clipboardData.generic];
// Avoid multiple content with same ID
delete clipboardData.generic.subContentId;
} }
return clipboardData; return clipboardData;
}; };
/** /**
* Update file URLs. Useful when copying content. * Update file URLs and reset content IDs.
* Useful when copying content.
* *
* @private * @private
* @param {object} params Reference * @param {object} params Reference
* @param {function} handler Modifies the path to work when pasted * @param {function} handler Modifies the path to work when pasted
*/ */
var updateFileUrls = function (params, handler) { var recursiveUpdate = function (params, handler) {
for (var prop in params) { for (var prop in params) {
if (params.hasOwnProperty(prop) && params[prop] instanceof Object) { if (params.hasOwnProperty(prop) && params[prop] instanceof Object) {
var obj = params[prop]; var obj = params[prop];
@ -2324,7 +2710,11 @@ H5P.createTitle = function (rawTitle, maxLength) {
obj.path = handler(obj.path); obj.path = handler(obj.path);
} }
else { else {
updateFileUrls(obj, handler); if (obj.library !== undefined && obj.subContentId !== undefined) {
// Avoid multiple content with same ID
delete obj.subContentId;
}
recursiveUpdate(obj, handler);
} }
} }
} }
@ -2336,9 +2726,6 @@ H5P.createTitle = function (rawTitle, maxLength) {
window.addEventListener('storage', function (event) { window.addEventListener('storage', function (event) {
// Pick up clipboard changes from other tabs // Pick up clipboard changes from other tabs
if (event.key === 'h5pClipboard') { if (event.key === 'h5pClipboard') {
// Clear cache
parsedClipboard = null;
// Trigger an event so all 'Paste' buttons may be enabled. // Trigger an event so all 'Paste' buttons may be enabled.
H5P.externalDispatcher.trigger('datainclipboard', {reset: event.newValue === null}); H5P.externalDispatcher.trigger('datainclipboard', {reset: event.newValue === null});
} }

33
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

@ -266,6 +266,20 @@ button.h5p-admin.disabled:hover {
display: none; 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"] { .h5p-data-view th[role="button"] {
cursor: pointer; cursor: pointer;
} }
@ -339,3 +353,6 @@ button.h5p-admin.disabled:hover {
.h5p-data-view .h5p-facet-tag > span:active { .h5p-data-view .h5p-facet-tag > span:active {
color: #d20000; color: #d20000;
} }
.content-upgrade-log {
color: red;
}

View File

@ -1,5 +1,5 @@
.h5p-confirmation-dialog-background { .h5p-confirmation-dialog-background {
position: absolute; position: fixed;
height: 100%; height: 100%;
width: 100%; width: 100%;
left: 0; left: 0;
@ -116,3 +116,68 @@ button.h5p-confirmation-dialog-exit:hover {
margin-top: -6px; margin-top: -6px;
display: inline-block; 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);
}
}

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

View File

@ -3,15 +3,27 @@
/* Custom H5P font to use for icons. */ /* Custom H5P font to use for icons. */
@font-face { @font-face {
font-family: 'h5p'; font-family: 'h5p';
src: url('../fonts/h5p-core-19.eot?cb8kvi'); src: url('../fonts/h5p-core-28.eot?h1atjl');
src: url('../fonts/h5p-core-19.eot?cb8kvi#iefix') format('embedded-opentype'), src: url('../fonts/h5p-core-28.eot?h1atjl#iefix') format('embedded-opentype'),
url('../fonts/h5p-core-19.ttf?cb8kvi') format('truetype'), url('../fonts/h5p-core-28.ttf?h1atjl') format('truetype'),
url('../fonts/h5p-core-19.woff?cb8kvi') format('woff'), url('../fonts/h5p-core-28.woff?h1atjl') format('woff'),
url('../fonts/h5p-core-19.svg?cb8kvi#h5p') format('svg'); url('../fonts/h5p-core-28.svg?h1atjl#h5p-core-28') format('svg');
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@font-face {
font-family: 'h5p-hub-publish';
src: url('../fonts/h5p-hub-publish.eot?wy8ylc');
src: url('../fonts/h5p-hub-publish.eot?wy8ylc#iefix') format('embedded-opentype'),
url('../fonts/h5p-hub-publish.ttf?wy8ylc') format('truetype'),
url('../fonts/h5p-hub-publish.woff?wy8ylc') format('woff'),
url('../fonts/h5p-hub-publish.svg?wy8ylc#h5p-hub') format('svg');
font-weight: normal;
font-style: normal;
font-display: block;
}
html.h5p-iframe, html.h5p-iframe > body { html.h5p-iframe, html.h5p-iframe > body {
font-family: Sans-Serif; /* Use the browser's default sans-serif font. (Since Heletica doesn't look nice on Windows, and Arial on OS X.) */ font-family: Sans-Serif; /* Use the browser's default sans-serif font. (Since Heletica doesn't look nice on Windows, and Arial on OS X.) */
width: 100%; width: 100%;
@ -43,6 +55,8 @@ html.h5p-iframe .h5p-content {
line-height: 1.5em; line-height: 1.5em;
width: 100%; width: 100%;
height: auto; height: auto;
-webkit-text-size-adjust: none;
text-size-adjust: none;
} }
html.h5p-iframe .h5p-fullscreen .h5p-content, html.h5p-iframe .h5p-fullscreen .h5p-content,
html.h5p-iframe .h5p-semi-fullscreen .h5p-content { html.h5p-iframe .h5p-semi-fullscreen .h5p-content {
@ -199,13 +213,13 @@ div.h5p-fullscreen {
background: none; background: none;
padding: 0 0.75em 0 0.25em; padding: 0 0.75em 0 0.25em;
vertical-align: top; vertical-align: top;
color: #999; color: #707070;
text-decoration: none; text-decoration: none;
outline: none; outline: none;
line-height: 23px; line-height: 22px;
} }
.h5p-actions > .h5p-button:hover { .h5p-actions > .h5p-button:hover {
color: #666; color: #333;
} }
.h5p-actions > .h5p-button:active, .h5p-actions > .h5p-button:active,
.h5p-actions > .h5p-button:focus, .h5p-actions > .h5p-button:focus,
@ -223,12 +237,12 @@ div.h5p-fullscreen {
.h5p-actions > .h5p-button:before { .h5p-actions > .h5p-button:before {
font-family: 'H5P'; font-family: 'H5P';
font-size: 20px; font-size: 20px;
line-height: 20px; line-height: 23px;
vertical-align: top; vertical-align: bottom;
padding-right: 0; padding-right: 0;
} }
.h5p-actions > .h5p-button.h5p-export:before { .h5p-actions > .h5p-button.h5p-export:before {
content: "\e893"; content: "\e90b";
} }
.h5p-actions > .h5p-button.h5p-copyrights:before { .h5p-actions > .h5p-button.h5p-copyrights:before {
content: "\e88f"; content: "\e88f";
@ -260,7 +274,7 @@ div.h5p-fullscreen {
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; min-height: 100%;
z-index: 100; z-index: 100;
padding: 2em; padding: 2em;
box-sizing: border-box; box-sizing: border-box;
@ -297,13 +311,20 @@ div.h5p-fullscreen {
padding: 0.325em 0.5em 0.25em; padding: 0.325em 0.5em 0.25em;
line-height: 1.25em; line-height: 1.25em;
border-bottom: 1px solid #ccc; border-bottom: 1px solid #ccc;
z-index: 2;
} }
.h5p-embed-dialog .h5p-inner { .h5p-popup-dialog .h5p-inner > h2 > a {
width: 300px; font-size: 12px;
margin-left: 1em;
}
.h5p-embed-dialog .h5p-inner,
.h5p-reuse-dialog .h5p-inner,
.h5p-content-user-data-reset-dialog .h5p-inner {
min-width: 316px;
max-width: 400px;
left: 50%; left: 50%;
top: 50%; top: 50%;
margin: 0 0 0 -150px; transform: translateX(-50%);
transition: margin 250ms linear 100ms;
} }
.h5p-embed-dialog .h5p-embed-code-container, .h5p-embed-dialog .h5p-embed-code-container,
.h5p-embed-size { .h5p-embed-size {
@ -339,11 +360,14 @@ div.h5p-fullscreen {
padding: 1em; padding: 1em;
box-sizing: border-box; box-sizing: border-box;
-moz-box-sizing: border-box; -moz-box-sizing: border-box;
height: 100%; color: #555555;
z-index: 1;
}
.h5p-popup-dialog.h5p-open .h5p-scroll-content {
overflow: auto; overflow: auto;
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
color: #555555; height: 100%;
} }
.h5p-popup-dialog .h5p-scroll-content::-webkit-scrollbar { .h5p-popup-dialog .h5p-scroll-content::-webkit-scrollbar {
width: 8px; width: 8px;
@ -357,11 +381,6 @@ div.h5p-fullscreen {
} }
.h5p-popup-dialog .h5p-close { .h5p-popup-dialog .h5p-close {
cursor: pointer; cursor: pointer;
outline:none
}
.h5p-popup-dialog .h5p-close:after {
font-family: 'H5P';
content: "\e894";
font-size: 2em; font-size: 2em;
position: absolute; position: absolute;
right: 0; right: 0;
@ -372,6 +391,11 @@ div.h5p-fullscreen {
color: #656565; color: #656565;
cursor: pointer; cursor: pointer;
text-indent: -0.065em; text-indent: -0.065em;
z-index: 3
}
.h5p-popup-dialog .h5p-close:after {
font-family: 'H5P';
content: "\e894";
} }
.h5p-popup-dialog .h5p-close:hover:after, .h5p-popup-dialog .h5p-close:hover:after,
.h5p-popup-dialog .h5p-close:focus:after { .h5p-popup-dialog .h5p-close:focus:after {
@ -402,7 +426,6 @@ div.h5p-fullscreen {
.h5p-expander { .h5p-expander {
cursor: pointer; cursor: pointer;
font-size: 1.125em; font-size: 1.125em;
outline: none;
margin: 0.5em 0 0; margin: 0.5em 0 0;
display: inline-block; display: inline-block;
} }
@ -455,3 +478,148 @@ div.h5p-fullscreen {
.h5p-dialog-ok-button:active { .h5p-dialog-ok-button:active {
background: #eeffee; background: #eeffee;
} }
.h5p-big-button {
line-height: 1.25;
display: block;
position: relative;
cursor: pointer;
width: 100%;
padding: 1em 1em 1em 3.75em;
text-align: left;
border: 1px solid #dedede;
background: linear-gradient(#ffffff, #f1f1f2);
border-radius: 0.25em;
}
.h5p-big-button:before {
font-family: 'h5p';
content: "\e893";
line-height: 1;
font-size: 3em;
color: #2747f7;
position: absolute;
left: 0.125em;
top: 0.125em;
}
.h5p-copy-button:before {
content: "\e905";
}
.h5p-big-button:hover {
border: 1px solid #2747f7;
background: #eff1fe;
}
.h5p-big-button:active {
border: 1px solid #dedede;
background: #dfe4fe;
}
.h5p-button-title {
color: #2747f7;
font-size: 15px;
font-weight: bold;
margin-bottom: 0.5em;
}
.h5p-button-description {
color: #757575;
}
.h5p-horizontal-line-text {
border-top: 1px solid #dadada;
line-height: 1;
color: #474747;
text-align: center;
position: relative;
margin: 1.25em 0;
}
.h5p-horizontal-line-text > span {
background: white;
padding: 0.5em;
position: absolute;
top: -1em;
left: 50%;
transform: translateX(-50%);
}
.h5p-toast {
font-size: 0.75em;
background-color: rgba(0, 0, 0, 0.9);
color: #fff;
z-index: 110;
position: absolute;
padding: 0 0.5em;
line-height: 2;
border-radius: 4px;
white-space: nowrap;
pointer-events: none;
top: 0;
opacity: 1;
visibility: visible;
transition: opacity 1s;
}
.h5p-toast-disabled {
opacity: 0;
visibility: hidden;
}
.h5p-content code,
.h5peditor code {
color: #3d3d3d;
background: #e0e0e0;
border-radius: 2px;
padding: 0 5px;
}
.h5p-content pre > code,
.h5peditor pre > code {
background-color: #fafafa;
padding: 5px;
display: block;
line-height: normal;
border: 1px solid #c7c7c7;
border-left-width: 4px;
max-width: 100%;
white-space: pre;
overflow: auto;
}
/* This is loaded as part of Core and not Editor since this needs to be outside the editor iframe */
.h5peditor-semi-fullscreen {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 101;
}
iframe.h5peditor-semi-fullscreen {
background: #fff;
z-index: 100001;
}
.h5p-content.using-mouse *:not(textarea):focus {
outline: none !important;
}
.h5p-content-hub-button:before {
font-family: "h5p";
margin-right: 0.5em;
font-size: 0.7em;
line-height: 1;
}
.h5p-content-hub-button.unpublish:before {
content: "\e916";
}
.h5p-content-hub-button.waiting:before,
.h5p-content-hub-button.sync:before {
content: "\e917";
}
.h5p-content-hub-button.waiting:before {
display: inline-block;
animation: rotate 2s linear infinite;
}
@keyframes rotate {
to {
transform: rotate(360deg);
}
}