Compare commits
222 Commits
HFP-2095-F
...
master
Author | SHA1 | Date |
---|---|---|
Ravi Majithia | c79f97a16f | |
Oliver Tacke | d3d003e978 | |
Ravi Majithia | 22115c0aea | |
Erik Langhaug | aaf26d584b | |
Frode Petterson | eeefc1228b | |
Erik Langhaug | 13ba87ed58 | |
Erik Langhaug | f9a20e908f | |
Thomas Marstrander | 4599291d7c | |
Frode Petterson | 1c12b7bbf7 | |
Frode Petterson | 588f096afe | |
Frode Petterson | affaa83b51 | |
Frode Petterson | db3da7a144 | |
Frode Petterson | 17e97d48db | |
Frode Petterson | efd98a719d | |
Frode Petterson | 0eca5935c0 | |
Thomas Marstrander | f6fef74651 | |
Thomas Marstrander | cc5a0b2e57 | |
Thomas Marstrander | fe3f4a504d | |
Thomas Marstrander | d2522e3800 | |
Thomas Marstrander | 4c543f3214 | |
Thomas Marstrander | 1d8f0e8dac | |
Thomas Marstrander | a0f1e1a527 | |
Thomas Marstrander | 0308e3a888 | |
Thomas Marstrander | 8ba1611575 | |
Thomas Marstrander | 951912d7c1 | |
Thomas Marstrander | 0c40e081e7 | |
Hannaes | 982d07f137 | |
Hannaes | 96d5b63b2e | |
Thomas Marstrander | 16e51c06f5 | |
Thomas Marstrander | 09e7a7cb0d | |
Thomas Marstrander | 9aacfa1780 | |
Frode Petterson | f1ddd3b3f5 | |
Frode Petterson | 90835b7345 | |
Thomas Marstrander | 1831312d41 | |
Frode Petterson | 47d4499377 | |
Frode Petterson | fdd2a618bc | |
Frode Petterson | 8a29796cab | |
Frode Petterson | aa6c909572 | |
Frode Petterson | 0ba2496c11 | |
Frode Petterson | dab4e5120d | |
Frode Petterson | d5be0158a4 | |
Frode Petterson | 4d7dccad3d | |
Frode Petterson | 160b86e9ae | |
Frode Petterson | aa5abe786e | |
Frode Petterson | 48c961b661 | |
Frode Petterson | d1450fc1bb | |
Erik Langhaug | 96a2c1ff91 | |
Hannaes | 4b76c7ff8f | |
Erik Langhaug | 720e6b29a2 | |
Paal Joergensen | a5c3dd6c4e | |
Hannaes | 832707dcaf | |
Erik Langhaug | ba98139ccb | |
Thomas Marstrander | ae7b82a34a | |
Erik Langhaug | 25deeac560 | |
Thomas Marstrander | 7538202500 | |
Thomas Marstrander | 0d7abe0e51 | |
Thomas Marstrander | 14bad68d70 | |
Thomas Marstrander | 917a9b6ccb | |
Thomas Marstrander | 67bce48842 | |
Frode Petterson | d90accc55e | |
Frode Petterson | a7f2054101 | |
Frode Petterson | 03fe25df5a | |
Frode Petterson | 7cb4419eb0 | |
Thomas Marstrander | 645058f03e | |
Thomas Marstrander | b47ae6de6e | |
Frode Petterson | e65b22f0d1 | |
Frode Petterson | 8b317fa5fe | |
Thomas Marstrander | 1a644dda11 | |
Thomas Marstrander | 16c71b444b | |
Thomas Marstrander | eb52ec25a0 | |
Thomas Marstrander | 3a2232e690 | |
Thomas Marstrander | fb6278744c | |
Thomas Marstrander | 35eb39c469 | |
Thomas Marstrander | 555442d37e | |
Thomas Marstrander | c472d5172d | |
Oliver Tacke | a80773e8d6 | |
Oliver Tacke | ce373203b0 | |
Frode Petterson | 196888bf3e | |
Pål Jørgensen | 743147698f | |
Pål Jørgensen | 3b2990f9b8 | |
Andrew Nicols | 2cb43ad147 | |
Andrew Nicols | acec5b0b33 | |
Paal Joergensen | df9d25a5b3 | |
Paal Joergensen | bea974e597 | |
Paal Joergensen | 866f94ea47 | |
Pål Jørgensen | 8432a88386 | |
Andrew Nicols | d392737f45 | |
Andrew Nicols | 668233fb95 | |
Pål Jørgensen | 4c973c3088 | |
Pål Jørgensen | 87f6f3c970 | |
Thomas | 42568106fc | |
Frode Petterson | 541f6d8415 | |
Frode Petterson | 143a44cef5 | |
Frode Petterson | 55b04018d7 | |
Eloy Lafuente (stronk7) | f6f6d0fb56 | |
Frode Petterson | f37231eb3a | |
Frode Petterson | 128fbbc532 | |
Frode Petterson | 8bf43081dd | |
Frode Petterson | ec518a6f67 | |
Frode Petterson | e635d33169 | |
Frode Petterson | 43605b14d6 | |
Frode Petterson | f08655cfb0 | |
Frode Petterson | 0293d2cdfb | |
Andrew Nicols | 34bc10184d | |
Thomas Marstrander | 9a658ba387 | |
Frode Petterson | 159f83f1b8 | |
Frode Petterson | 117668d0e5 | |
Oliver Tacke | bf10430671 | |
Sjoerd Zonneveld | 7d7b420b45 | |
Paal Joergensen | e6fa3d7e54 | |
Thomas Marstrander | 4d061aef7a | |
Thomas Marstrander | 058a9f0a71 | |
Frode Petterson | 9577c57f95 | |
Thomas Marstrander | 8cfd2f0519 | |
Paal Joergensen | 0922db6fab | |
Thomas Marstrander | 7a8f894c85 | |
Paal Joergensen | 7bc8666f30 | |
Paal Joergensen | 8ceb77e881 | |
Thomas Marstrander | 064391236a | |
Frode Petterson | 4a9ea77d47 | |
Frode Petterson | 03794f36dd | |
Frode Petterson | 9e749eda92 | |
Frode Petterson | 2c15047e50 | |
Frode Petterson | fec8953ba8 | |
Frode Petterson | 3570441801 | |
Frode Petterson | b9a1e5f404 | |
Paal Joergensen | 5d7b480c3b | |
Thomas Marstrander | 665e5d424a | |
Thomas Marstrander | 3b685a5520 | |
Thomas Marstrander | 38fc962625 | |
Frode Petterson | 70278d15f4 | |
Thomas Marstrander | 0b1aadbbca | |
Thomas Marstrander | 687f886e3d | |
Thomas Marstrander | 39d27ab9bb | |
Thomas Marstrander | ada2f4009d | |
Thomas Marstrander | 75453e872c | |
Thomas Marstrander | 49c48e29b3 | |
Thomas Marstrander | a934d5b3ec | |
Thomas Marstrander | e0eb03026a | |
Frode Petterson | 052ad0ea81 | |
Frode Petterson | 7a85c115db | |
Frode Petterson | cdb53c5cfd | |
Frode Petterson | ac5dba1e19 | |
Thomas Horn Sivertsen | 4525d6383f | |
Thomas Marstrander | d4931ec20a | |
Thomas Marstrander | 8f7742ab0b | |
Thomas Marstrander | cd869f8400 | |
Frode Petterson | 60fb6c96ca | |
Frode Petterson | 366d8f2a0b | |
Frode Petterson | d38b3b1e8a | |
Frode Petterson | bf9250d80b | |
Frode Petterson | d05bc94d92 | |
Frode Petterson | 71038f89ea | |
Thomas Marstrander | 1a09b1a30e | |
Frode Petterson | 7b7b35ea39 | |
Frode Petterson | 68e56dd8fd | |
Frode Petterson | e9d08b973a | |
Frode Petterson | 53adda67c2 | |
Frode Petterson | fc044630bc | |
Frode Petterson | 840f5dcb12 | |
Frode Petterson | a5f1b49f6b | |
Frode Petterson | b64292af09 | |
Frode Petterson | 47d049afb2 | |
Frode Petterson | 01550e7f11 | |
Frode Petterson | d3b5b07669 | |
Thomas Marstrander | 801f3f33c3 | |
Thomas Marstrander | 32b0840ca6 | |
Frode Petterson | 7ee0c3372b | |
Frode Petterson | 2b2184fa30 | |
Frode Petterson | 415e101064 | |
Frode Petterson | d1dd47be6f | |
Frode Petterson | aa723bcb40 | |
Frode Petterson | 741cd04d34 | |
Frode Petterson | e7a256da05 | |
Frode Petterson | f96d04cc27 | |
Frode Petterson | c9e1ac9347 | |
Frode Petterson | 9cf3f4aa7f | |
Frode Petterson | bee7c550d9 | |
Frode Petterson | b6080a1a00 | |
Oliver Tacke | bfb7b5600c | |
Oliver Tacke | c2d7b987cc | |
Frode Petterson | 8d30949969 | |
Frode Petterson | 9a7a343844 | |
Frode Petterson | f19ca76461 | |
Frode Petterson | 4a9c3c7881 | |
Frode Petterson | 6f4c4d9cc3 | |
Frode Petterson | 2b474699b2 | |
thomasmars | b43051c785 | |
Frode Petterson | 96694e4c70 | |
Frode Petterson | 57570db8d6 | |
Oliver Tacke | 0678126f82 | |
Frode Petterson | 152dfc0fb2 | |
Oliver Tacke | 48f3805f94 | |
Oliver Tacke | 2be06b2eb9 | |
Oliver Tacke | 132f25e14a | |
Frode Petterson | f2a9801879 | |
Frode Petterson | c438f9136e | |
Frode Petterson | 1cd7b67010 | |
Frode Petterson | ec9127d245 | |
Frode Petterson | f7f2479b2a | |
Paal Joergensen | a0e7bcd2af | |
Frode Petterson | 85b278bd52 | |
Frode Petterson | c8ddb305ab | |
Frode Petterson | 39fc577fd5 | |
Paal Joergensen | 512a0de321 | |
Paal Joergensen | 898d975921 | |
Frode Petterson | 6b3b3db575 | |
Frode Petterson | db022830a6 | |
Paal Joergensen | d9940b81e2 | |
Paal Joergensen | 715fa6f803 | |
Frode Petterson | e15f6d6678 | |
Oliver Tacke | 37c0593ff4 | |
Oliver Tacke | 066ea94b11 | |
Paal Joergensen | fd2ac997ef | |
Paal Joergensen | 2e305ded71 | |
Paal Joergensen | f661248b5a | |
Paal Joergensen | 82b50fc2f1 | |
Paal Joergensen | e316eff18d | |
Paal Joergensen | 85d2e2eb75 | |
Paal Joergensen | c4e52f4f29 | |
Paal Joergensen | 8dafa5db91 | |
thomasmars | 579ba96b49 |
|
@ -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.
|
@ -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=" " horiz-adv-x="512" d="" />
|
||||
<glyph unicode="" glyph-name="arrow-down" data-tags="arrow-down" d="M234 432.335h556l-278-278z" />
|
||||
<glyph unicode="" glyph-name="arrow-left" data-tags="arrow-left" d="M381 31.335v524l262-262z" />
|
||||
<glyph unicode="" glyph-name="colapse" data-tags="colapse" d="M512 490.002l256-256-60-60-196 196-196-196-60 60z" />
|
||||
<glyph unicode="" glyph-name="expand" data-tags="expand" d="M708 466.002l60-60-256-256-256 256 60 60 196-196z" />
|
||||
<glyph unicode="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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.
Binary file not shown.
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 97 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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=" " horiz-adv-x="512" d="" />
|
||||
<glyph unicode="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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="" 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 |
Binary file not shown.
Binary file not shown.
|
@ -311,13 +311,7 @@ class H5PDefaultStorage implements \H5PFileStorage {
|
|||
// Add filename to path
|
||||
$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;
|
||||
}
|
||||
|
@ -363,15 +357,14 @@ class H5PDefaultStorage implements \H5PFileStorage {
|
|||
* content from the current temporary upload folder to the editor path.
|
||||
*
|
||||
* @param string $source path to source directory
|
||||
* @param string $contentId Id of content
|
||||
*
|
||||
* @return object Object containing h5p json and content json data
|
||||
* @param string $contentId Id of contentarray
|
||||
*/
|
||||
public function moveContentDirectory($source, $contentId = NULL) {
|
||||
if ($source === NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO: Remove $contentId and never copy temporary files into content folder. JI-366
|
||||
if ($contentId === NULL || $contentId == 0) {
|
||||
$target = $this->getEditorPath();
|
||||
}
|
||||
|
@ -380,7 +373,7 @@ class H5PDefaultStorage implements \H5PFileStorage {
|
|||
$target = "{$this->path}/content/{$contentId}";
|
||||
}
|
||||
|
||||
$contentSource = $source . DIRECTORY_SEPARATOR . 'content';
|
||||
$contentSource = $source . '/' . 'content';
|
||||
$contentFiles = array_diff(scandir($contentSource), array('.','..', 'content.json'));
|
||||
foreach ($contentFiles as $file) {
|
||||
if (is_dir("{$contentSource}/{$file}")) {
|
||||
|
@ -391,14 +384,7 @@ class H5PDefaultStorage implements \H5PFileStorage {
|
|||
}
|
||||
}
|
||||
|
||||
// Successfully loaded content json of file into editor
|
||||
$h5pJson = $this->getContent($source . DIRECTORY_SEPARATOR . 'h5p.json');
|
||||
$contentJson = $this->getContent($contentSource . DIRECTORY_SEPARATOR . 'content.json');
|
||||
|
||||
return (object) array(
|
||||
'h5pJson' => $h5pJson,
|
||||
'contentJson' => $contentJson
|
||||
);
|
||||
// TODO: Return list of all files so that they can be marked as temporary. JI-366
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -459,11 +445,49 @@ class H5PDefaultStorage implements \H5PFileStorage {
|
|||
* @return bool
|
||||
*/
|
||||
public function hasPresave($libraryFolder, $developmentPath = null) {
|
||||
$path = is_null($developmentPath) ? 'libraries' . DIRECTORY_SEPARATOR . $libraryFolder : $developmentPath;
|
||||
$filePath = realpath($this->path . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . 'presave.js');
|
||||
$path = is_null($developmentPath) ? 'libraries' . '/' . $libraryFolder : $developmentPath;
|
||||
$filePath = realpath($this->path . '/' . $path . '/' . 'presave.js');
|
||||
return file_exists($filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if upgrades script exist for library.
|
||||
*
|
||||
* @param string $machineName
|
||||
* @param int $majorVersion
|
||||
* @param int $minorVersion
|
||||
* @return string Relative path
|
||||
*/
|
||||
public function getUpgradeScript($machineName, $majorVersion, $minorVersion) {
|
||||
$upgrades = "/libraries/{$machineName}-{$majorVersion}.{$minorVersion}/upgrades.js";
|
||||
if (file_exists($this->path . $upgrades)) {
|
||||
return $upgrades;
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the given stream into the given file.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $file
|
||||
* @param resource $stream
|
||||
* @return bool
|
||||
*/
|
||||
public function saveFileFromZip($path, $file, $stream) {
|
||||
$filePath = $path . '/' . $file;
|
||||
|
||||
// Make sure the directory exists first
|
||||
$matches = array();
|
||||
preg_match('/(.+)\/[^\/]*$/', $filePath, $matches);
|
||||
self::dirReady($matches[1]);
|
||||
|
||||
// Store in local storage folder
|
||||
return file_put_contents($filePath, $stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive function for copying directories.
|
||||
*
|
||||
|
|
|
@ -67,7 +67,7 @@ class H5PDevelopment {
|
|||
$contents = scandir($path);
|
||||
|
||||
for ($i = 0, $s = count($contents); $i < $s; $i++) {
|
||||
if ($contents[$i]{0} === '.') {
|
||||
if ($contents[$i][0] === '.') {
|
||||
continue; // Skip hidden stuff.
|
||||
}
|
||||
|
||||
|
|
|
@ -199,4 +199,24 @@ interface H5PFileStorage {
|
|||
* @return bool
|
||||
*/
|
||||
public function hasPresave($libraryName, $developmentPath = null);
|
||||
|
||||
/**
|
||||
* Check if upgrades script exist for library.
|
||||
*
|
||||
* @param string $machineName
|
||||
* @param int $majorVersion
|
||||
* @param int $minorVersion
|
||||
* @return string Relative path
|
||||
*/
|
||||
public function getUpgradeScript($machineName, $majorVersion, $minorVersion);
|
||||
|
||||
/**
|
||||
* Store the given stream into the given file.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $file
|
||||
* @param resource $stream
|
||||
* @return bool
|
||||
*/
|
||||
public function saveFileFromZip($path, $file, $stream);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,10 @@ abstract class H5PMetadata {
|
|||
'type' => 'text',
|
||||
'maxLength' => 255
|
||||
),
|
||||
'a11yTitle' => array(
|
||||
'type' => 'text',
|
||||
'maxLength' => 255,
|
||||
),
|
||||
'authors' => array(
|
||||
'type' => 'json'
|
||||
),
|
||||
|
@ -40,6 +44,10 @@ abstract class H5PMetadata {
|
|||
),
|
||||
'yearTo' => array(
|
||||
'type' => 'int'
|
||||
),
|
||||
'defaultLanguage' => array(
|
||||
'type' => 'text',
|
||||
'maxLength' => 32,
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -53,6 +61,7 @@ abstract class H5PMetadata {
|
|||
// Note: deliberatly creating JSON string "manually" to improve performance
|
||||
return
|
||||
'{"title":' . (isset($content->title) ? json_encode($content->title) : 'null') .
|
||||
',"a11yTitle":' . (isset($content->a11y_title) ? $content->a11y_title : 'null') .
|
||||
',"authors":' . (isset($content->authors) ? $content->authors : 'null') .
|
||||
',"source":' . (isset($content->source) ? '"' . $content->source . '"' : 'null') .
|
||||
',"license":' . (isset($content->license) ? '"' . $content->license . '"' : 'null') .
|
||||
|
@ -61,18 +70,20 @@ abstract class H5PMetadata {
|
|||
',"yearFrom":' . (isset($content->year_from) ? $content->year_from : 'null') .
|
||||
',"yearTo":' . (isset($content->year_to) ? $content->year_to : 'null') .
|
||||
',"changes":' . (isset($content->changes) ? $content->changes : 'null') .
|
||||
',"defaultLanguage":' . (isset($content->default_language) ? '"' . $content->default_language . '"' : 'null') .
|
||||
',"authorComments":' . (isset($content->author_comments) ? json_encode($content->author_comments) : 'null') . '}';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make the metadata into an associative array keyed by the property names
|
||||
* @param mixed $metadata Array or object containing metadata
|
||||
* @param bool $include_title
|
||||
* @param bool $include_missing For metadata fields not being set, skip 'em.
|
||||
* Relevant for content upgrade
|
||||
* @param array $types
|
||||
* @return array
|
||||
*/
|
||||
public static function toDBArray($metadata, $include_title = true, &$types = array()) {
|
||||
public static function toDBArray($metadata, $include_title = true, $include_missing = true, &$types = array()) {
|
||||
$fields = array();
|
||||
|
||||
if (!is_array($metadata)) {
|
||||
|
@ -81,35 +92,43 @@ abstract class H5PMetadata {
|
|||
|
||||
foreach (self::$fields as $key => $config) {
|
||||
|
||||
// Ignore title?
|
||||
if ($key === 'title' && !$include_title) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($metadata[$key])) {
|
||||
$value = $metadata[$key];
|
||||
$db_field_name = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $key));
|
||||
$exists = array_key_exists($key, $metadata);
|
||||
|
||||
switch ($config['type']) {
|
||||
case 'text':
|
||||
if (strlen($value) > $config['maxLength']) {
|
||||
$value = mb_substr($value, 0, $config['maxLength']);
|
||||
}
|
||||
$types[] = '%s';
|
||||
break;
|
||||
|
||||
case 'int':
|
||||
$value = ($value !== null) ? intval($value): null;
|
||||
$types[] = '%d';
|
||||
break;
|
||||
|
||||
case 'json':
|
||||
$value = json_encode($value);
|
||||
$types[] = '%s';
|
||||
break;
|
||||
}
|
||||
|
||||
$fields[$db_field_name] = $value;
|
||||
// Don't include missing fields
|
||||
if (!$include_missing && !$exists) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$value = $exists ? $metadata[$key] : null;
|
||||
|
||||
// lowerCamelCase to snake_case
|
||||
$db_field_name = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $key));
|
||||
|
||||
switch ($config['type']) {
|
||||
case 'text':
|
||||
if ($value !== null && strlen($value) > $config['maxLength']) {
|
||||
$value = mb_substr($value, 0, $config['maxLength']);
|
||||
}
|
||||
$types[] = '%s';
|
||||
break;
|
||||
|
||||
case 'int':
|
||||
$value = ($value !== null) ? intval($value) : null;
|
||||
$types[] = '%d';
|
||||
break;
|
||||
|
||||
case 'json':
|
||||
$value = ($value !== null) ? json_encode($value) : null;
|
||||
$types[] = '%s';
|
||||
break;
|
||||
}
|
||||
|
||||
$fields[$db_field_name] = $value;
|
||||
}
|
||||
|
||||
return $fields;
|
||||
|
@ -128,7 +147,7 @@ abstract class H5PMetadata {
|
|||
if (isset($metadataSettings['disable'])) {
|
||||
$metadataSettings['disable'] = $metadataSettings['disable'] === 1;
|
||||
}
|
||||
if (isset($metadataSettings['disable'])) {
|
||||
if (isset($metadataSettings['disableExtraTitleField'])) {
|
||||
$metadataSettings['disableExtraTitleField'] = $metadataSettings['disableExtraTitleField'] === 1;
|
||||
}
|
||||
|
||||
|
|
1119
h5p.classes.php
1119
h5p.classes.php
File diff suppressed because it is too large
Load Diff
|
@ -57,9 +57,9 @@ H5P.ActionBar = (function ($, EventDispatcher) {
|
|||
};
|
||||
|
||||
// Register action bar buttons
|
||||
if (displayOptions.export) {
|
||||
if (displayOptions.export || displayOptions.copy) {
|
||||
// Add export button
|
||||
addActionButton('download', 'export');
|
||||
addActionButton('reuse', 'export');
|
||||
}
|
||||
if (displayOptions.copyright) {
|
||||
addActionButton('copyrights');
|
||||
|
|
|
@ -11,6 +11,10 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
|
|||
* @param [options.dialogText] Dialog text
|
||||
* @param [options.cancelText] Cancel dialog button text
|
||||
* @param [options.confirmText] Confirm dialog button text
|
||||
* @param [options.hideCancel] Hide cancel button
|
||||
* @param [options.hideExit] Hide exit button
|
||||
* @param [options.skipRestoreFocus] Skip restoring focus when hiding the dialog
|
||||
* @param [options.classes] Extra classes for popup
|
||||
* @constructor
|
||||
*/
|
||||
function ConfirmationDialog(options) {
|
||||
|
@ -73,6 +77,12 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
|
|||
// Create outer popup
|
||||
var popup = document.createElement('div');
|
||||
popup.classList.add('h5p-confirmation-dialog-popup', 'hidden');
|
||||
if (options.classes) {
|
||||
options.classes.forEach(function (popupClass) {
|
||||
popup.classList.add(popupClass);
|
||||
});
|
||||
}
|
||||
|
||||
popup.setAttribute('role', 'dialog');
|
||||
popup.setAttribute('aria-labelledby', 'h5p-confirmation-dialog-dialog-text-' + uniqueId);
|
||||
popupBackground.appendChild(popup);
|
||||
|
@ -139,7 +149,14 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
|
|||
flowTo(confirmButton, e);
|
||||
}
|
||||
});
|
||||
buttons.appendChild(cancelButton);
|
||||
|
||||
if (!options.hideCancel) {
|
||||
buttons.appendChild(cancelButton);
|
||||
}
|
||||
else {
|
||||
// Center buttons
|
||||
buttons.classList.add('center');
|
||||
}
|
||||
|
||||
// Confirm handler
|
||||
confirmButton.addEventListener('click', dialogConfirmed);
|
||||
|
@ -148,7 +165,8 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
|
|||
dialogConfirmed(e);
|
||||
}
|
||||
else if (e.which === 9 && !e.shiftKey) { // Tab
|
||||
flowTo(cancelButton, e);
|
||||
const nextButton = !options.hideCancel ? cancelButton : confirmButton;
|
||||
flowTo(nextButton, e);
|
||||
}
|
||||
});
|
||||
buttons.appendChild(confirmButton);
|
||||
|
@ -160,7 +178,9 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
|
|||
dialogCanceled(e);
|
||||
}
|
||||
});
|
||||
popup.appendChild(exitButton);
|
||||
if (!options.hideExit) {
|
||||
popup.appendChild(exitButton);
|
||||
}
|
||||
|
||||
// Wrapper element
|
||||
var wrapperElement;
|
||||
|
@ -272,10 +292,14 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
|
|||
*/
|
||||
var fitToContainer = function (offsetTop) {
|
||||
var popupOffsetTop = parseInt(popup.style.top, 10);
|
||||
if (offsetTop) {
|
||||
if (offsetTop !== undefined) {
|
||||
popupOffsetTop = offsetTop;
|
||||
}
|
||||
|
||||
if (!popupOffsetTop) {
|
||||
popupOffsetTop = 0;
|
||||
}
|
||||
|
||||
// Overflows height
|
||||
if (popupOffsetTop + popup.offsetHeight > wrapperElement.offsetHeight) {
|
||||
popupOffsetTop = wrapperElement.offsetHeight - popup.offsetHeight - shadowOffset;
|
||||
|
@ -335,7 +359,9 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
|
|||
|
||||
// Restore focus
|
||||
stopCapturingFocus();
|
||||
previouslyFocused.focus();
|
||||
if (!options.skipRestoreFocus) {
|
||||
previouslyFocused.focus();
|
||||
}
|
||||
restoreUnderlay();
|
||||
setTimeout(function () {
|
||||
popupBackground.classList.add('hidden');
|
||||
|
@ -346,12 +372,29 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
|
|||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve element
|
||||
*
|
||||
* @return {HTMLElement}
|
||||
*/
|
||||
this.getElement = function () {
|
||||
return popup;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get previously focused element
|
||||
* @return {HTMLElement}
|
||||
*/
|
||||
this.getPreviouslyFocused = function () {
|
||||
return previouslyFocused;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the minimum height of the view port
|
||||
*
|
||||
* @param {number|null} minHeight
|
||||
*/
|
||||
this.setViewPortMinimumHeight = function(minHeight) {
|
||||
this.setViewPortMinimumHeight = function (minHeight) {
|
||||
var container = document.querySelector('.h5p-container') || document.body;
|
||||
container.style.minHeight = (typeof minHeight === 'number') ? (minHeight + 'px') : minHeight;
|
||||
};
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
* @class
|
||||
* @augments H5P.EventDispatcher
|
||||
*/
|
||||
H5P.ContentType = function (isRootLibrary, library) {
|
||||
H5P.ContentType = function (isRootLibrary) {
|
||||
|
||||
function ContentType() {}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ H5P.ContentUpgradeProcess = (function (Version) {
|
|||
self.loadLibrary = loadLibrary;
|
||||
self.upgrade(name, oldVersion, newVersion, params.params, params.metadata, function (err, upgradedParams, upgradedMetadata) {
|
||||
if (err) {
|
||||
err.id = id;
|
||||
return done(err);
|
||||
}
|
||||
|
||||
|
@ -53,6 +54,12 @@ H5P.ContentUpgradeProcess = (function (Version) {
|
|||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
if (library.semantics === null) {
|
||||
return done({
|
||||
type: 'libraryMissing',
|
||||
library: library.name + ' ' + library.version.major + '.' + library.version.minor
|
||||
});
|
||||
}
|
||||
|
||||
// Run upgrade routines on params
|
||||
self.processParams(library, oldVersion, newVersion, params, metadata, function (err, params, metadata) {
|
||||
|
@ -96,7 +103,7 @@ H5P.ContentUpgradeProcess = (function (Version) {
|
|||
}
|
||||
|
||||
// No upgrades script. Move on
|
||||
return next(null, params);
|
||||
return next(null, params, metadata);
|
||||
}
|
||||
|
||||
// Run upgrade hooks. Start by going through major versions
|
||||
|
@ -127,10 +134,10 @@ H5P.ContentUpgradeProcess = (function (Version) {
|
|||
}, {metadata: metadata});
|
||||
}
|
||||
catch (err) {
|
||||
if (console && console.log) {
|
||||
console.log("Error", err.stack);
|
||||
console.log("Error", err.name);
|
||||
console.log("Error", err.message);
|
||||
if (console && console.error) {
|
||||
console.error("Error", err.stack);
|
||||
console.error("Error", err.name);
|
||||
console.error("Error", err.message);
|
||||
}
|
||||
next(err);
|
||||
}
|
||||
|
@ -176,7 +183,11 @@ H5P.ContentUpgradeProcess = (function (Version) {
|
|||
var usedVer = new Version(usedLib[1]);
|
||||
var availableVer = new Version(availableLib[1]);
|
||||
if (usedVer.major > availableVer.major || (usedVer.major === availableVer.major && usedVer.minor >= availableVer.minor)) {
|
||||
return done(); // 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
|
||||
|
@ -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;
|
||||
|
||||
case 'group':
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* global importScripts */
|
||||
var H5P = H5P || {};
|
||||
importScripts('h5p-version.js', 'h5p-content-upgrade-process.js');
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*jshint -W083 */
|
||||
/* global H5PAdminIntegration H5PUtils */
|
||||
|
||||
(function ($, Version) {
|
||||
var info, $container, librariesCache = {}, scriptsCache = {};
|
||||
var info, $log, $container, librariesCache = {}, scriptsCache = {};
|
||||
|
||||
// Initialize
|
||||
$(document).ready(function () {
|
||||
|
@ -9,7 +9,9 @@
|
|||
info = H5PAdminIntegration.libraryInfo;
|
||||
|
||||
// Get and reset container
|
||||
$container = $('#h5p-admin-container').html('<p>' + info.message + '</p>');
|
||||
const $wrapper = $('#h5p-admin-container').html('');
|
||||
$log = $('<ul class="content-upgrade-log"></ul>').appendTo($wrapper);
|
||||
$container = $('<div><p>' + info.message + '</p></div>').appendTo($wrapper);
|
||||
|
||||
// Make it possible to select version
|
||||
var $version = $(getVersionSelect(info.versions)).appendTo($container);
|
||||
|
@ -120,9 +122,7 @@
|
|||
},
|
||||
error: function (error) {
|
||||
self.printError(error.err);
|
||||
|
||||
// Stop everything
|
||||
self.terminate();
|
||||
self.workDone(error.id, null, this);
|
||||
},
|
||||
loadLibrary: function (details) {
|
||||
var worker = this;
|
||||
|
@ -184,7 +184,7 @@
|
|||
self.token = inData.token;
|
||||
|
||||
// Start processing
|
||||
self.processBatch(inData.params);
|
||||
self.processBatch(inData.params, inData.skipped);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -202,11 +202,12 @@
|
|||
*
|
||||
* @param {Object} parameters
|
||||
*/
|
||||
ContentUpgrade.prototype.processBatch = function (parameters) {
|
||||
ContentUpgrade.prototype.processBatch = function (parameters, skipped) {
|
||||
var self = this;
|
||||
|
||||
// Track upgraded params
|
||||
self.upgraded = {};
|
||||
self.skipped = skipped;
|
||||
|
||||
// Track current batch
|
||||
self.parameters = parameters;
|
||||
|
@ -276,7 +277,7 @@
|
|||
}, function done(err, result) {
|
||||
if (err) {
|
||||
self.printError(err);
|
||||
return ;
|
||||
result = null;
|
||||
}
|
||||
|
||||
self.workDone(id, result);
|
||||
|
@ -291,7 +292,12 @@
|
|||
var self = this;
|
||||
|
||||
self.working--;
|
||||
self.upgraded[id] = result;
|
||||
if (result === null) {
|
||||
self.skipped.push(id);
|
||||
}
|
||||
else {
|
||||
self.upgraded[id] = result;
|
||||
}
|
||||
|
||||
// Update progress message
|
||||
self.throbber.setProgress(Math.round((info.total - self.left + self.current) / (info.total / 100)) + ' %');
|
||||
|
@ -302,6 +308,7 @@
|
|||
self.nextBatch({
|
||||
libraryId: self.version.libraryId,
|
||||
token: self.token,
|
||||
skipped: JSON.stringify(self.skipped),
|
||||
params: JSON.stringify(self.upgraded)
|
||||
});
|
||||
}
|
||||
|
@ -410,14 +417,29 @@
|
|||
ContentUpgrade.prototype.printError = function (error) {
|
||||
var self = this;
|
||||
|
||||
if (error.type === 'errorParamsBroken') {
|
||||
error = info.errorContent.replace('%id', error.id) + ' ' + info.errorParamsBroken;
|
||||
}
|
||||
else if (error.type === 'scriptMissing') {
|
||||
error = info.errorScript.replace('%lib', error.library);
|
||||
switch (error.type) {
|
||||
case 'errorParamsBroken':
|
||||
error = info.errorContent.replace('%id', error.id) + ' ' + info.errorParamsBroken;
|
||||
break;
|
||||
|
||||
case 'libraryMissing':
|
||||
error = info.errorLibrary.replace('%lib', error.library);
|
||||
break;
|
||||
|
||||
case 'scriptMissing':
|
||||
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);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* global H5PUtils */
|
||||
var H5PDataView = (function ($) {
|
||||
|
||||
/**
|
||||
|
@ -52,7 +53,17 @@ var H5PDataView = (function ($) {
|
|||
self.filterOn = [];
|
||||
self.facets = {};
|
||||
|
||||
self.loadData();
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,6 +161,12 @@ var H5PDataView = (function ($) {
|
|||
// Add filters
|
||||
self.addFilters();
|
||||
|
||||
// Add toggler for others' content
|
||||
if (H5PIntegration.user && parseInt(H5PIntegration.user.canToggleViewOthersH5PContents) > 0) {
|
||||
// canToggleViewOthersH5PContents = 1 is setting for only showing current user's contents
|
||||
self.addOthersContentToggler(parseInt(H5PIntegration.user.canToggleViewOthersH5PContents) === 1);
|
||||
}
|
||||
|
||||
// Add facets
|
||||
self.$facets = $('<div/>', {
|
||||
'class': 'h5p-facet-wrapper',
|
||||
|
@ -198,7 +215,6 @@ var H5PDataView = (function ($) {
|
|||
* @param number col ID of column
|
||||
*/
|
||||
H5PDataView.prototype.createFacets = function (input, col) {
|
||||
var self = this;
|
||||
var facets = '';
|
||||
|
||||
if (input instanceof Array) {
|
||||
|
@ -246,13 +262,17 @@ var H5PDataView = (function ($) {
|
|||
appendTo: self.$facets,
|
||||
})
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback for removing filter.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
var remove = function () {
|
||||
// Uncheck toggler for others' H5P contents
|
||||
if ( self.$othersContentToggler && self.facets.hasOwnProperty( self.columnIdAuthor ) ) {
|
||||
self.$othersContentToggler.prop('checked', false );
|
||||
}
|
||||
|
||||
self.facets[col].$tag.remove();
|
||||
delete self.facets[col];
|
||||
self.loadData();
|
||||
|
@ -374,5 +394,49 @@ var H5PDataView = (function ($) {
|
|||
}).appendTo(self.$container);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add toggle for others' H5P content.
|
||||
* @param {boolean} [checked=false] Initial check setting.
|
||||
*/
|
||||
H5PDataView.prototype.addOthersContentToggler = function (checked) {
|
||||
var self = this;
|
||||
|
||||
checked = (typeof checked === 'undefined') ? false : checked;
|
||||
|
||||
// Checkbox
|
||||
this.$othersContentToggler = $('<input/>', {
|
||||
type: 'checkbox',
|
||||
'class': 'h5p-others-contents-toggler',
|
||||
'id': 'h5p-others-contents-toggler',
|
||||
'checked': checked,
|
||||
'click': function () {
|
||||
if ( this.checked ) {
|
||||
// Add filter on current user
|
||||
self.filterByFacet( self.columnIdAuthor, H5PIntegration.user.id, H5PIntegration.user.name );
|
||||
}
|
||||
else {
|
||||
// Remove facet indicator and reload full data view
|
||||
if ( self.facets.hasOwnProperty( self.columnIdAuthor ) && self.facets[self.columnIdAuthor].$tag ) {
|
||||
self.facets[self.columnIdAuthor].$tag.remove();
|
||||
}
|
||||
delete self.facets[self.columnIdAuthor];
|
||||
self.loadData();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Label
|
||||
var $label = $('<label>', {
|
||||
'class': 'h5p-others-contents-toggler-label',
|
||||
'text': this.l10n.showOwnContentOnly,
|
||||
'for': 'h5p-others-contents-toggler'
|
||||
}).prepend(this.$othersContentToggler);
|
||||
|
||||
$('<div>', {
|
||||
'class': 'h5p-others-contents-toggler-wrapper'
|
||||
}).append($label)
|
||||
.appendTo(this.$container);
|
||||
};
|
||||
|
||||
return H5PDataView;
|
||||
})(H5P.jQuery);
|
||||
|
|
|
@ -10,7 +10,7 @@ var H5P = window.H5P = window.H5P || {};
|
|||
* @param {boolean} [extras.bubbles]
|
||||
* @param {boolean} [extras.external]
|
||||
*/
|
||||
H5P.Event = function(type, data, extras) {
|
||||
H5P.Event = function (type, data, extras) {
|
||||
this.type = type;
|
||||
this.data = data;
|
||||
var bubbles = false;
|
||||
|
@ -34,7 +34,7 @@ H5P.Event = function(type, data, extras) {
|
|||
/**
|
||||
* Prevent this event from bubbling up to parent
|
||||
*/
|
||||
this.preventBubbling = function() {
|
||||
this.preventBubbling = function () {
|
||||
bubbles = false;
|
||||
};
|
||||
|
||||
|
@ -44,7 +44,7 @@ H5P.Event = function(type, data, extras) {
|
|||
* @returns {boolean}
|
||||
* true if bubbling false otherwise
|
||||
*/
|
||||
this.getBubbles = function() {
|
||||
this.getBubbles = function () {
|
||||
return bubbles;
|
||||
};
|
||||
|
||||
|
@ -54,7 +54,7 @@ H5P.Event = function(type, data, extras) {
|
|||
* @returns {boolean}
|
||||
* true if external and not already scheduled, otherwise false
|
||||
*/
|
||||
this.scheduleForExternal = function() {
|
||||
this.scheduleForExternal = function () {
|
||||
if (external && !scheduledForExternal) {
|
||||
scheduledForExternal = true;
|
||||
return true;
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,5 @@
|
|||
var H5PLibraryDetails= H5PLibraryDetails || {};
|
||||
/* global H5PAdminIntegration H5PUtils */
|
||||
var H5PLibraryDetails = H5PLibraryDetails || {};
|
||||
|
||||
(function ($) {
|
||||
|
||||
|
@ -68,7 +69,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
|
|||
*/
|
||||
H5PLibraryDetails.createContentTable = function () {
|
||||
// Remove it if it exists:
|
||||
if(H5PLibraryDetails.$contentTable) {
|
||||
if (H5PLibraryDetails.$contentTable) {
|
||||
H5PLibraryDetails.$contentTable.remove();
|
||||
}
|
||||
|
||||
|
@ -77,10 +78,10 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
|
|||
var i = (H5PLibraryDetails.currentPage*H5PLibraryDetails.PAGER_SIZE);
|
||||
var lastIndex = (i+H5PLibraryDetails.PAGER_SIZE);
|
||||
|
||||
if(lastIndex > H5PLibraryDetails.currentContent.length) {
|
||||
if (lastIndex > H5PLibraryDetails.currentContent.length) {
|
||||
lastIndex = H5PLibraryDetails.currentContent.length;
|
||||
}
|
||||
for(; i<lastIndex; i++) {
|
||||
for (; i<lastIndex; i++) {
|
||||
var content = H5PLibraryDetails.currentContent[i];
|
||||
H5PLibraryDetails.$contentTable.append(H5PUtils.createTableRow(['<a href="' + content.url + '">' + content.title + '</a>']));
|
||||
}
|
||||
|
@ -97,7 +98,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
|
|||
H5PLibraryDetails.$next = $('<button type="button" class="next h5p-admin">></button>');
|
||||
|
||||
H5PLibraryDetails.$previous.on('click', function () {
|
||||
if(H5PLibraryDetails.$previous.hasClass('disabled')) {
|
||||
if (H5PLibraryDetails.$previous.hasClass('disabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -107,7 +108,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
|
|||
});
|
||||
|
||||
H5PLibraryDetails.$next.on('click', function () {
|
||||
if(H5PLibraryDetails.$next.hasClass('disabled')) {
|
||||
if (H5PLibraryDetails.$next.hasClass('disabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -127,7 +128,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
|
|||
H5PLibraryDetails.$pagerInfo.hide();
|
||||
|
||||
// User has updated the pageNumber
|
||||
var pageNumerUpdated = function() {
|
||||
var pageNumerUpdated = function () {
|
||||
var newPageNum = $gotoInput.val()-1;
|
||||
var intRegex = /^\d+$/;
|
||||
|
||||
|
@ -135,7 +136,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
|
|||
H5PLibraryDetails.$pagerInfo.css({display: 'inline-block'});
|
||||
|
||||
// Check if input value is valid, and that it has actually changed
|
||||
if(!(intRegex.test(newPageNum) && newPageNum >= 0 && newPageNum < H5PLibraryDetails.getNumPages() && newPageNum != H5PLibraryDetails.currentPage)) {
|
||||
if (!(intRegex.test(newPageNum) && newPageNum >= 0 && newPageNum < H5PLibraryDetails.getNumPages() && newPageNum != H5PLibraryDetails.currentPage)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -185,7 +186,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
|
|||
H5PLibraryDetails.updatePager = function () {
|
||||
H5PLibraryDetails.$pagerInfo.css({display: 'inline-block'});
|
||||
|
||||
if(H5PLibraryDetails.getNumPages() > 0) {
|
||||
if (H5PLibraryDetails.getNumPages() > 0) {
|
||||
var message = H5PUtils.translateReplace(H5PLibraryDetails.library.translations.pageXOfY, {
|
||||
'$x': (H5PLibraryDetails.currentPage+1),
|
||||
'$y': H5PLibraryDetails.getNumPages()
|
||||
|
@ -211,7 +212,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
|
|||
var searchString = $('.h5p-content-search > input').val();
|
||||
|
||||
// If search string same as previous, just do nothing
|
||||
if(H5PLibraryDetails.currentFilter === searchString) {
|
||||
if (H5PLibraryDetails.currentFilter === searchString) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -219,7 +220,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
|
|||
// If empty search, use the complete list
|
||||
H5PLibraryDetails.currentContent = H5PLibraryDetails.library.content;
|
||||
}
|
||||
else if(H5PLibraryDetails.filterCache[searchString]) {
|
||||
else if (H5PLibraryDetails.filterCache[searchString]) {
|
||||
// If search is cached, no need to filter
|
||||
H5PLibraryDetails.currentContent = H5PLibraryDetails.filterCache[searchString];
|
||||
}
|
||||
|
@ -227,10 +228,10 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
|
|||
var listToFilter = H5PLibraryDetails.library.content;
|
||||
|
||||
// Check if we can filter the already filtered results (for performance)
|
||||
if(searchString.length > 1 && H5PLibraryDetails.currentFilter === searchString.substr(0, H5PLibraryDetails.currentFilter.length)) {
|
||||
if (searchString.length > 1 && H5PLibraryDetails.currentFilter === searchString.substr(0, H5PLibraryDetails.currentFilter.length)) {
|
||||
listToFilter = H5PLibraryDetails.currentContent;
|
||||
}
|
||||
H5PLibraryDetails.currentContent = $.grep(listToFilter, function(content) {
|
||||
H5PLibraryDetails.currentContent = $.grep(listToFilter, function (content) {
|
||||
return content.title && content.title.match(new RegExp(searchString, 'i'));
|
||||
});
|
||||
}
|
||||
|
@ -256,7 +257,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
|
|||
$('input', H5PLibraryDetails.$search).on('change keypress paste input', function () {
|
||||
// Here we start the filtering
|
||||
// We wait at least 500 ms after last input to perform search
|
||||
if(inputTimer) {
|
||||
if (inputTimer) {
|
||||
clearTimeout(inputTimer);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*jshint multistr: true */
|
||||
/* global H5PAdminIntegration H5PUtils */
|
||||
var H5PLibraryList = H5PLibraryList || {};
|
||||
|
||||
(function ($) {
|
||||
|
@ -25,7 +25,7 @@ var H5PLibraryList = H5PLibraryList || {};
|
|||
*/
|
||||
H5PLibraryList.createLibraryList = function (libraries) {
|
||||
var t = H5PAdminIntegration.l10n;
|
||||
if(libraries.listData === undefined || libraries.listData.length === 0) {
|
||||
if (libraries.listData === undefined || libraries.listData.length === 0) {
|
||||
return $('<div>' + t.NA + '</div>');
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,12 @@
|
|||
// Make iframe responsive
|
||||
iframe.style.width = '100%';
|
||||
|
||||
// Bugfix for Chrome: Force update of iframe width. If this is not done the
|
||||
// document size may not be updated before the content resizes.
|
||||
iframe.getBoundingClientRect();
|
||||
|
||||
// Tell iframe that it needs to resize when our window resizes
|
||||
var resize = function (event) {
|
||||
var resize = function () {
|
||||
if (iframe.contentWindow) {
|
||||
// Limit resize calls to avoid flickering
|
||||
respond('resize');
|
||||
|
@ -64,7 +68,7 @@
|
|||
* @param {Object} data Payload
|
||||
* @param {Function} respond Send a response to the iframe
|
||||
*/
|
||||
actionHandlers.resize = function (iframe, data, respond) {
|
||||
actionHandlers.resize = function (iframe, data) {
|
||||
// Resize iframe so all content is visible. Use scrollHeight to make sure we get everything
|
||||
iframe.style.height = data.scrollHeight + 'px';
|
||||
};
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* global H5PAdminIntegration*/
|
||||
var H5PUtils = H5PUtils || {};
|
||||
|
||||
(function ($) {
|
||||
|
@ -9,7 +10,7 @@ var H5PUtils = H5PUtils || {};
|
|||
H5PUtils.createTable = function (headers) {
|
||||
var $table = $('<table class="h5p-admin-table' + (H5PAdminIntegration.extraTableClasses !== undefined ? ' ' + H5PAdminIntegration.extraTableClasses : '') + '"></table>');
|
||||
|
||||
if(headers) {
|
||||
if (headers) {
|
||||
var $thead = $('<thead></thead>');
|
||||
var $tr = $('<tr></tr>');
|
||||
|
||||
|
@ -44,7 +45,7 @@ var H5PUtils = H5PUtils || {};
|
|||
};
|
||||
}
|
||||
|
||||
$('<td/>', value).appendTo($tr);
|
||||
$('<td/>', value).appendTo($tr);
|
||||
});
|
||||
|
||||
return $tr;
|
||||
|
|
|
@ -7,11 +7,24 @@ H5P.Version = (function () {
|
|||
* @param {String} version
|
||||
*/
|
||||
function Version(version) {
|
||||
var versionSplit = version.split('.', 3);
|
||||
|
||||
// Public
|
||||
this.major =+ versionSplit[0];
|
||||
this.minor =+ versionSplit[1];
|
||||
if (typeof version === 'string') {
|
||||
// Name version string (used by content upgrade)
|
||||
var versionSplit = version.split('.', 3);
|
||||
this.major =+ versionSplit[0];
|
||||
this.minor =+ versionSplit[1];
|
||||
}
|
||||
else {
|
||||
// Library objects (used by editor)
|
||||
if (version.localMajorVersion !== undefined) {
|
||||
this.major =+ version.localMajorVersion;
|
||||
this.minor =+ version.localMinorVersion;
|
||||
}
|
||||
else {
|
||||
this.major =+ version.majorVersion;
|
||||
this.minor =+ version.minorVersion;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Public. Custom string for this object.
|
||||
|
|
|
@ -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: {}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -217,7 +229,7 @@ H5P.XAPIEvent.prototype.setActor = function () {
|
|||
* @returns {number}
|
||||
* The max score, or null if not defined
|
||||
*/
|
||||
H5P.XAPIEvent.prototype.getMaxScore = function() {
|
||||
H5P.XAPIEvent.prototype.getMaxScore = function () {
|
||||
return this.getVerifiedStatementValue(['result', 'score', 'max']);
|
||||
};
|
||||
|
||||
|
@ -227,7 +239,7 @@ H5P.XAPIEvent.prototype.getMaxScore = function() {
|
|||
* @returns {number}
|
||||
* The score, or null if not defined
|
||||
*/
|
||||
H5P.XAPIEvent.prototype.getScore = function() {
|
||||
H5P.XAPIEvent.prototype.getScore = function () {
|
||||
return this.getVerifiedStatementValue(['result', 'score', 'raw']);
|
||||
};
|
||||
|
||||
|
@ -239,7 +251,7 @@ H5P.XAPIEvent.prototype.getScore = function() {
|
|||
*/
|
||||
H5P.XAPIEvent.prototype.getContentXAPIId = function (instance) {
|
||||
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;
|
||||
if (instance.subContentId) {
|
||||
xAPIId += '?subContentId=' + instance.subContentId;
|
||||
|
@ -256,7 +268,7 @@ H5P.XAPIEvent.prototype.getContentXAPIId = function (instance) {
|
|||
H5P.XAPIEvent.prototype.isFromChild = function () {
|
||||
var parentId = this.getVerifiedStatementValue(['context', 'contextActivities', 'parent', 0, 'id']);
|
||||
return !parentId || parentId.indexOf('subContentId') === -1;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Figure out if a property exists in the statement and return it
|
||||
|
@ -267,7 +279,7 @@ H5P.XAPIEvent.prototype.isFromChild = function () {
|
|||
* @returns {*}
|
||||
* The value of the property if it is set, null otherwise.
|
||||
*/
|
||||
H5P.XAPIEvent.prototype.getVerifiedStatementValue = function(keys) {
|
||||
H5P.XAPIEvent.prototype.getVerifiedStatementValue = function (keys) {
|
||||
var val = this.data.statement;
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
if (val[keys[i]] === undefined) {
|
||||
|
@ -312,6 +324,8 @@ H5P.XAPIEvent.allowedXAPIVerbs = [
|
|||
|
||||
// Custom verbs used for action toolbar below content
|
||||
'downloaded',
|
||||
'copied',
|
||||
'accessed-reuse',
|
||||
'accessed-embed',
|
||||
'accessed-copyright'
|
||||
];
|
||||
|
|
|
@ -92,7 +92,7 @@ H5P.EventDispatcher.prototype.triggerXAPIScored = function (score, maxScore, ver
|
|||
this.trigger(event);
|
||||
};
|
||||
|
||||
H5P.EventDispatcher.prototype.setActivityStarted = function() {
|
||||
H5P.EventDispatcher.prototype.setActivityStarted = function () {
|
||||
if (this.activityStartTime === undefined) {
|
||||
// Don't trigger xAPI events in the editor
|
||||
if (this.contentId !== undefined &&
|
||||
|
|
650
js/h5p.js
650
js/h5p.js
|
@ -23,7 +23,7 @@ H5P.$window = H5P.jQuery(window);
|
|||
H5P.instances = [];
|
||||
|
||||
// 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.
|
||||
* undefined means no fullscreen support.
|
||||
|
@ -74,9 +74,10 @@ H5P.init = function (target) {
|
|||
* fullscreen, and the semi-fullscreen solution doesn't work when embedded.
|
||||
* @type {boolean}
|
||||
*/
|
||||
H5P.fullscreenSupported = !(H5P.isFramed && H5P.externalEmbed !== false) || !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled);
|
||||
// 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
|
||||
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
|
||||
// -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
|
||||
|
@ -89,7 +90,7 @@ H5P.init = function (target) {
|
|||
}
|
||||
|
||||
// H5Ps added in normal DIV.
|
||||
var $containers = H5P.jQuery('.h5p-content:not(.h5p-initialized)', target).each(function () {
|
||||
H5P.jQuery('.h5p-content:not(.h5p-initialized)', target).each(function () {
|
||||
var $element = H5P.jQuery(this).addClass('h5p-initialized');
|
||||
var $container = H5P.jQuery('<div class="h5p-container"></div>').appendTo($element);
|
||||
var contentId = $element.data('content-id');
|
||||
|
@ -123,6 +124,9 @@ H5P.init = function (target) {
|
|||
};
|
||||
|
||||
$dialog.find('.h5p-dialog-ok-button').click(closeDialog).keypress(closeDialog);
|
||||
H5P.trigger(instance, 'resize');
|
||||
}).on('dialog-closed', function () {
|
||||
H5P.trigger(instance, 'resize');
|
||||
});
|
||||
dialog.open();
|
||||
}
|
||||
|
@ -132,6 +136,8 @@ H5P.init = function (target) {
|
|||
// Create new instance.
|
||||
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.
|
||||
if (contentData.fullScreen == 1 && H5P.fullscreenSupported) {
|
||||
H5P.jQuery(
|
||||
|
@ -139,6 +145,7 @@ H5P.init = function (target) {
|
|||
'<div role="button" ' +
|
||||
'tabindex="0" ' +
|
||||
'class="h5p-enable-fullscreen" ' +
|
||||
'aria-label="' + H5P.t('fullscreen') + '" ' +
|
||||
'title="' + H5P.t('fullscreen') + '">' +
|
||||
'</div>' +
|
||||
'</div>')
|
||||
|
@ -174,20 +181,20 @@ H5P.init = function (target) {
|
|||
var actionBar = new H5P.ActionBar(displayOptions);
|
||||
var $actions = actionBar.getDOMElement();
|
||||
|
||||
actionBar.on('download', function () {
|
||||
window.location.href = contentData.exportUrl;
|
||||
instance.triggerXAPI('downloaded');
|
||||
actionBar.on('reuse', function () {
|
||||
H5P.openReuseDialog($actions, contentData, library, instance, contentId);
|
||||
instance.triggerXAPI('accessed-reuse');
|
||||
});
|
||||
actionBar.on('copyrights', function () {
|
||||
var dialog = new H5P.Dialog('copyrights', H5P.t('copyrightInformation'), copyrights, $container);
|
||||
dialog.open();
|
||||
dialog.open(true);
|
||||
instance.triggerXAPI('accessed-copyright');
|
||||
});
|
||||
actionBar.on('embed', function () {
|
||||
H5P.openEmbedDialog($actions, contentData.embedCode, contentData.resizeCode, {
|
||||
width: $element.width(),
|
||||
height: $element.height()
|
||||
});
|
||||
}, instance);
|
||||
instance.triggerXAPI('accessed-embed');
|
||||
});
|
||||
|
||||
|
@ -258,6 +265,11 @@ H5P.init = function (target) {
|
|||
var parentHeight = iframe.parentElement.style.height;
|
||||
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.
|
||||
iframe.style.height = '1px';
|
||||
|
||||
|
@ -301,7 +313,7 @@ H5P.init = function (target) {
|
|||
});
|
||||
|
||||
// When resize has been prepared tell parent window to resize
|
||||
H5P.communicator.on('resizePrepared', function (data) {
|
||||
H5P.communicator.on('resizePrepared', function () {
|
||||
H5P.communicator.send('resize', {
|
||||
scrollHeight: document.body.scrollHeight
|
||||
});
|
||||
|
@ -351,14 +363,43 @@ H5P.init = function (target) {
|
|||
|
||||
// Resize content.
|
||||
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.
|
||||
H5P.jQuery('iframe.h5p-iframe:not(.h5p-initialized)', target).each(function () {
|
||||
var contentId = H5P.jQuery(this).addClass('h5p-initialized').data('content-id');
|
||||
this.contentDocument.open();
|
||||
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 iframe = this;
|
||||
const $iframe = H5P.jQuery(iframe);
|
||||
|
||||
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();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -494,7 +535,7 @@ H5P.fullScreen = function ($element, instance, exitCallback, body, forceSemiFull
|
|||
}
|
||||
|
||||
var $container = $element;
|
||||
var $classes, $iframe;
|
||||
var $classes, $iframe, $body;
|
||||
if (body === undefined) {
|
||||
$body = H5P.$body;
|
||||
}
|
||||
|
@ -569,7 +610,7 @@ H5P.fullScreen = function ($element, instance, exitCallback, body, forceSemiFull
|
|||
}
|
||||
|
||||
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 () {
|
||||
if (prevViewportContent) {
|
||||
// Use content from the previous viewport tag
|
||||
|
@ -635,7 +676,7 @@ H5P.fullScreen = function ($element, instance, exitCallback, body, forceSemiFull
|
|||
});
|
||||
|
||||
if (H5P.fullScreenBrowserPrefix === '') {
|
||||
$element[0].requestFullScreen();
|
||||
$element[0].requestFullscreen();
|
||||
}
|
||||
else {
|
||||
var method = (H5P.fullScreenBrowserPrefix === 'ms' ? 'msRequestFullscreen' : H5P.fullScreenBrowserPrefix + 'RequestFullScreen');
|
||||
|
@ -658,52 +699,140 @@ H5P.fullScreen = function ($element, instance, exitCallback, body, forceSemiFull
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Find the path to the content files based on the id of the content.
|
||||
* Also identifies and returns absolute paths.
|
||||
*
|
||||
* @param {string} path
|
||||
* Relative to content folder or absolute.
|
||||
* @param {number} contentId
|
||||
* ID of the content requesting the path.
|
||||
* @returns {string}
|
||||
* Complete URL to path.
|
||||
*/
|
||||
H5P.getPath = function (path, contentId) {
|
||||
(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);
|
||||
};
|
||||
|
||||
if (hasProtocol(path)) {
|
||||
return path;
|
||||
}
|
||||
|
||||
var prefix;
|
||||
var isTmpFile = (path.substr(-4,4) === '#tmp');
|
||||
if (contentId !== undefined && !isTmpFile) {
|
||||
// Check for custom override URL
|
||||
if (H5PIntegration.contents !== undefined &&
|
||||
H5PIntegration.contents['cid-' + contentId]) {
|
||||
prefix = H5PIntegration.contents['cid-' + contentId].contentUrl;
|
||||
/**
|
||||
* 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 (!prefix) {
|
||||
prefix = H5PIntegration.url + '/content/' + contentId;
|
||||
|
||||
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.
|
||||
}
|
||||
}
|
||||
else if (window.H5PEditor !== undefined) {
|
||||
prefix = H5PEditor.filesPath;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if (!hasProtocol(prefix)) {
|
||||
// Use absolute urls
|
||||
prefix = window.location.protocol + "//" + window.location.host + prefix;
|
||||
}
|
||||
/**
|
||||
* Find the path to the content files based on the id of the content.
|
||||
* Also identifies and returns absolute paths.
|
||||
*
|
||||
* @param {string} path
|
||||
* Relative to content folder or absolute.
|
||||
* @param {number} contentId
|
||||
* ID of the content requesting the path.
|
||||
* @returns {string}
|
||||
* Complete URL to path.
|
||||
*/
|
||||
H5P.getPath = function (path, contentId) {
|
||||
if (hasProtocol(path)) {
|
||||
return path;
|
||||
}
|
||||
|
||||
return prefix + '/' + path;
|
||||
};
|
||||
var prefix;
|
||||
var isTmpFile = (path.substr(-4,4) === '#tmp');
|
||||
if (contentId !== undefined && !isTmpFile) {
|
||||
// Check for custom override URL
|
||||
if (H5PIntegration.contents !== undefined &&
|
||||
H5PIntegration.contents['cid-' + contentId]) {
|
||||
prefix = H5PIntegration.contents['cid-' + contentId].contentUrl;
|
||||
}
|
||||
if (!prefix) {
|
||||
prefix = H5PIntegration.url + '/content/' + contentId;
|
||||
}
|
||||
}
|
||||
else if (window.H5PEditor !== undefined) {
|
||||
prefix = H5PEditor.filesPath;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasProtocol(prefix)) {
|
||||
// Use absolute urls
|
||||
prefix = window.location.protocol + "//" + window.location.host + prefix;
|
||||
}
|
||||
|
||||
return prefix + '/' + path;
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* THIS FUNCTION IS DEPRECATED, USE getPath INSTEAD
|
||||
|
@ -920,25 +1049,35 @@ H5P.t = function (key, vars, ns) {
|
|||
H5P.Dialog = function (name, title, content, $element) {
|
||||
/** @alias H5P.Dialog# */
|
||||
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">\
|
||||
<h2>' + title + '</h2>\
|
||||
<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>')
|
||||
.insertAfter($element)
|
||||
.click(function () {
|
||||
.click(function (e) {
|
||||
if (e && e.originalEvent && e.originalEvent.preventClosing) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.close();
|
||||
})
|
||||
.children('.h5p-inner')
|
||||
.click(function () {
|
||||
return false;
|
||||
.click(function (e) {
|
||||
e.originalEvent.preventClosing = true;
|
||||
})
|
||||
.find('.h5p-close')
|
||||
.click(function () {
|
||||
self.close();
|
||||
})
|
||||
.keypress(function (e) {
|
||||
if (e.which === 13 || e.which === 32) {
|
||||
self.close();
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.end()
|
||||
.find('a')
|
||||
.click(function (e) {
|
||||
|
@ -950,11 +1089,15 @@ H5P.Dialog = function (name, title, content, $element) {
|
|||
/**
|
||||
* Opens the dialog.
|
||||
*/
|
||||
self.open = function () {
|
||||
self.open = function (scrollbar) {
|
||||
if (scrollbar) {
|
||||
$dialog.css('height', '100%');
|
||||
}
|
||||
setTimeout(function () {
|
||||
$dialog.addClass('h5p-open'); // Fade in
|
||||
// Triggering an event, in case something has to be done after dialog has been opened.
|
||||
H5P.jQuery(self).trigger('dialog-opened', [$dialog]);
|
||||
$dialog.focus();
|
||||
}, 1);
|
||||
};
|
||||
|
||||
|
@ -965,6 +1108,9 @@ H5P.Dialog = function (name, title, content, $element) {
|
|||
$dialog.removeClass('h5p-open'); // Fade out
|
||||
setTimeout(function () {
|
||||
$dialog.remove();
|
||||
H5P.jQuery(self).trigger('dialog-closed', [$dialog]);
|
||||
$element.attr('tabindex', '-1');
|
||||
$element.focus();
|
||||
}, 200);
|
||||
};
|
||||
};
|
||||
|
@ -1089,7 +1235,7 @@ H5P.findCopyrights = function (info, parameters, contentId, extras) {
|
|||
}
|
||||
}
|
||||
|
||||
function buildFromMetadata (data, name, contentId) {
|
||||
function buildFromMetadata(data, name, contentId) {
|
||||
if (data.metadata) {
|
||||
const metadataCopyrights = H5P.buildMetadataCopyrights(data.metadata, name);
|
||||
if (metadataCopyrights !== undefined) {
|
||||
|
@ -1105,12 +1251,12 @@ H5P.findCopyrights = function (info, parameters, contentId, extras) {
|
|||
}
|
||||
};
|
||||
|
||||
H5P.buildMetadataCopyrights = function (metadata, contentTypeName) {
|
||||
H5P.buildMetadataCopyrights = function (metadata) {
|
||||
if (metadata && metadata.license !== undefined && metadata.license !== 'U') {
|
||||
var dataset = {
|
||||
contentType: metadata.contentType,
|
||||
title: metadata.title,
|
||||
author: (metadata.authors && metadata.authors.length > 0) ? metadata.authors.map(function(author) {
|
||||
author: (metadata.authors && metadata.authors.length > 0) ? metadata.authors.map(function (author) {
|
||||
return (author.role) ? author.name + ' (' + author.role + ')' : author.name;
|
||||
}).join(', ') : undefined,
|
||||
source: metadata.source,
|
||||
|
@ -1118,7 +1264,7 @@ H5P.buildMetadataCopyrights = function (metadata, contentTypeName) {
|
|||
license: metadata.license,
|
||||
version: metadata.licenseVersion,
|
||||
licenseExtras: metadata.licenseExtras,
|
||||
changes: (metadata.changes && metadata.changes.length > 0) ? metadata.changes.map(function(change) {
|
||||
changes: (metadata.changes && metadata.changes.length > 0) ? metadata.changes.map(function (change) {
|
||||
return change.log + (change.author ? ', ' + change.author : '') + (change.date ? ', ' + change.date : '');
|
||||
}).join(' / ') : undefined
|
||||
};
|
||||
|
@ -1127,6 +1273,65 @@ H5P.buildMetadataCopyrights = function (metadata, contentTypeName) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
|
@ -1141,9 +1346,9 @@ H5P.buildMetadataCopyrights = function (metadata, contentTypeName) {
|
|||
* @param {number} size.width
|
||||
* @param {number} size.height
|
||||
*/
|
||||
H5P.openEmbedDialog = function ($element, embedCode, resizeCode, size) {
|
||||
H5P.openEmbedDialog = function ($element, embedCode, resizeCode, size, instance) {
|
||||
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
|
||||
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 diff = $scroll.outerHeight() - $scroll.innerHeight();
|
||||
var positionInner = function () {
|
||||
var height = $inner.height();
|
||||
if ($scroll[0].scrollHeight + diff > height) {
|
||||
$inner.css('height', ''); // 100%
|
||||
}
|
||||
else {
|
||||
$inner.css('height', 'auto');
|
||||
height = $inner.height();
|
||||
}
|
||||
$inner.css('marginTop', '-' + (height / 2) + 'px');
|
||||
H5P.trigger(instance, 'resize');
|
||||
};
|
||||
|
||||
// Handle changing of width/height
|
||||
|
@ -1181,10 +1378,10 @@ H5P.openEmbedDialog = function ($element, embedCode, resizeCode, size) {
|
|||
updateEmbed();
|
||||
|
||||
// Select text and expand textareas
|
||||
$dialog.find('.h5p-embed-code-container').each(function(index, value) {
|
||||
H5P.jQuery(this).css('height', this.scrollHeight + 'px').focus(function() {
|
||||
H5P.jQuery(this).select();
|
||||
});
|
||||
$dialog.find('.h5p-embed-code-container').each(function () {
|
||||
H5P.jQuery(this).css('height', this.scrollHeight + 'px').focus(function () {
|
||||
H5P.jQuery(this).select();
|
||||
});
|
||||
});
|
||||
$dialog.find('.h5p-embed-code-container').eq(0).select();
|
||||
positionInner();
|
||||
|
@ -1194,14 +1391,14 @@ H5P.openEmbedDialog = function ($element, embedCode, resizeCode, size) {
|
|||
var $expander = H5P.jQuery(this);
|
||||
var $content = $expander.next();
|
||||
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();
|
||||
}
|
||||
else {
|
||||
$expander.addClass('h5p-open').text(H5P.t('hideAdvanced'));
|
||||
$expander.addClass('h5p-open').text(H5P.t('hideAdvanced')).attr('aria-expanded', 'false');
|
||||
$content.show();
|
||||
}
|
||||
$dialog.find('.h5p-embed-code-container').each(function(index, value) {
|
||||
$dialog.find('.h5p-embed-code-container').each(function () {
|
||||
H5P.jQuery(this).css('height', this.scrollHeight + 'px');
|
||||
});
|
||||
positionInner();
|
||||
|
@ -1209,13 +1406,221 @@ H5P.openEmbedDialog = function ($element, embedCode, resizeCode, size) {
|
|||
$dialog.find('.h5p-expander').click(expand).keypress(function (event) {
|
||||
if (event.keyCode === 32) {
|
||||
expand.apply(this);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}).on('dialog-closed', function () {
|
||||
H5P.trigger(instance, 'resize');
|
||||
});
|
||||
|
||||
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.
|
||||
*
|
||||
|
@ -1418,7 +1823,7 @@ H5P.MediaCopyright = function (copyright, labels, order, extraFields) {
|
|||
|
||||
for (var i = 0; i < order.length; i++) {
|
||||
var fieldName = order[i];
|
||||
if (copyright[fieldName] !== undefined) {
|
||||
if (copyright[fieldName] !== undefined && copyright[fieldName] !== '') {
|
||||
var humanValue = copyright[fieldName];
|
||||
if (fieldName === 'license') {
|
||||
humanValue = humanizeLicense(copyright.license, copyright.version);
|
||||
|
@ -1614,7 +2019,8 @@ H5P.Coords = function (x, y, w, h) {
|
|||
this.y = x.y;
|
||||
this.w = x.w;
|
||||
this.h = x.h;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (x !== undefined) {
|
||||
this.x = x;
|
||||
}
|
||||
|
@ -1664,7 +2070,13 @@ H5P.libraryFromString = function (library) {
|
|||
* The full path to the 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;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1786,14 +2198,18 @@ H5P.setFinished = function (contentId, score, maxScore, time) {
|
|||
};
|
||||
|
||||
// Post the results
|
||||
H5P.jQuery.post(H5PIntegration.ajax.setFinished, {
|
||||
const data = {
|
||||
contentId: contentId,
|
||||
score: score,
|
||||
maxScore: maxScore,
|
||||
opened: toUnix(H5P.opened[contentId]),
|
||||
finished: toUnix(new Date()),
|
||||
time: time
|
||||
});
|
||||
};
|
||||
H5P.jQuery.post(H5PIntegration.ajax.setFinished, data)
|
||||
.fail(function () {
|
||||
H5P.offlineRequestQueue.add(H5PIntegration.ajax.setFinished, data);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1870,7 +2286,7 @@ H5P.on = function (instance, eventType, handler) {
|
|||
* @returns {string} UUID
|
||||
*/
|
||||
H5P.createUUID = function () {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(char) {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (char) {
|
||||
var random = Math.random()*16|0, newChar = char === 'x' ? random : (random&0x3|0x8);
|
||||
return newChar.toString(16);
|
||||
});
|
||||
|
@ -2023,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.
|
||||
*
|
||||
|
@ -2098,7 +2501,7 @@ H5P.createTitle = function (rawTitle, maxLength) {
|
|||
}
|
||||
|
||||
preloadedData[options.subContentId][dataId] = data;
|
||||
contentUserDataAjax(contentId, dataId, options.subContentId, function (error, data) {
|
||||
contentUserDataAjax(contentId, dataId, options.subContentId, function (error) {
|
||||
if (options.errorCallback && error) {
|
||||
options.errorCallback(error);
|
||||
}
|
||||
|
@ -2211,23 +2614,13 @@ H5P.createTitle = function (rawTitle, maxLength) {
|
|||
H5P.setClipboard(clipboardItem);
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a cache for pasted data to prevent parsing multiple times.
|
||||
* @type {Object}
|
||||
*/
|
||||
var parsedClipboard = null;
|
||||
|
||||
/**
|
||||
* Retrieve parsed clipboard data.
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
H5P.getClipboard = function () {
|
||||
if (!parsedClipboard) {
|
||||
parsedClipboard = parseClipboard();
|
||||
}
|
||||
|
||||
return parsedClipboard;
|
||||
return parseClipboard();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2238,9 +2631,6 @@ H5P.createTitle = function (rawTitle, maxLength) {
|
|||
H5P.setClipboard = function (clipboardItem) {
|
||||
localStorage.setItem('h5pClipboard', JSON.stringify(clipboardItem));
|
||||
|
||||
// Clear cache
|
||||
parsedClipboard = null;
|
||||
|
||||
// Trigger an event so all 'Paste' buttons may be enabled.
|
||||
H5P.externalDispatcher.trigger('datainclipboard', {reset: false});
|
||||
};
|
||||
|
@ -2260,7 +2650,6 @@ H5P.createTitle = function (rawTitle, maxLength) {
|
|||
* Get item from the H5P Clipboard.
|
||||
*
|
||||
* @private
|
||||
* @param {boolean} [skipUpdateFileUrls]
|
||||
* @return {Object}
|
||||
*/
|
||||
var parseClipboard = function () {
|
||||
|
@ -2278,10 +2667,10 @@ H5P.createTitle = function (rawTitle, maxLength) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Update file URLs
|
||||
updateFileUrls(clipboardData.specific, function (path) {
|
||||
// Update file URLs and reset content Ids
|
||||
recursiveUpdate(clipboardData.specific, function (path) {
|
||||
var isTmpFile = (path.substr(-4, 4) === '#tmp');
|
||||
if (!isTmpFile && clipboardData.contentId) {
|
||||
if (!isTmpFile && clipboardData.contentId && !path.match(/^https?:\/\//i)) {
|
||||
// Comes from existing content
|
||||
|
||||
if (H5PEditor.contentId) {
|
||||
|
@ -2300,22 +2689,20 @@ H5P.createTitle = function (rawTitle, maxLength) {
|
|||
if (clipboardData.generic) {
|
||||
// Use reference instead of key
|
||||
clipboardData.generic = clipboardData.specific[clipboardData.generic];
|
||||
|
||||
// Avoid multiple content with same ID
|
||||
delete clipboardData.generic.subContentId;
|
||||
}
|
||||
|
||||
return clipboardData;
|
||||
};
|
||||
|
||||
/**
|
||||
* Update file URLs. Useful when copying content.
|
||||
* Update file URLs and reset content IDs.
|
||||
* Useful when copying content.
|
||||
*
|
||||
* @private
|
||||
* @param {object} params Reference
|
||||
* @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) {
|
||||
if (params.hasOwnProperty(prop) && params[prop] instanceof Object) {
|
||||
var obj = params[prop];
|
||||
|
@ -2323,7 +2710,11 @@ H5P.createTitle = function (rawTitle, maxLength) {
|
|||
obj.path = handler(obj.path);
|
||||
}
|
||||
else {
|
||||
updateFileUrls(obj, handler);
|
||||
if (obj.library !== undefined && obj.subContentId !== undefined) {
|
||||
// Avoid multiple content with same ID
|
||||
delete obj.subContentId;
|
||||
}
|
||||
recursiveUpdate(obj, handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2335,9 +2726,6 @@ H5P.createTitle = function (rawTitle, maxLength) {
|
|||
window.addEventListener('storage', function (event) {
|
||||
// Pick up clipboard changes from other tabs
|
||||
if (event.key === 'h5pClipboard') {
|
||||
// Clear cache
|
||||
parsedClipboard = null;
|
||||
|
||||
// Trigger an event so all 'Paste' buttons may be enabled.
|
||||
H5P.externalDispatcher.trigger('datainclipboard', {reset: event.newValue === null});
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -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);
|
|
@ -266,6 +266,20 @@ button.h5p-admin.disabled:hover {
|
|||
display: none;
|
||||
}
|
||||
|
||||
.h5p-data-view .h5p-others-contents-toggler-wrapper {
|
||||
float: right;
|
||||
line-height: 2;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.h5p-data-view .h5p-others-contents-toggler-label {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.h5p-data-view .h5p-others-contents-toggler {
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.h5p-data-view th[role="button"] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
@ -339,3 +353,6 @@ button.h5p-admin.disabled:hover {
|
|||
.h5p-data-view .h5p-facet-tag > span:active {
|
||||
color: #d20000;
|
||||
}
|
||||
.content-upgrade-log {
|
||||
color: red;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.h5p-confirmation-dialog-background {
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
|
@ -116,3 +116,68 @@ button.h5p-confirmation-dialog-exit:hover {
|
|||
margin-top: -6px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.h5p-confirmation-dialog-popup.offline .h5p-confirmation-dialog-buttons {
|
||||
float: none;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.h5p-confirmation-dialog-popup.offline .count-down {
|
||||
font-family: Arial;
|
||||
margin-top: 0.15em;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.h5p-confirmation-dialog-popup.offline .h5p-confirmation-dialog-confirm-button:before {
|
||||
content: "\e90b";
|
||||
font-weight: normal;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
.throbber-wrapper {
|
||||
display: none;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
background: rgba(44, 44, 44, 0.9);
|
||||
}
|
||||
|
||||
.throbber-wrapper.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.throbber-wrapper .throbber-container {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.throbber-wrapper .sending-requests-throbber{
|
||||
position: absolute;
|
||||
top: 7em;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.throbber-wrapper .sending-requests-throbber:before {
|
||||
display: block;
|
||||
font-family: 'H5P';
|
||||
content: "\e90b";
|
||||
color: white;
|
||||
font-size: 10em;
|
||||
animation: request-throbber 1.5s infinite linear;
|
||||
}
|
||||
|
||||
@keyframes request-throbber {
|
||||
from {
|
||||
transform: rotate(0);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
216
styles/h5p.css
216
styles/h5p.css
|
@ -3,15 +3,27 @@
|
|||
/* Custom H5P font to use for icons. */
|
||||
@font-face {
|
||||
font-family: 'h5p';
|
||||
src: url('../fonts/h5p-core-19.eot?cb8kvi');
|
||||
src: url('../fonts/h5p-core-19.eot?cb8kvi#iefix') format('embedded-opentype'),
|
||||
url('../fonts/h5p-core-19.ttf?cb8kvi') format('truetype'),
|
||||
url('../fonts/h5p-core-19.woff?cb8kvi') format('woff'),
|
||||
url('../fonts/h5p-core-19.svg?cb8kvi#h5p') format('svg');
|
||||
src: url('../fonts/h5p-core-28.eot?h1atjl');
|
||||
src: url('../fonts/h5p-core-28.eot?h1atjl#iefix') format('embedded-opentype'),
|
||||
url('../fonts/h5p-core-28.ttf?h1atjl') format('truetype'),
|
||||
url('../fonts/h5p-core-28.woff?h1atjl') format('woff'),
|
||||
url('../fonts/h5p-core-28.svg?h1atjl#h5p-core-28') format('svg');
|
||||
font-weight: 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 {
|
||||
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%;
|
||||
|
@ -43,6 +55,8 @@ html.h5p-iframe .h5p-content {
|
|||
line-height: 1.5em;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
-webkit-text-size-adjust: none;
|
||||
text-size-adjust: none;
|
||||
}
|
||||
html.h5p-iframe .h5p-fullscreen .h5p-content,
|
||||
html.h5p-iframe .h5p-semi-fullscreen .h5p-content {
|
||||
|
@ -199,13 +213,13 @@ div.h5p-fullscreen {
|
|||
background: none;
|
||||
padding: 0 0.75em 0 0.25em;
|
||||
vertical-align: top;
|
||||
color: #999;
|
||||
color: #707070;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
line-height: 23px;
|
||||
line-height: 22px;
|
||||
}
|
||||
.h5p-actions > .h5p-button:hover {
|
||||
color: #666;
|
||||
color: #333;
|
||||
}
|
||||
.h5p-actions > .h5p-button:active,
|
||||
.h5p-actions > .h5p-button:focus,
|
||||
|
@ -223,12 +237,12 @@ div.h5p-fullscreen {
|
|||
.h5p-actions > .h5p-button:before {
|
||||
font-family: 'H5P';
|
||||
font-size: 20px;
|
||||
line-height: 20px;
|
||||
vertical-align: top;
|
||||
line-height: 23px;
|
||||
vertical-align: bottom;
|
||||
padding-right: 0;
|
||||
}
|
||||
.h5p-actions > .h5p-button.h5p-export:before {
|
||||
content: "\e893";
|
||||
content: "\e90b";
|
||||
}
|
||||
.h5p-actions > .h5p-button.h5p-copyrights:before {
|
||||
content: "\e88f";
|
||||
|
@ -260,7 +274,7 @@ div.h5p-fullscreen {
|
|||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
z-index: 100;
|
||||
padding: 2em;
|
||||
box-sizing: border-box;
|
||||
|
@ -297,13 +311,20 @@ div.h5p-fullscreen {
|
|||
padding: 0.325em 0.5em 0.25em;
|
||||
line-height: 1.25em;
|
||||
border-bottom: 1px solid #ccc;
|
||||
z-index: 2;
|
||||
}
|
||||
.h5p-embed-dialog .h5p-inner {
|
||||
width: 300px;
|
||||
.h5p-popup-dialog .h5p-inner > h2 > a {
|
||||
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%;
|
||||
top: 50%;
|
||||
margin: 0 0 0 -150px;
|
||||
transition: margin 250ms linear 100ms;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.h5p-embed-dialog .h5p-embed-code-container,
|
||||
.h5p-embed-size {
|
||||
|
@ -339,11 +360,14 @@ div.h5p-fullscreen {
|
|||
padding: 1em;
|
||||
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-x: hidden;
|
||||
overflow-y: auto;
|
||||
color: #555555;
|
||||
height: 100%;
|
||||
}
|
||||
.h5p-popup-dialog .h5p-scroll-content::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
|
@ -357,11 +381,6 @@ div.h5p-fullscreen {
|
|||
}
|
||||
.h5p-popup-dialog .h5p-close {
|
||||
cursor: pointer;
|
||||
outline:none
|
||||
}
|
||||
.h5p-popup-dialog .h5p-close:after {
|
||||
font-family: 'H5P';
|
||||
content: "\e894";
|
||||
font-size: 2em;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
|
@ -372,6 +391,11 @@ div.h5p-fullscreen {
|
|||
color: #656565;
|
||||
cursor: pointer;
|
||||
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:focus:after {
|
||||
|
@ -402,7 +426,6 @@ div.h5p-fullscreen {
|
|||
.h5p-expander {
|
||||
cursor: pointer;
|
||||
font-size: 1.125em;
|
||||
outline: none;
|
||||
margin: 0.5em 0 0;
|
||||
display: inline-block;
|
||||
}
|
||||
|
@ -455,3 +478,148 @@ div.h5p-fullscreen {
|
|||
.h5p-dialog-ok-button:active {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue