pageflow 15.2.2 → 15.6.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pageflow might be problematic. Click here for more details.

Files changed (213) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -118
  3. data/README.md +2 -3
  4. data/admins/pageflow/accounts.rb +1 -98
  5. data/admins/pageflow/entry.rb +21 -1
  6. data/admins/pageflow/entry_templates.rb +140 -0
  7. data/admins/pageflow/membership.rb +12 -0
  8. data/admins/pageflow/user.rb +5 -5
  9. data/app/assets/javascripts/pageflow/admin/entries.js +65 -0
  10. data/app/assets/javascripts/pageflow/admin/users.js +1 -1
  11. data/app/assets/javascripts/pageflow/asset_urls.js.erb +1 -0
  12. data/app/assets/javascripts/pageflow/base.js +0 -12
  13. data/app/assets/javascripts/pageflow/components.js +2 -6
  14. data/app/assets/javascripts/pageflow/dist/ui.js +178 -55
  15. data/app/assets/javascripts/pageflow/editor/vendor.js +1 -0
  16. data/app/assets/javascripts/pageflow/vendor.js +12 -10
  17. data/app/assets/stylesheets/pageflow/base.scss +0 -7
  18. data/app/assets/stylesheets/pageflow/editor/base.scss +5 -2
  19. data/app/assets/stylesheets/pageflow/editor/composables.scss +5 -1
  20. data/app/assets/stylesheets/pageflow/editor/drop_down_button.scss +1 -1
  21. data/app/assets/stylesheets/pageflow/editor/emulation_mode_button.scss +44 -55
  22. data/app/assets/stylesheets/pageflow/editor/help.scss +2 -2
  23. data/app/assets/stylesheets/pageflow/editor/select_button.scss +1 -1
  24. data/app/assets/stylesheets/pageflow/editor/sidebar_footer.scss +1 -1
  25. data/app/assets/stylesheets/pageflow/entries.scss +1 -1
  26. data/app/assets/stylesheets/pageflow/loading_spinner.scss +4 -1
  27. data/app/assets/stylesheets/pageflow/navigation_mobile.scss +4 -4
  28. data/app/assets/stylesheets/pageflow/themes/default/anchors.scss +1 -1
  29. data/app/assets/stylesheets/pageflow/themes/default/logo/variant/watermark.scss +1 -1
  30. data/app/assets/stylesheets/pageflow/themes/default/page.scss +7 -0
  31. data/app/assets/stylesheets/pageflow/themes/default/page/anchors.scss +1 -1
  32. data/app/assets/stylesheets/pageflow/themes/default/player_controls/classic/control_bar.scss +1 -1
  33. data/app/assets/stylesheets/pageflow/themes/default/player_controls/classic/info_box.scss +1 -1
  34. data/app/assets/stylesheets/pageflow/themes/default/player_controls/shared/menu_bar.scss +2 -2
  35. data/app/assets/stylesheets/pageflow/themes/default/player_controls/slim/control_bar.scss +2 -2
  36. data/app/assets/stylesheets/pageflow/themes/default/player_controls/slim/info_box.scss +1 -1
  37. data/app/assets/stylesheets/pageflow/themes/default/player_controls/slim/quality_menu.scss +2 -2
  38. data/app/assets/stylesheets/pageflow/themes/default/player_controls/waveform/wave.scss +1 -1
  39. data/app/assets/stylesheets/pageflow/ui/forms.scss +9 -2
  40. data/app/assets/stylesheets/pageflow/ui/input/extended_select_input.scss +2 -2
  41. data/app/assets/stylesheets/pageflow/ui/tooltip.scss +17 -3
  42. data/app/helpers/pageflow/admin/entries_helper.rb +16 -0
  43. data/app/helpers/pageflow/structured_data_helper.rb +0 -2
  44. data/app/models/pageflow/account.rb +21 -1
  45. data/app/models/pageflow/account_role_query.rb +1 -1
  46. data/app/models/pageflow/chapter.rb +3 -9
  47. data/app/models/pageflow/entry.rb +9 -2
  48. data/app/models/pageflow/entry_duplicate.rb +1 -0
  49. data/app/models/pageflow/entry_template.rb +16 -2
  50. data/app/models/pageflow/managed_user_query.rb +1 -1
  51. data/app/models/pageflow/page.rb +1 -4
  52. data/app/models/pageflow/revision.rb +0 -4
  53. data/app/models/pageflow/storyline.rb +2 -9
  54. data/app/policies/pageflow/account_policy.rb +10 -0
  55. data/app/policies/pageflow/entry_template_policy.rb +5 -1
  56. data/app/policies/pageflow/folder_policy.rb +2 -2
  57. data/app/policies/pageflow/membership_policy.rb +2 -2
  58. data/app/policies/pageflow/theming_policy.rb +2 -2
  59. data/app/policies/pageflow/user_policy.rb +1 -1
  60. data/app/views/admin/accounts/_entry_template_details.html.arb +7 -5
  61. data/app/views/admin/accounts/_form.html.erb +3 -49
  62. data/app/views/admin/entries/_attributes_table.html.arb +5 -0
  63. data/app/views/admin/entries/_not_allowed_to_see_entry_types.json.jbuilder +2 -0
  64. data/app/views/admin/entries/entry_types.json.jbuilder +4 -0
  65. data/app/views/admin/entry_templates/_form.html.erb +58 -0
  66. data/app/views/admin/users/_not_allowed_to_see_user_quota.html.erb +3 -0
  67. data/app/views/components/pageflow/admin/entry_templates_tab.rb +48 -0
  68. data/app/views/pageflow/admin/initial_passwords/edit.html.erb +2 -1
  69. data/app/views/pageflow/admin/users/_quota_exhausted.html.erb +1 -1
  70. data/app/views/pageflow/themes/_theme.json.jbuilder +1 -1
  71. data/app/views/pageflow/video_files/_video_file.json.jbuilder +8 -1
  72. data/config/initializers/admin_resource_tabs.rb +5 -0
  73. data/config/initializers/help_entries.rb +1 -5
  74. data/config/initializers/revision_components.rb +5 -0
  75. data/config/locales/de.yml +88 -155
  76. data/config/locales/en.yml +79 -143
  77. data/db/migrate/20200515112500_add_constraints_to_entry_templates.rb +21 -0
  78. data/db/migrate/20200807135200_rename_pageflow_entry_template_entry_type_to_entry_type_name.rb +7 -0
  79. data/entry_types/paged/app/assets/javascripts/pageflow_paged/components.js +7 -0
  80. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/editor.js +1528 -1349
  81. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/frontend.js +9258 -0
  82. data/{app/assets/javascripts/pageflow → entry_types/paged/app/assets/javascripts/pageflow_paged}/dist/react-client.js +1 -1
  83. data/{app/assets/javascripts/pageflow → entry_types/paged/app/assets/javascripts/pageflow_paged}/dist/react-server.js +3 -3
  84. data/entry_types/paged/app/assets/javascripts/pageflow_paged/frontend.js +6 -0
  85. data/entry_types/paged/app/assets/javascripts/pageflow_paged/server_rendering.js +9 -0
  86. data/entry_types/paged/app/assets/javascripts/pageflow_paged/vendor.js +9 -0
  87. data/entry_types/paged/app/assets/javascripts/pageflow_paged/videojs.js +6 -0
  88. data/entry_types/paged/app/controllers/pageflow_paged/application_controller.rb +2 -2
  89. data/{app/helpers/pageflow → entry_types/paged/app/helpers/pageflow_paged}/page_background_asset_helper.rb +4 -3
  90. data/{app/helpers/pageflow → entry_types/paged/app/helpers/pageflow_paged}/react_server_side_rendering_helper.rb +23 -2
  91. data/entry_types/paged/app/views/layouts/pageflow_paged/_loading_spinner_inline_script.html.erb +1 -0
  92. data/entry_types/paged/app/views/layouts/pageflow_paged/application.html.erb +3 -3
  93. data/entry_types/paged/app/views/pageflow_paged/editor/entries/_head.html.erb +4 -2
  94. data/entry_types/paged/app/views/pageflow_paged/entries/_entry.html.erb +1 -1
  95. data/{app/views/pageflow → entry_types/paged/app/views/pageflow_paged}/page_background_asset/_element.html.erb +0 -0
  96. data/{app/views/pageflow → entry_types/paged/app/views/pageflow_paged}/react/_widget.html.erb +0 -0
  97. data/{app/views/pageflow → entry_types/paged/app/views/pageflow_paged}/react/page.html.erb +0 -0
  98. data/entry_types/paged/config/initializers/features.rb +1 -1
  99. data/entry_types/paged/config/initializers/help_entries.rb +17 -0
  100. data/entry_types/paged/config/locales/new/help.de.yml +162 -0
  101. data/entry_types/paged/config/locales/new/help.en.yml +153 -0
  102. data/entry_types/paged/lib/pageflow_paged/engine.rb +13 -0
  103. data/entry_types/paged/lib/pageflow_paged/plugin.rb +5 -1
  104. data/entry_types/paged/lib/pageflow_paged/react.rb +12 -0
  105. data/{lib/pageflow → entry_types/paged/lib/pageflow_paged}/react/page_type.rb +2 -2
  106. data/{lib/pageflow → entry_types/paged/lib/pageflow_paged}/react/widget_type.rb +2 -2
  107. data/entry_types/paged/lib/tasks/pageflow_paged_tasks.rake +7 -0
  108. data/entry_types/paged/vendor/assets/javascripts/development/pageflow_paged/vendor/react-server.js +20613 -0
  109. data/entry_types/paged/vendor/assets/javascripts/development/pageflow_paged/vendor/react.js +21495 -0
  110. data/{vendor/assets/javascripts → entry_types/paged/vendor/assets/javascripts/pageflow_paged/vendor}/dash.all.min.js +0 -0
  111. data/{vendor/assets/javascripts → entry_types/paged/vendor/assets/javascripts/pageflow_paged/vendor}/videojs-dash.js +0 -0
  112. data/{vendor/assets/javascripts → entry_types/paged/vendor/assets/javascripts/pageflow_paged/vendor}/videojs.js +0 -0
  113. data/entry_types/paged/vendor/assets/javascripts/production/pageflow_paged/vendor/react-server.js +24 -0
  114. data/entry_types/paged/vendor/assets/javascripts/production/pageflow_paged/vendor/react.js +24 -0
  115. data/entry_types/scrolled/app/assets/javascripts/pageflow_scrolled/legacy.js +0 -0
  116. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/chapters_controller.rb +2 -2
  117. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/content_elements_controller.rb +14 -4
  118. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/sections_controller.rb +2 -2
  119. data/entry_types/scrolled/app/controllers/pageflow_scrolled/entries_controller.rb +10 -0
  120. data/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/seed_html_helper.rb +7 -0
  121. data/entry_types/scrolled/app/helpers/pageflow_scrolled/entry_json_seed_helper.rb +2 -0
  122. data/entry_types/scrolled/app/helpers/pageflow_scrolled/favicon_helper.rb +21 -0
  123. data/entry_types/scrolled/app/helpers/pageflow_scrolled/react_server_side_rendering_helper.rb +40 -0
  124. data/entry_types/scrolled/app/helpers/pageflow_scrolled/themes_helper.rb +36 -0
  125. data/entry_types/scrolled/app/models/pageflow_scrolled/chapter.rb +3 -9
  126. data/entry_types/scrolled/app/models/pageflow_scrolled/content_element.rb +37 -2
  127. data/entry_types/scrolled/app/models/pageflow_scrolled/section.rb +3 -9
  128. data/entry_types/scrolled/app/models/pageflow_scrolled/storyline.rb +1 -9
  129. data/entry_types/scrolled/app/views/pageflow_scrolled/editor/content_elements/batch.json.jbuilder +2 -0
  130. data/entry_types/scrolled/app/views/pageflow_scrolled/editor/entries/_head.html.erb +1 -7
  131. data/entry_types/scrolled/app/views/pageflow_scrolled/entries/_global_notices.html.erb +10 -0
  132. data/entry_types/scrolled/app/views/pageflow_scrolled/entries/show.html.erb +28 -11
  133. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder +3 -0
  134. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_theme.json.jbuilder +8 -0
  135. data/entry_types/scrolled/app/views/pageflow_scrolled/favicons/_entry.html.erb +10 -0
  136. data/entry_types/scrolled/config/initializers/help_entries.rb +16 -0
  137. data/entry_types/scrolled/config/locales/de.yml +669 -0
  138. data/entry_types/scrolled/config/locales/en.yml +488 -0
  139. data/entry_types/scrolled/config/routes.rb +1 -0
  140. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/install_generator.rb +76 -6
  141. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/android-chrome-192x192.png +0 -0
  142. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/android-chrome-512x512.png +0 -0
  143. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/apple-touch-icon.png +0 -0
  144. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/browserconfig.xml +9 -0
  145. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/favicon-16x16.png +0 -0
  146. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/favicon-32x32.png +0 -0
  147. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/favicon.ico +0 -0
  148. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/mstile-150x150.png +0 -0
  149. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/safari-pinned-tab.svg +46 -0
  150. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/site.webmanifest +19 -0
  151. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoDesktop.svg +56 -0
  152. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoMobile.svg +22 -0
  153. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/unmute.mp3 +0 -0
  154. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/themes_plugin.rb.tt +26 -0
  155. data/entry_types/scrolled/lib/pageflow_scrolled/engine.rb +6 -0
  156. data/entry_types/scrolled/lib/pageflow_scrolled/plugin.rb +3 -1
  157. data/entry_types/scrolled/lib/pageflow_scrolled/seeds.rb +90 -30
  158. data/entry_types/scrolled/lib/tasks/pageflow_scrolled/create_bundle_symlinks_for_yarn.rake +33 -0
  159. data/entry_types/scrolled/lib/tasks/pageflow_scrolled/dummy.rake +8 -0
  160. data/entry_types/scrolled/lib/tasks/pageflow_scrolled/storybook.rake +173 -0
  161. data/entry_types/scrolled/package/config/webpack.js +11 -0
  162. data/entry_types/scrolled/package/contentElements-editor.js +316 -185
  163. data/entry_types/scrolled/package/contentElements-frontend.css +1 -0
  164. data/entry_types/scrolled/package/contentElements-frontend.js +940 -304
  165. data/entry_types/scrolled/package/editor.js +2930 -371
  166. data/entry_types/scrolled/package/frontend-server.js +228 -0
  167. data/entry_types/scrolled/package/frontend/EditableText-7093fd0e.js +1071 -0
  168. data/entry_types/scrolled/package/frontend/Viewer-e49e7807.js +387 -0
  169. data/entry_types/scrolled/package/frontend/Wavesurfer-0adf5667.js +375 -0
  170. data/entry_types/scrolled/package/frontend/components-6a6793ca.js +2534 -0
  171. data/entry_types/scrolled/package/frontend/getPrototypeOf-63c7c8e8.js +86 -0
  172. data/entry_types/scrolled/package/frontend/i18n-4dc6c377.js +1092 -0
  173. data/entry_types/scrolled/package/frontend/index.css +9 -0
  174. data/entry_types/scrolled/package/frontend/index.js +5686 -0
  175. data/entry_types/scrolled/package/frontend/useBrowserFeature-91a4c29d.js +33 -0
  176. data/entry_types/scrolled/package/package.json +30 -9
  177. data/entry_types/scrolled/spec/fixtures/audio.m4a +0 -0
  178. data/entry_types/scrolled/spec/fixtures/video.mp4 +0 -0
  179. data/lib/generators/pageflow/initializer/templates/pageflow.rb +14 -9
  180. data/lib/pageflow/ability_mixin.rb +14 -2
  181. data/lib/pageflow/configuration.rb +6 -5
  182. data/lib/pageflow/entry_export_import/revision_serialization.rb +15 -13
  183. data/lib/pageflow/entry_export_import/revision_serialization/import.rb +18 -26
  184. data/lib/pageflow/entry_type_configuration.rb +2 -0
  185. data/lib/pageflow/global_config_api.rb +5 -4
  186. data/lib/pageflow/nested_revision_component.rb +49 -0
  187. data/lib/pageflow/react.rb +4 -2
  188. data/lib/pageflow/revision_component.rb +6 -2
  189. data/lib/pageflow/themes.rb +4 -0
  190. data/lib/pageflow/user_mixin.rb +2 -1
  191. data/lib/pageflow/version.rb +1 -1
  192. data/{packages/pageflow → package}/config/jest/index.js +8 -2
  193. data/{packages/pageflow → package}/config/jest/transformers/jst.js +0 -0
  194. data/{packages/pageflow → package}/config/jest/transformers/upwardBabel.js +0 -0
  195. data/{packages/pageflow → package}/config/webpack.js +7 -0
  196. data/{packages/pageflow → package}/editor.js +482 -1130
  197. data/package/frontend.js +2553 -0
  198. data/{packages/pageflow → package}/package.json +3 -0
  199. data/{packages/pageflow → package}/testHelpers.js +114 -13
  200. data/{packages/pageflow → package}/ui.js +178 -55
  201. data/spec/factories/accounts.rb +3 -1
  202. data/spec/factories/entry_templates.rb +1 -0
  203. data/spec/factories/published_entries.rb +6 -1
  204. data/spec/factories/test_revision_components.rb +4 -0
  205. metadata +95 -36
  206. data/app/assets/javascripts/pageflow/dist/frontend.js +0 -5800
  207. data/app/assets/javascripts/pageflow/videojs.js +0 -6
  208. data/config/initializers/entry_types.rb +0 -4
  209. data/entry_types/scrolled/config/locales/new/de.yml +0 -269
  210. data/entry_types/scrolled/config/locales/new/en.yml +0 -264
  211. data/entry_types/scrolled/lib/tasks/pageflow_scrolled_tasks.rake +0 -96
  212. data/entry_types/scrolled/package/frontend.js +0 -2879
  213. data/packages/pageflow/config/jest/transformers/cssModules.js +0 -1
@@ -0,0 +1,2553 @@
1
+ import 'core-js/modules/es.array.from';
2
+ import 'core-js/modules/es.array.includes';
3
+ import 'core-js/modules/es.object.assign';
4
+ import 'core-js/modules/es.object.entries';
5
+ import 'core-js/modules/es.object.keys';
6
+ import 'core-js/modules/es.object.to-string';
7
+ import 'core-js/modules/es.promise';
8
+ import 'core-js/modules/es.promise.finally';
9
+ import 'core-js/modules/es.string.iterator';
10
+ import 'core-js/modules/esnext.aggregate-error';
11
+ import 'core-js/modules/esnext.promise.all-settled';
12
+ import 'core-js/modules/esnext.promise.any';
13
+ import 'core-js/modules/esnext.promise.try';
14
+ import 'core-js/modules/web.dom-collections.iterator';
15
+ import 'classlist.js';
16
+ import BackboneEvents from 'backbone-events-standalone';
17
+ import VideoJS from 'video.js';
18
+
19
+ var log = function log(text, options) {
20
+ if (window.console && (debugMode() || options && options.force)) {
21
+ window.console.log(text);
22
+ }
23
+ };
24
+ var debugMode = function debugMode() {
25
+ return window.location.href.indexOf('debug=true') >= 0;
26
+ };
27
+
28
+ var state = typeof window !== 'undefined' && window.pageflow || {};
29
+
30
+ var assetUrls = state.assetUrls || {};
31
+
32
+ // https://developer.mozilla.org/en-US/docs/Web/API/document.cookie
33
+ var cookies = {
34
+ getItem: function getItem(sKey) {
35
+ if (!sKey) {
36
+ return null;
37
+ } // eslint-disable-next-line no-useless-escape
38
+
39
+
40
+ return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
41
+ },
42
+ setItem: function setItem(sKey, sValue, vEnd, sPath, sDomain, bSecure) {
43
+ // eslint-disable-next-line no-useless-escape
44
+ if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) {
45
+ return false;
46
+ }
47
+
48
+ var sExpires = "";
49
+
50
+ if (vEnd) {
51
+ switch (vEnd.constructor) {
52
+ case Number:
53
+ sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
54
+ break;
55
+
56
+ case String:
57
+ sExpires = "; expires=" + vEnd;
58
+ break;
59
+
60
+ case Date:
61
+ sExpires = "; expires=" + vEnd.toUTCString();
62
+ break;
63
+ }
64
+ }
65
+
66
+ document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");
67
+ return true;
68
+ },
69
+ removeItem: function removeItem(sKey, sPath, sDomain) {
70
+ if (!this.hasItem(sKey)) {
71
+ return false;
72
+ }
73
+
74
+ document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "");
75
+ return true;
76
+ },
77
+ hasItem: function hasItem(sKey) {
78
+ if (!sKey) {
79
+ return false;
80
+ } // eslint-disable-next-line no-useless-escape
81
+
82
+
83
+ return new RegExp("(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=").test(document.cookie);
84
+ },
85
+ keys: function keys() {
86
+ // eslint-disable-next-line no-useless-escape
87
+ var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);
88
+
89
+ for (var nLen = aKeys.length, nIdx = 0; nIdx < nLen; nIdx++) {
90
+ aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]);
91
+ }
92
+
93
+ return aKeys;
94
+ }
95
+ };
96
+
97
+ var events = Object.assign({}, BackboneEvents);
98
+
99
+ /**
100
+ * Detect browser via user agent. Use only if feature detection is not
101
+ * an option.
102
+ */
103
+ var Agent = function Agent(userAgent) {
104
+ return {
105
+ matchesSilk: function matchesSilk() {
106
+ return matches(/\bSilk\b/);
107
+ },
108
+ matchesDesktopSafari: function matchesDesktopSafari(options) {
109
+ if (options) {
110
+ return this.matchesSafari() && !this.matchesMobilePlatform() && matchesMinVersion(/Version\/(\d+)/i, options.minVersion);
111
+ } else {
112
+ return this.matchesSafari() && !this.matchesMobilePlatform();
113
+ }
114
+ },
115
+ matchesDesktopSafari9: function matchesDesktopSafari9() {
116
+ return this.matchesSafari9() && !this.matchesMobilePlatform();
117
+ },
118
+ matchesDesktopSafari10: function matchesDesktopSafari10() {
119
+ return this.matchesSafari10() && !this.matchesMobilePlatform();
120
+ },
121
+ matchesSafari9: function matchesSafari9() {
122
+ return this.matchesSafari() && matches(/Version\/9/i);
123
+ },
124
+ matchesSafari10: function matchesSafari10() {
125
+ return this.matchesSafari() && matches(/Version\/10/i);
126
+ },
127
+ matchesSafari11: function matchesSafari11() {
128
+ return this.matchesSafari() && matches(/Version\/11/i);
129
+ },
130
+ matchesSafari11AndAbove: function matchesSafari11AndAbove() {
131
+ return this.matchesSafari() && matchesMinVersion(/Version\/(\d+)/i, 11);
132
+ },
133
+ matchesSafari: function matchesSafari() {
134
+ // - Chrome also reports to be a Safari
135
+ // - Safari does not report to be a Chrome
136
+ // - Edge also reports to be a Safari, but also reports to be Chrome
137
+ return matches(/Safari\//i) && !matches(/Chrome/i);
138
+ },
139
+
140
+ /**
141
+ * Returns true on iOS Safari.
142
+ * @return {boolean}
143
+ */
144
+ matchesMobileSafari: function matchesMobileSafari() {
145
+ var matchers = [/iPod/i, /iPad/i, /iPhone/i];
146
+ return matchers.some(function (matcher) {
147
+ return userAgent.match(matcher);
148
+ }) && !window.MSStream || //IE exclusion from being detected as an iOS device;
149
+ matchesiPadSafari13AndAbove();
150
+ },
151
+
152
+ /**
153
+ * Returns true on iOS or Android.
154
+ * @return {boolean}
155
+ */
156
+ matchesMobilePlatform: function matchesMobilePlatform() {
157
+ var matchers = [/iPod/i, /iPad/i, /iPhone/i, /Android/i, /Silk/i, /IEMobile/i];
158
+ return matchers.some(function (matcher) {
159
+ return userAgent.match(matcher);
160
+ }) || matchesiPadSafari13AndAbove();
161
+ },
162
+
163
+ /**
164
+ * Returns true on Internet Explorser version 9, 10 and 11.
165
+ * @return {boolean}
166
+ */
167
+ matchesIEUpTo11: function matchesIEUpTo11() {
168
+ return userAgent.match(/Trident\//);
169
+ },
170
+
171
+ /**
172
+ * Returns true in InApp browser of Facebook app.
173
+ * @return {boolean}
174
+ */
175
+ matchesFacebookInAppBrowser: function matchesFacebookInAppBrowser() {
176
+ return userAgent.match(/FBAN/) && userAgent.match(/FBAV/);
177
+ },
178
+ matchesDesktopChrome: function matchesDesktopChrome(options) {
179
+ if (options) {
180
+ return this.matchesChrome() && !this.matchesMobilePlatform() && matchesMinVersion(/Chrome\/(\d+)/i, options.minVersion);
181
+ } else {
182
+ return this.matchesChrome() && !this.matchesMobilePlatform();
183
+ }
184
+ },
185
+ matchesDesktopFirefox: function matchesDesktopFirefox(options) {
186
+ if (options) {
187
+ return this.matchesFirefox() && !this.matchesMobilePlatform() && matchesMinVersion(/Firefox\/(\d+)/i, options.minVersion);
188
+ } else {
189
+ return this.matchesFirefox() && !this.matchesMobilePlatform();
190
+ }
191
+ },
192
+ matchesDesktopEdge: function matchesDesktopEdge(options) {
193
+ if (options) {
194
+ return this.matchesEdge() && !this.matchesMobilePlatform() && matchesMinVersion(/Edg\/(\d+)/i, options.minVersion);
195
+ } else {
196
+ return this.matchesEdge() && !this.matchesMobilePlatform();
197
+ }
198
+ },
199
+
200
+ /**
201
+ * Returns true on Google Chrome.
202
+ * @return {boolean}
203
+ */
204
+ matchesChrome: function matchesChrome() {
205
+ // - Edge also reports to be a Chrome
206
+ return matches(/Chrome\//i) && !matches(/Edg/i);
207
+ },
208
+
209
+ /**
210
+ * Returns true on Firefox.
211
+ * @return {boolean}
212
+ */
213
+ matchesFirefox: function matchesFirefox() {
214
+ return matches(/Firefox\//i) && !matches(/Seamonkey/i);
215
+ },
216
+
217
+ /**
218
+ * Returns true on Microsoft Edge.
219
+ * @return {boolean}
220
+ */
221
+ matchesEdge: function matchesEdge() {
222
+ return matches(/Edg\//i);
223
+ }
224
+ };
225
+
226
+ function matches(exp) {
227
+ return !!userAgent.match(exp);
228
+ }
229
+
230
+ function matchesMinVersion(exp, version) {
231
+ var match = userAgent.match(exp);
232
+ return match && match[1] && parseInt(match[1], 10) >= version;
233
+ } //After ios13 update, iPad reports the same user string
234
+ //as Safari on Dekstop MacOS.
235
+ //At the time of this writing there are no other devices
236
+ //with multi-touch support other than IOS/iPadOS
237
+ //See: https://stackoverflow.com/a/58064481
238
+
239
+
240
+ function matchesiPadSafari13AndAbove() {
241
+ return agent.matchesSafari() && navigator.maxTouchPoints > 1 && navigator.platform === 'MacIntel';
242
+ }
243
+ };
244
+ var agent = new Agent(typeof navigator !== 'undefined' ? navigator.userAgent : 'ssr');
245
+
246
+ /**
247
+ * Browser feature detection.
248
+ *
249
+ * @since 0.9
250
+ */
251
+
252
+ var browser = function () {
253
+ var tests = {},
254
+ results = {},
255
+ featureDetectionComplete = false;
256
+ var readyPromiseResolve;
257
+ var readyPromise = new Promise(function (resolve, reject) {
258
+ readyPromiseResolve = resolve;
259
+ });
260
+ return {
261
+ off: {},
262
+ on: {},
263
+ unset: {},
264
+
265
+ /**
266
+ * Add a feature test.
267
+ *
268
+ * @param name [String] Name of the feature. Can contain whitespace.
269
+ * @param test [Function] A function that either returns `true` or
270
+ * `false` or a promise that resolves to `true` or `false`.
271
+ * @memberof pageflow.browser
272
+ */
273
+ feature: function feature(name, test) {
274
+ var s = name.replace(/ /g, '_');
275
+
276
+ this.off[s] = function () {
277
+ window.localStorage['override ' + name] = 'off';
278
+ log('Feature off: ' + name, {
279
+ force: true
280
+ });
281
+ };
282
+
283
+ this.on[s] = function () {
284
+ window.localStorage['override ' + name] = 'on';
285
+ log('Feature on: ' + name, {
286
+ force: true
287
+ });
288
+ };
289
+
290
+ this.unset[s] = function () {
291
+ window.localStorage.removeItem('override ' + name);
292
+ log('Feature unset: ' + name, {
293
+ force: true
294
+ });
295
+ };
296
+
297
+ tests[name] = test;
298
+ },
299
+
300
+ /**
301
+ * Check whether the browser has a specific feature. This method
302
+ * may only be called after the `#ready` promise is resolved.
303
+ *
304
+ * @param name [String] Name of the feature.
305
+ * @return [Boolean]
306
+ * @memberof pageflow.browser
307
+ */
308
+ has: function has(name) {
309
+ if (!featureDetectionComplete) {
310
+ throw 'Feature detection has not finished yet.';
311
+ }
312
+
313
+ if (results[name] === undefined) {
314
+ throw 'Unknown feature "' + name + '".';
315
+ }
316
+
317
+ return results[name];
318
+ },
319
+
320
+ /**
321
+ * A promise that is resolved once feature detection has finished.
322
+ *
323
+ * @return Promise
324
+ * @memberof pageflow.browser
325
+ */
326
+ ready: function ready() {
327
+ return readyPromise;
328
+ },
329
+
330
+ /** @api private */
331
+ detectFeatures: function detectFeatures() {
332
+ var promises = {};
333
+
334
+ var asyncHas = function asyncHas(name) {
335
+ var runTest = function runTest() {
336
+ var value,
337
+ underscoredName = name.replace(/ /g, '_');
338
+
339
+ if (debugMode() && location.href.indexOf('&has=' + underscoredName) >= 0) {
340
+ value = location.href.indexOf('&has=' + underscoredName + '_on') >= 0;
341
+ log('FEATURE OVERRIDDEN ' + name + ': ' + value, {
342
+ force: true
343
+ });
344
+ return value;
345
+ } else if ((debugMode() || window.PAGEFLOW_ALLOW_FEATURE_OVERRIDES) && window.localStorage && typeof window.localStorage['override ' + name] !== 'undefined') {
346
+ value = window.localStorage['override ' + name] === 'on';
347
+ log('FEATURE OVERRIDDEN ' + name + ': ' + value, {
348
+ force: true
349
+ });
350
+ return value;
351
+ } else {
352
+ return tests[name](asyncHas);
353
+ }
354
+ };
355
+
356
+ promises[name] = promises[name] || Promise.all([runTest()]).then(function (a) {
357
+ return a[0];
358
+ });
359
+ return promises[name];
360
+ };
361
+
362
+ asyncHas.not = function (name) {
363
+ return asyncHas(name).then(function (result) {
364
+ return !result;
365
+ });
366
+ };
367
+
368
+ asyncHas.all = function ()
369
+ /* arguments */
370
+ {
371
+ return Promise.all(arguments).then(function (results) {
372
+ return results.every(function (result) {
373
+ return result;
374
+ });
375
+ });
376
+ };
377
+
378
+ Promise.all(Object.keys(tests).map(function (name) {
379
+ return asyncHas(name).then(function (result) {
380
+ var cssClassName = name.replace(/ /g, '_');
381
+ document.body.classList.toggle('has_' + cssClassName, !!result);
382
+ document.body.classList.toggle('has_no_' + cssClassName, !result);
383
+ results[name] = !!result;
384
+ });
385
+ })).then(function () {
386
+ featureDetectionComplete = true;
387
+ readyPromiseResolve();
388
+ });
389
+ return this.ready();
390
+ }
391
+ };
392
+ }();
393
+
394
+ browser.feature('autoplay support', function (has) {
395
+ return !agent.matchesSafari11AndAbove() && !agent.matchesMobilePlatform();
396
+ });
397
+
398
+ browser.feature('css animations', function () {
399
+ var prefixes = ['Webkit', 'Moz', 'O', 'ms', 'Khtml'],
400
+ elm = document.createElement('div');
401
+
402
+ if (elm.style.animationName !== undefined) {
403
+ return true;
404
+ }
405
+
406
+ for (var i = 0; i < prefixes.length; i++) {
407
+ if (elm.style[prefixes[i] + 'AnimationName'] !== undefined) {
408
+ return true;
409
+ }
410
+ }
411
+
412
+ return false;
413
+ });
414
+
415
+ // phone which hides parts of the browser viewport. Normally this is
416
+ // hidden once the user scrolls, but since there is no native
417
+ // scrolling in Pageflow, the bar stays and hides page elements like
418
+ // the slim player controls.
419
+
420
+ browser.feature('facebook toolbar', function (has) {
421
+ return has.all(has('iphone platform'), agent.matchesFacebookInAppBrowser());
422
+ });
423
+
424
+ browser.feature('ie', function () {
425
+ if (navigator.appName == 'Microsoft Internet Explorer') {
426
+ return true;
427
+ } else {
428
+ return false;
429
+ }
430
+ });
431
+
432
+ browser.feature('ios platform', function () {
433
+ return agent.matchesMobileSafari();
434
+ });
435
+ browser.feature('iphone platform', function (has) {
436
+ return has.all(has('ios platform'), has('phone platform'));
437
+ });
438
+
439
+ browser.feature('mobile platform', function () {
440
+ return agent.matchesMobilePlatform();
441
+ });
442
+
443
+ browser.feature('phone platform', function () {
444
+ var matchers = [/iPod/i, /iPad/i, /iPhone/i, /Android/i, /IEMobile/i];
445
+ return matchers.some(function (matcher) {
446
+ return navigator.userAgent.match(matcher) && window.innerWidth < 700;
447
+ });
448
+ });
449
+
450
+ browser.feature('pushstate support', function () {
451
+ return window.history && 'pushState' in window.history;
452
+ });
453
+
454
+ browser.feature('request animation frame support', function () {
455
+ return 'requestAnimationFrame' in window || 'web';
456
+ });
457
+
458
+ browser.feature('touch support', function () {
459
+ return 'ontouchstart' in window ||
460
+ /* Firefox on android */
461
+ window.DocumentTouch && document instanceof window.DocumentTouch ||
462
+ /* > 0 on IE touch devices */
463
+ navigator.maxTouchPoints;
464
+ });
465
+
466
+ browser.feature('rewrite video sources support', function () {
467
+ // set from conditionally included script file
468
+ return !state.ie9;
469
+ });
470
+ browser.feature('stop buffering support', function (has) {
471
+ return has.not('mobile platform');
472
+ });
473
+ browser.feature('buffer underrun waiting support', function (has) {
474
+ return has.not('mobile platform');
475
+ });
476
+ browser.feature('prebuffering support', function (has) {
477
+ return has.not('mobile platform');
478
+ });
479
+ browser.feature('mp4 support only', function (has) {
480
+ // - Silk does not play videos with hls source
481
+ // - Desktop Safari 9.1 does not loop hls videos
482
+ // - Desktop Safari 10 does not loop hls videos on El
483
+ // Capitan. Appears to be fixed on Sierra
484
+ return agent.matchesSilk() || agent.matchesDesktopSafari9() || agent.matchesDesktopSafari10();
485
+ });
486
+ browser.feature('mse and native hls support', function (has) {
487
+ return agent.matchesSafari() && !agent.matchesMobilePlatform();
488
+ });
489
+ browser.feature('hls support', function (has) {
490
+ return agent.matchesSafari() || agent.matchesMobilePlatform();
491
+ });
492
+ browser.feature('native video player', function (has) {
493
+ return has('iphone platform');
494
+ });
495
+
496
+ browser.feature('volume control support', function (has) {
497
+ return has.not('ios platform');
498
+ });
499
+ browser.feature('audio context volume fading support', function () {
500
+ return !agent.matchesDesktopSafari();
501
+ });
502
+
503
+ browser.agent = agent;
504
+ browser.Agent = Agent;
505
+
506
+ function _classCallCheck(instance, Constructor) {
507
+ if (!(instance instanceof Constructor)) {
508
+ throw new TypeError("Cannot call a class as a function");
509
+ }
510
+ }
511
+
512
+ function _defineProperties(target, props) {
513
+ for (var i = 0; i < props.length; i++) {
514
+ var descriptor = props[i];
515
+ descriptor.enumerable = descriptor.enumerable || false;
516
+ descriptor.configurable = true;
517
+ if ("value" in descriptor) descriptor.writable = true;
518
+ Object.defineProperty(target, descriptor.key, descriptor);
519
+ }
520
+ }
521
+
522
+ function _createClass(Constructor, protoProps, staticProps) {
523
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
524
+ if (staticProps) _defineProperties(Constructor, staticProps);
525
+ return Constructor;
526
+ }
527
+
528
+ /**
529
+ * Let plugins register functions which extend the editor or
530
+ * slideshow with certain functionality when a named feature is
531
+ * enabled.
532
+ *
533
+ * @alias pageflow.features
534
+ * @since 0.9
535
+ */
536
+
537
+ var Features =
538
+ /*#__PURE__*/
539
+ function () {
540
+ /** @lends pageflow.features */
541
+
542
+ /** @api private */
543
+ function Features() {
544
+ _classCallCheck(this, Features);
545
+
546
+ this.registry = {};
547
+ this.enabledFeatureNames = [];
548
+ }
549
+ /**
550
+ * `pageflow.features` has been renamed to `pageflow.browser`.
551
+ * @deprecated
552
+ */
553
+
554
+
555
+ _createClass(Features, [{
556
+ key: "has",
557
+ value: function has()
558
+ /* arguments */
559
+ {
560
+ return browser.has.apply(browser, arguments);
561
+ }
562
+ /**
563
+ * Register a function to configure a feature when it is active.
564
+ *
565
+ * @param {String} scope - Name of the scope the passed function
566
+ * shall be called in.
567
+ * @param name [String] Name of the feature
568
+ * @param fn [Function] Function to call when the given feature
569
+ * is activate.
570
+ */
571
+
572
+ }, {
573
+ key: "register",
574
+ value: function register(scope, name, fn) {
575
+ this.registry[scope] = this.registry[scope] || {};
576
+ this.registry[scope][name] = this.registry[scope][name] || [];
577
+ this.registry[scope][name].push(fn);
578
+ }
579
+ /**
580
+ * Check if a feature as been enabled.
581
+ *
582
+ * @param name [String]
583
+ * @return [Boolean]
584
+ */
585
+
586
+ }, {
587
+ key: "isEnabled",
588
+ value: function isEnabled(name) {
589
+ return this.enabledFeatureNames.includes(name);
590
+ }
591
+ /** @api private */
592
+
593
+ }, {
594
+ key: "enable",
595
+ value: function enable(scope, names) {
596
+ var fns = this.registry[scope] || {};
597
+ this.enabledFeatureNames = this.enabledFeatureNames.concat(names);
598
+ names.forEach(function (name) {
599
+ (fns[name] || []).forEach(function (fn) {
600
+ fn();
601
+ });
602
+ });
603
+ }
604
+ }]);
605
+
606
+ return Features;
607
+ }();
608
+ var features = new Features();
609
+
610
+ function _defineProperty(obj, key, value) {
611
+ if (key in obj) {
612
+ Object.defineProperty(obj, key, {
613
+ value: value,
614
+ enumerable: true,
615
+ configurable: true,
616
+ writable: true
617
+ });
618
+ } else {
619
+ obj[key] = value;
620
+ }
621
+
622
+ return obj;
623
+ }
624
+
625
+ function ownKeys(object, enumerableOnly) {
626
+ var keys = Object.keys(object);
627
+
628
+ if (Object.getOwnPropertySymbols) {
629
+ var symbols = Object.getOwnPropertySymbols(object);
630
+ if (enumerableOnly) symbols = symbols.filter(function (sym) {
631
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
632
+ });
633
+ keys.push.apply(keys, symbols);
634
+ }
635
+
636
+ return keys;
637
+ }
638
+
639
+ function _objectSpread2(target) {
640
+ for (var i = 1; i < arguments.length; i++) {
641
+ var source = arguments[i] != null ? arguments[i] : {};
642
+
643
+ if (i % 2) {
644
+ ownKeys(Object(source), true).forEach(function (key) {
645
+ _defineProperty(target, key, source[key]);
646
+ });
647
+ } else if (Object.getOwnPropertyDescriptors) {
648
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
649
+ } else {
650
+ ownKeys(Object(source)).forEach(function (key) {
651
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
652
+ });
653
+ }
654
+ }
655
+
656
+ return target;
657
+ }
658
+
659
+ var handleFailedPlay = function handleFailedPlay(player, options) {
660
+ var originalPlay = player.play;
661
+
662
+ player.play = function ()
663
+ /* arguments */
664
+ {
665
+ var result = originalPlay.apply(player, arguments);
666
+
667
+ if (result && typeof result["catch"] !== 'undefined') {
668
+ return result["catch"](function (e) {
669
+ if (e.name === 'NotAllowedError' && options.hasAutoplaySupport) {
670
+ if (options.fallbackToMutedAutoplay) {
671
+ player.muted(true);
672
+ return originalPlay.apply(player, arguments).then(function () {
673
+ player.trigger('playmuted');
674
+ }, function () {
675
+ player.trigger('playfailed');
676
+ });
677
+ } else {
678
+ player.trigger('playfailed');
679
+ }
680
+ } else {
681
+ log('Caught play exception for video.');
682
+ }
683
+ });
684
+ }
685
+
686
+ return result;
687
+ };
688
+ };
689
+
690
+ var asyncPlay = function asyncPlay(player) {
691
+ var originalPlay = player.play;
692
+ var originalPause = player.pause;
693
+ var intendingToPlay = false;
694
+ var intendingToPause = false;
695
+
696
+ player.play = function ()
697
+ /* arguments */
698
+ {
699
+ player.intendToPlay();
700
+ return originalPlay.apply(player, arguments);
701
+ };
702
+
703
+ player.pause = function ()
704
+ /* arguments */
705
+ {
706
+ player.intendToPause();
707
+ return originalPause.apply(player, arguments);
708
+ };
709
+
710
+ player.intendToPlay = function () {
711
+ intendingToPlay = true;
712
+ intendingToPause = false;
713
+ };
714
+
715
+ player.intendToPause = function () {
716
+ intendingToPause = true;
717
+ intendingToPlay = false;
718
+ };
719
+
720
+ player.intendingToPlay = function () {
721
+ return intendingToPlay;
722
+ };
723
+
724
+ player.intendingToPause = function () {
725
+ return intendingToPause;
726
+ };
727
+
728
+ player.ifIntendingToPause = function () {
729
+ return promiseFromBoolean(intendingToPause);
730
+ };
731
+
732
+ player.ifIntendingToPlay = function () {
733
+ return promiseFromBoolean(intendingToPlay);
734
+ };
735
+
736
+ function promiseFromBoolean(value) {
737
+ return new Promise(function (resolve, reject) {
738
+ if (value) {
739
+ resolve();
740
+ } else {
741
+ reject('aborted');
742
+ }
743
+ });
744
+ }
745
+ };
746
+
747
+ var hooks = function hooks(player, _hooks) {
748
+ var originalPlay = player.play;
749
+
750
+ player.updateHooks = function (newHooks) {
751
+ _hooks = newHooks;
752
+ };
753
+
754
+ player.play = function ()
755
+ /* args */
756
+ {
757
+ var args = arguments;
758
+ player.trigger('beforeplay');
759
+ player.intendToPlay();
760
+
761
+ if (_hooks.before) {
762
+ return Promise.all([_hooks.before()]).then(function () {
763
+ return player.ifIntendingToPlay().then(function () {
764
+ return originalPlay.apply(player, args);
765
+ });
766
+ });
767
+ } else {
768
+ return originalPlay.apply(player, args);
769
+ }
770
+ };
771
+
772
+ if (player.afterHookListener) {
773
+ player.off('pause', player.afterHookListener);
774
+ player.off('ended', player.afterHookListener);
775
+ }
776
+
777
+ player.afterHookListener = function () {
778
+ if (_hooks.after) {
779
+ _hooks.after();
780
+ }
781
+ };
782
+
783
+ player.on('pause', player.afterHookListener);
784
+ player.on('ended', player.afterHookListener);
785
+ };
786
+
787
+ var volumeBinding = function volumeBinding(player, settings, options) {
788
+ options = options || {};
789
+ var originalPlay = player.play;
790
+ var originalPause = player.pause;
791
+ var volumeFactor = 'volumeFactor' in options ? options.volumeFactor : 1;
792
+
793
+ player.play = function () {
794
+ player.intendToPlay();
795
+ player.volume(player.targetVolume());
796
+ listenToVolumeSetting();
797
+ return originalPlay.call(player);
798
+ };
799
+
800
+ player.playAndFadeIn = function (duration) {
801
+ if (!player.paused() && !player.intendingToPause()) {
802
+ return Promise.resolve();
803
+ }
804
+
805
+ player.intendToPlay();
806
+ player.volume(0);
807
+ return Promise.all([originalPlay.call(player)]).then(function () {
808
+ listenToVolumeSetting();
809
+ return player.ifIntendingToPlay().then(function () {
810
+ return player.fadeVolume(player.targetVolume(), duration).then(null, function () {
811
+ return Promise.resolve();
812
+ });
813
+ });
814
+ });
815
+ };
816
+
817
+ player.pause = function () {
818
+ stopListeningToVolumeSetting();
819
+ originalPause.call(player);
820
+ };
821
+
822
+ player.fadeOutAndPause = function (duration) {
823
+ if (player.paused() && !player.intendingToPlay()) {
824
+ return Promise.resolve();
825
+ }
826
+
827
+ player.intendToPause();
828
+ stopListeningToVolumeSetting();
829
+ return player.fadeVolume(0, duration).then(function () {
830
+ return player.ifIntendingToPause().then(function () {
831
+ originalPause.call(player);
832
+ });
833
+ });
834
+ };
835
+
836
+ player.changeVolumeFactor = function (factor, duration) {
837
+ volumeFactor = factor;
838
+ return player.fadeVolume(player.targetVolume(), duration);
839
+ };
840
+
841
+ player.targetVolume = function () {
842
+ return settings.get('volume') * volumeFactor;
843
+ };
844
+
845
+ function listenToVolumeSetting() {
846
+ player.on('dispose', stopListeningToVolumeSetting);
847
+ settings.on('change:volume', onVolumeChange);
848
+ }
849
+
850
+ function stopListeningToVolumeSetting() {
851
+ player.off('dispose', stopListeningToVolumeSetting);
852
+ settings.off('change:volume', onVolumeChange);
853
+ }
854
+
855
+ function onVolumeChange(model, value) {
856
+ player.fadeVolume(player.targetVolume(), 40);
857
+ }
858
+ };
859
+
860
+ /**
861
+ * Obtain the globally shared audio context. There can only be a
862
+ * limited number of `AudioContext` objects in one page.
863
+ *
864
+ * @since 12.1
865
+ */
866
+
867
+ var audioContext = {
868
+ /**
869
+ * @returns [AudioContext]
870
+ * Returns `null` if web audio API is not supported or creating
871
+ * the context fails.
872
+ */
873
+ get: function get() {
874
+ var AudioContext = window.AudioContext || window.webkitAudioContext;
875
+
876
+ if (typeof this._audioContext === 'undefined') {
877
+ try {
878
+ this._audioContext = AudioContext && new AudioContext();
879
+ } catch (e) {
880
+ this._audioContext = null;
881
+ log('Failed to create AudioContext.', {
882
+ force: true
883
+ });
884
+ }
885
+ }
886
+
887
+ return this._audioContext;
888
+ }
889
+ };
890
+
891
+ var webAudio = function webAudio(player, audioContext) {
892
+ var gainNode;
893
+ var currentResolve;
894
+ var currentTimeout;
895
+ var currentValue = 1;
896
+ var lastStartTime;
897
+ var lastDuration;
898
+ var lastStartValue;
899
+ var allowedMinValue = 0.000001;
900
+
901
+ if (audioContext.state === 'suspended') {
902
+ events.on('background_media:unmute', function () {
903
+ player.volume(currentValue);
904
+ });
905
+ }
906
+
907
+ function tryResumeIfSuspended() {
908
+ return new Promise(function (resolve, reject) {
909
+ if (audioContext.state === 'suspended') {
910
+ var maybePromise = audioContext.resume();
911
+
912
+ if (maybePromise && maybePromise.then) {
913
+ maybePromise.then(handlePromise);
914
+ } else {
915
+ setTimeout(handlePromise, 0);
916
+ }
917
+ } else {
918
+ resolve();
919
+ }
920
+
921
+ function handlePromise() {
922
+ if (audioContext.state === 'suspended') {
923
+ reject();
924
+ } else {
925
+ resolve();
926
+ }
927
+ }
928
+ });
929
+ }
930
+
931
+ player.volume = function (value) {
932
+ if (typeof value !== 'undefined') {
933
+ tryResumeIfSuspended().then(function () {
934
+ ensureGainNode();
935
+ cancel();
936
+ currentValue = ensureInAllowedRange(value);
937
+ gainNode.gain.setValueAtTime(currentValue, audioContext.currentTime);
938
+ }, function () {
939
+ currentValue = ensureInAllowedRange(value);
940
+ });
941
+ }
942
+
943
+ return Math.round(currentValue * 100) / 100;
944
+ };
945
+
946
+ player.fadeVolume = function (value, duration) {
947
+ return tryResumeIfSuspended().then(function () {
948
+ ensureGainNode();
949
+ cancel();
950
+ recordFadeStart(duration);
951
+ currentValue = ensureInAllowedRange(value);
952
+ gainNode.gain.setValueAtTime(lastStartValue, audioContext.currentTime);
953
+ gainNode.gain.linearRampToValueAtTime(currentValue, audioContext.currentTime + duration / 1000);
954
+ return new Promise(function (resolve, reject) {
955
+ currentResolve = resolve;
956
+ currentTimeout = setTimeout(resolveCurrent, duration);
957
+ });
958
+ }, function () {
959
+ currentValue = ensureInAllowedRange(value);
960
+ return Promise.resolve();
961
+ });
962
+ };
963
+
964
+ player.one('dispose', cancel);
965
+
966
+ function ensureGainNode() {
967
+ if (!gainNode) {
968
+ gainNode = audioContext.createGain();
969
+ var source = audioContext.createMediaElementSource(player.getMediaElement());
970
+ source.connect(gainNode);
971
+ gainNode.connect(audioContext.destination);
972
+ }
973
+ }
974
+
975
+ function resolveCurrent() {
976
+ clearTimeout(currentTimeout);
977
+ currentResolve('done');
978
+ currentTimeout = null;
979
+ currentResolve = null;
980
+ }
981
+
982
+ function cancel() {
983
+ if (currentResolve) {
984
+ gainNode.gain.cancelScheduledValues(audioContext.currentTime);
985
+ clearTimeout(currentTimeout);
986
+ currentResolve('cancelled');
987
+ currentTimeout = null;
988
+ currentResolve = null;
989
+ updateCurrentValueFromComputedValue();
990
+ }
991
+ }
992
+
993
+ function recordFadeStart(duration) {
994
+ lastStartTime = audioContext.currentTime;
995
+ lastStartValue = currentValue;
996
+ lastDuration = duration;
997
+ }
998
+
999
+ function updateCurrentValueFromComputedValue() {
1000
+ // Firefox 54 on Ubuntu does not provide computed values when gain
1001
+ // was changed via one of the scheduling methods. Instead
1002
+ // gain.value always reports 1. Interpolate manually do determine
1003
+ // how far the fade was performed before cancel was called.
1004
+ if (gainNode.gain.value == 1) {
1005
+ var performedDuration = (audioContext.currentTime - lastStartTime) * 1000;
1006
+ var lastDelta = currentValue - lastStartValue;
1007
+ var performedFraction = lastDelta > 0 ? performedDuration / lastDuration : 1;
1008
+ currentValue = ensureInAllowedRange(lastStartValue + performedFraction * lastDelta);
1009
+ } else {
1010
+ currentValue = gainNode.gain.value;
1011
+ }
1012
+ }
1013
+
1014
+ function ensureInAllowedRange(value) {
1015
+ return value < allowedMinValue ? allowedMinValue : value;
1016
+ }
1017
+ };
1018
+
1019
+ var noop = function noop(player) {
1020
+ player.fadeVolume = function (value, duration) {
1021
+ return Promise.resolve();
1022
+ };
1023
+ };
1024
+
1025
+ var interval = function interval(player) {
1026
+ var originalVolume = player.volume;
1027
+ var fadeVolumeResolve;
1028
+ var fadeVolumeInterval;
1029
+
1030
+ player.volume = function (value) {
1031
+ if (typeof value !== 'undefined') {
1032
+ cancelFadeVolume();
1033
+ }
1034
+
1035
+ return originalVolume.apply(player, arguments);
1036
+ };
1037
+
1038
+ player.fadeVolume = function (value, duration) {
1039
+ cancelFadeVolume();
1040
+ return new Promise(function (resolve, reject) {
1041
+ var resolution = 10;
1042
+ var startValue = volume();
1043
+ var steps = duration / resolution;
1044
+ var leap = (value - startValue) / steps;
1045
+
1046
+ if (value === startValue) {
1047
+ resolve();
1048
+ } else {
1049
+ fadeVolumeResolve = resolve;
1050
+ fadeVolumeInterval = setInterval(function () {
1051
+ volume(volume() + leap);
1052
+
1053
+ if (volume() >= value && value >= startValue || volume() <= value && value <= startValue) {
1054
+ resolveFadeVolume();
1055
+ }
1056
+ }, resolution);
1057
+ }
1058
+ });
1059
+ };
1060
+
1061
+ player.one('dispose', cancelFadeVolume);
1062
+
1063
+ function volume()
1064
+ /* arguments */
1065
+ {
1066
+ return originalVolume.apply(player, arguments);
1067
+ }
1068
+
1069
+ function resolveFadeVolume() {
1070
+ clearInterval(fadeVolumeInterval);
1071
+ fadeVolumeResolve('done');
1072
+ fadeVolumeInterval = null;
1073
+ fadeVolumeResolve = null;
1074
+ }
1075
+
1076
+ function cancelFadeVolume() {
1077
+ if (fadeVolumeResolve) {
1078
+ fadeVolumeResolve('cancelled');
1079
+ fadeVolumeResolve = null;
1080
+ }
1081
+
1082
+ if (fadeVolumeInterval) {
1083
+ clearInterval(fadeVolumeInterval);
1084
+ fadeVolumeInterval = null;
1085
+ }
1086
+ }
1087
+ };
1088
+
1089
+ var volumeFading = function volumeFading(player) {
1090
+ if (!browser.has('volume control support')) {
1091
+ return noop(player);
1092
+ } else if (browser.has('audio context volume fading support') && audioContext.get() && player.getMediaElement) {
1093
+ return webAudio(player, audioContext.get());
1094
+ } else {
1095
+ return interval(player);
1096
+ }
1097
+ };
1098
+
1099
+ volumeFading.interval = interval;
1100
+ volumeFading.noop = noop;
1101
+ volumeFading.webAudio = webAudio;
1102
+
1103
+ var loadWaiting = function loadWaiting(player) {
1104
+ var originalFadeVolume = player.fadeVolume;
1105
+
1106
+ player.fadeVolume = function ()
1107
+ /* args */
1108
+ {
1109
+ var args = arguments;
1110
+ return Promise.all([this.loadedPromise]).then(function () {
1111
+ return originalFadeVolume.apply(player, args);
1112
+ });
1113
+ };
1114
+ };
1115
+
1116
+ var Settings =
1117
+ /*#__PURE__*/
1118
+ function () {
1119
+ function Settings() {
1120
+ _classCallCheck(this, Settings);
1121
+
1122
+ this.attributes = {
1123
+ volume: 1
1124
+ };
1125
+ this.initialize();
1126
+ }
1127
+
1128
+ _createClass(Settings, [{
1129
+ key: "get",
1130
+ value: function get(attributeName) {
1131
+ return this.attributes[attributeName];
1132
+ }
1133
+ }, {
1134
+ key: "set",
1135
+ value: function set(key, value) {
1136
+ var attrs;
1137
+
1138
+ if (typeof key === 'object') {
1139
+ attrs = key;
1140
+ } else {
1141
+ (attrs = {})[key] = value;
1142
+ }
1143
+
1144
+ for (var attr in attrs) {
1145
+ this.attributes[attr] = attrs[attr];
1146
+ this.trigger('change:' + attr);
1147
+ }
1148
+
1149
+ this.trigger('change');
1150
+ }
1151
+ }, {
1152
+ key: "toJSON",
1153
+ value: function toJSON() {
1154
+ return _objectSpread2({}, this.attributes);
1155
+ }
1156
+ }, {
1157
+ key: "initialize",
1158
+ value: function initialize() {
1159
+ var storage = this.getLocalStorage();
1160
+
1161
+ if (storage) {
1162
+ if (storage['pageflow.settings']) {
1163
+ try {
1164
+ this.set(JSON.parse(storage['pageflow.settings']));
1165
+ } catch (e) {
1166
+ log(e);
1167
+ }
1168
+ }
1169
+
1170
+ this.on('change', function () {
1171
+ storage['pageflow.settings'] = JSON.stringify(this.attributes);
1172
+ });
1173
+ }
1174
+ }
1175
+ }, {
1176
+ key: "getLocalStorage",
1177
+ value: function getLocalStorage() {
1178
+ try {
1179
+ return window.localStorage;
1180
+ } catch (e) {
1181
+ // Safari throws SecurityError when accessing window.localStorage
1182
+ // if cookies/website data are disabled.
1183
+ return null;
1184
+ }
1185
+ }
1186
+ }]);
1187
+
1188
+ return Settings;
1189
+ }();
1190
+
1191
+ Object.assign(Settings.prototype, BackboneEvents);
1192
+ var settings = new Settings();
1193
+
1194
+ var mediaPlayer = {
1195
+ enhance: function enhance(player, options) {
1196
+ handleFailedPlay(player, _objectSpread2({
1197
+ hasAutoplaySupport: browser.has('autoplay support')
1198
+ }, options));
1199
+ asyncPlay(player);
1200
+
1201
+ if (options.hooks) {
1202
+ hooks(player, options.hooks);
1203
+ }
1204
+
1205
+ if (options.volumeFading) {
1206
+ volumeFading(player);
1207
+ volumeBinding(player, settings, options);
1208
+ }
1209
+
1210
+ if (options.loadWaiting) {
1211
+ loadWaiting(player);
1212
+ }
1213
+ }
1214
+ };
1215
+
1216
+ mediaPlayer.handleFailedPlay = handleFailedPlay;
1217
+ mediaPlayer.volumeBinding = volumeBinding;
1218
+ mediaPlayer.volumeFading = volumeFading;
1219
+ mediaPlayer.loadWaiting = loadWaiting;
1220
+ mediaPlayer.hooks = hooks;
1221
+ mediaPlayer.asyncPlay = asyncPlay;
1222
+
1223
+ var mediaEvents = function mediaEvents(player, context) {
1224
+ function triggerMediaEvent(name) {
1225
+ events.trigger('media:' + name, {
1226
+ fileName: player.currentSrc,
1227
+ context: context,
1228
+ currentTime: player.position,
1229
+ duration: player.duration,
1230
+ volume: player.volume(),
1231
+ bitrate: 128000
1232
+ });
1233
+ }
1234
+
1235
+ player.on('play', function () {
1236
+ triggerMediaEvent('play');
1237
+ });
1238
+ player.on('timeupdate', function () {
1239
+ triggerMediaEvent('timeupdate');
1240
+ });
1241
+ player.on('pause', function () {
1242
+ triggerMediaEvent('pause');
1243
+ });
1244
+ player.on('ended', function () {
1245
+ triggerMediaEvent('ended');
1246
+ });
1247
+ };
1248
+
1249
+ // Prevent audio play back when browser enters background on mobile
1250
+ // device. Use the face that timeupdate events continue to fire while
1251
+ // intervals no longer executed when the browser is in the background.
1252
+ var pauseInBackground = function pauseInBackground(player) {
1253
+ var interval;
1254
+ var lastInterval;
1255
+ var resolution = 100;
1256
+
1257
+ function startProbeInterval() {
1258
+ interval = setInterval(function () {
1259
+ lastInterval = new Date().getTime();
1260
+ }, resolution);
1261
+ }
1262
+
1263
+ function stopProbeInterval() {
1264
+ clearInterval(interval);
1265
+ interval = null;
1266
+ }
1267
+
1268
+ function pauseIfProbeIntervalHalted() {
1269
+ if (intervalHalted()) {
1270
+ player.pause();
1271
+ }
1272
+ }
1273
+
1274
+ function intervalHalted() {
1275
+ return interval && lastInterval < new Date().getTime() - resolution * 5;
1276
+ }
1277
+
1278
+ player.on('play', startProbeInterval);
1279
+ player.on('pause', stopProbeInterval);
1280
+ player.on('ended', stopProbeInterval);
1281
+ player.on('timeupdate', pauseIfProbeIntervalHalted);
1282
+ };
1283
+
1284
+ /**
1285
+ * Calling seek before the media tag is ready causes InvalidState
1286
+ * exeption. If this happens, we wait for the next progress event and
1287
+ * retry. We resolve a promise once seeking succeeded.
1288
+ *
1289
+ * @api private
1290
+ */
1291
+ var seekWithInvalidStateHandling = function seekWithInvalidStateHandling(player) {
1292
+ var originalSeek = player.seek;
1293
+
1294
+ player.seek = function (time) {
1295
+ return retryOnProgress(function () {
1296
+ originalSeek.call(player, time);
1297
+ });
1298
+ };
1299
+
1300
+ function retryOnProgress(fn) {
1301
+ var tries = 0;
1302
+ return new Promise(function (resolve, reject) {
1303
+ function tryOrWaitForProgress() {
1304
+ tries += 1;
1305
+
1306
+ if (tries >= 50) {
1307
+ reject();
1308
+ return;
1309
+ }
1310
+
1311
+ try {
1312
+ fn();
1313
+ resolve();
1314
+ } catch (e) {
1315
+ player.one('progress', tryOrWaitForProgress);
1316
+ }
1317
+ }
1318
+
1319
+ tryOrWaitForProgress();
1320
+ });
1321
+ }
1322
+ };
1323
+
1324
+ var rewindMethod = function rewindMethod(player) {
1325
+ /**
1326
+ * Seek to beginning of file. If already at the beginning do
1327
+ * nothing.
1328
+ *
1329
+ * @alias pageflow.AudioPlayer#rewind
1330
+ */
1331
+ player.rewind = function () {
1332
+ if (player.position > 0) {
1333
+ var result = player.seek(0);
1334
+ player.trigger('timeupdate', player.position, player.duration);
1335
+ return result;
1336
+ } else {
1337
+ return Promise.resolve();
1338
+ }
1339
+ };
1340
+ };
1341
+
1342
+ var getMediaElementMethod = function getMediaElementMethod(player) {
1343
+ player.getMediaElement = function () {
1344
+ return player.audio.audio;
1345
+ };
1346
+ };
1347
+
1348
+ /**
1349
+ * Playing audio sources
1350
+ *
1351
+ * @param {Object[]} sources
1352
+ * List of sources for audio element.
1353
+ *
1354
+ * @param {string} sources[].type
1355
+ * Mime type of the audio.
1356
+ *
1357
+ * @param {string} sources[].src
1358
+ * Url of the audio.
1359
+ *
1360
+ * @class
1361
+ */
1362
+
1363
+ var AudioPlayer = function AudioPlayer(sources, options) {
1364
+ options = options || {};
1365
+ var codecMapping = {
1366
+ vorbis: 'audio/ogg',
1367
+ mp4: 'audio/mp4',
1368
+ mp3: 'audio/mpeg'
1369
+ };
1370
+ var readyResolve;
1371
+ var readyPromise = new Promise(function (resolve) {
1372
+ readyResolve = resolve;
1373
+ });
1374
+ var loadedResolve;
1375
+ var loadedPromise = new Promise(function (resolve) {
1376
+ loadedResolve = resolve;
1377
+ });
1378
+ var audio = new Audio5js({
1379
+ reusedTag: options.tag,
1380
+ swf_path: assetUrls.audioSwf,
1381
+ throw_errors: false,
1382
+ format_time: false,
1383
+ codecs: options.codecs || ['vorbis', 'mp4', 'mp3'],
1384
+ ready: readyResolve,
1385
+ loop: options.loop
1386
+ });
1387
+ audio.readyPromise = readyPromise;
1388
+ audio.loadedPromise = loadedPromise;
1389
+ audio.on('load', loadedResolve);
1390
+
1391
+ if (options.mediaEvents) {
1392
+ mediaEvents(audio, options.context);
1393
+ }
1394
+
1395
+ if (options.pauseInBackground && browser.has('mobile platform')) {
1396
+ pauseInBackground(audio);
1397
+ }
1398
+
1399
+ mediaPlayer.enhance(audio, _objectSpread2({
1400
+ loadWaiting: true
1401
+ }, options));
1402
+ seekWithInvalidStateHandling(audio);
1403
+ rewindMethod(audio);
1404
+ getMediaElementMethod(audio);
1405
+
1406
+ audio.src = function (sources) {
1407
+ readyPromise.then(function () {
1408
+ var source = (sources || []).find(function (source) {
1409
+ return codecMapping[audio.settings.player.codec] === source.type;
1410
+ });
1411
+ audio.load(source ? source.src : '');
1412
+ });
1413
+ };
1414
+
1415
+ var originalLoad = audio.load;
1416
+
1417
+ audio.load = function (src) {
1418
+ if (!src) {
1419
+ this.duration = 0;
1420
+ }
1421
+
1422
+ this.currentSrc = src;
1423
+ this.position = 0;
1424
+ this.trigger('timeupdate', this.position, this.duration);
1425
+ originalLoad.apply(this, arguments);
1426
+ };
1427
+
1428
+ var originalSeek = audio.seek;
1429
+
1430
+ audio.seek = function () {
1431
+ if (this.currentSrc) {
1432
+ return originalSeek.apply(this, arguments);
1433
+ }
1434
+ };
1435
+
1436
+ var originalPlay = audio.play;
1437
+
1438
+ audio.play = function () {
1439
+ if (this.currentSrc) {
1440
+ originalPlay.apply(this, arguments);
1441
+ }
1442
+ };
1443
+
1444
+ audio.paused = function () {
1445
+ return !audio.playing;
1446
+ };
1447
+
1448
+ audio.src(sources);
1449
+ return audio;
1450
+ };
1451
+
1452
+ AudioPlayer.fromAudioTag = function (element, options) {
1453
+ return new AudioPlayer(element.find('source').map(function () {
1454
+ return {
1455
+ src: this.getAttribute('src'),
1456
+ type: this.getAttribute('type')
1457
+ };
1458
+ }).get(), _objectSpread2({
1459
+ tag: element[0]
1460
+ }, options));
1461
+ };
1462
+
1463
+ AudioPlayer.fromScriptTag = function (element, options) {
1464
+ var sources = element.length ? JSON.parse(element.text()) : [];
1465
+ return new AudioPlayer(sources, options);
1466
+ };
1467
+
1468
+ var Null = function Null() {
1469
+ this.playAndFadeIn = function () {
1470
+ return Promise.resolve();
1471
+ };
1472
+
1473
+ this.fadeOutAndPause = function () {
1474
+ return Promise.resolve();
1475
+ };
1476
+
1477
+ this.changeVolumeFactor = function () {
1478
+ return Promise.resolve();
1479
+ };
1480
+
1481
+ this.play = function () {};
1482
+
1483
+ this.pause = function () {};
1484
+
1485
+ this.paused = function () {
1486
+ return true;
1487
+ };
1488
+
1489
+ this.seek = function () {
1490
+ return Promise.resolve();
1491
+ };
1492
+
1493
+ this.rewind = function () {
1494
+ return Promise.resolve();
1495
+ };
1496
+
1497
+ this.formatTime = function () {};
1498
+
1499
+ this.one = function (event, handler) {
1500
+ handler();
1501
+ };
1502
+ };
1503
+ Object.assign(Null.prototype, BackboneEvents);
1504
+
1505
+ AudioPlayer.mediaEvents = mediaEvents;
1506
+ AudioPlayer.Null = Null;
1507
+ AudioPlayer.seekWithInvalidStateHandling = seekWithInvalidStateHandling;
1508
+ AudioPlayer.rewindMethod = rewindMethod;
1509
+ AudioPlayer.pauseInBackground = pauseInBackground;
1510
+
1511
+ function _arrayLikeToArray(arr, len) {
1512
+ if (len == null || len > arr.length) len = arr.length;
1513
+
1514
+ for (var i = 0, arr2 = new Array(len); i < len; i++) {
1515
+ arr2[i] = arr[i];
1516
+ }
1517
+
1518
+ return arr2;
1519
+ }
1520
+
1521
+ function _arrayWithoutHoles(arr) {
1522
+ if (Array.isArray(arr)) return _arrayLikeToArray(arr);
1523
+ }
1524
+
1525
+ function _iterableToArray(iter) {
1526
+ if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
1527
+ }
1528
+
1529
+ function _unsupportedIterableToArray(o, minLen) {
1530
+ if (!o) return;
1531
+ if (typeof o === "string") return _arrayLikeToArray(o, minLen);
1532
+ var n = Object.prototype.toString.call(o).slice(8, -1);
1533
+ if (n === "Object" && o.constructor) n = o.constructor.name;
1534
+ if (n === "Map" || n === "Set") return Array.from(n);
1535
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
1536
+ }
1537
+
1538
+ function _nonIterableSpread() {
1539
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
1540
+ }
1541
+
1542
+ function _toConsumableArray(arr) {
1543
+ return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
1544
+ }
1545
+
1546
+ if (typeof window !== 'undefined') {
1547
+ window.VIDEOJS_NO_DYNAMIC_STYLE = true;
1548
+ }
1549
+
1550
+ var filterSources = function filterSources(playerElement) {
1551
+ if (playerElement.tagName.toLowerCase() !== 'video') {
1552
+ return playerElement;
1553
+ }
1554
+
1555
+ var changed = false;
1556
+
1557
+ if (browser.has('mp4 support only')) {
1558
+ // keep only mp4 source
1559
+ playerElement.querySelectorAll('source').forEach(function (source) {
1560
+ if (source.type !== 'video/mp4') {
1561
+ playerElement.removeChild(source);
1562
+ }
1563
+ });
1564
+ changed = true;
1565
+ } else if (browser.has('mse and native hls support')) {
1566
+ // remove dash source to ensure hls is used
1567
+ var dashSource = playerElement.querySelector('source[type="application/dash+xml"]');
1568
+
1569
+ if (dashSource) {
1570
+ playerElement.removeChild(dashSource);
1571
+ changed = true;
1572
+ }
1573
+ }
1574
+
1575
+ if (changed) {
1576
+ // the video tags initially in the dom are broken since they "saw"
1577
+ // the other sources. replace with clone
1578
+ var clone = playerElement.cloneNode(true);
1579
+ playerElement.replaceWith(clone);
1580
+ return clone;
1581
+ } else {
1582
+ return playerElement;
1583
+ }
1584
+ };
1585
+
1586
+ var useSlimPlayerControlsDuringPhonePlayback = function useSlimPlayerControlsDuringPhonePlayback(player) {
1587
+ var originalPlay = player.play;
1588
+
1589
+ player.play = function () {
1590
+ if (browser.has('phone platform') && !browser.has('native video player')) {
1591
+ state.widgets.use({
1592
+ name: 'slim_player_controls',
1593
+ insteadOf: 'classic_player_controls'
1594
+ }, function (restoreWidgets) {
1595
+ player.one('pause', restoreWidgets);
1596
+ });
1597
+ }
1598
+
1599
+ return originalPlay.apply(this, arguments);
1600
+ };
1601
+ };
1602
+
1603
+ var prebuffering = function prebuffering(player) {
1604
+ var prebufferPromiseReject;
1605
+
1606
+ player.isBufferedAhead = function (delta, silent) {
1607
+ // video.js only gives us one time range starting from 0 here. We
1608
+ // still ask for the last time range to be on the safe side.
1609
+ var timeRanges = player.buffered();
1610
+ var currentBufferTime = timeRanges.end(timeRanges.length - 1);
1611
+ var desiredBufferTime = player.currentTime() + delta;
1612
+
1613
+ if (player.duration()) {
1614
+ desiredBufferTime = Math.min(desiredBufferTime, Math.floor(player.duration()));
1615
+ }
1616
+
1617
+ var result = currentBufferTime >= desiredBufferTime;
1618
+
1619
+ if (!silent) {
1620
+ log('buffered ahead ' + delta + ': ' + result + ' (' + currentBufferTime + '/' + desiredBufferTime + ')');
1621
+ }
1622
+
1623
+ return result;
1624
+ };
1625
+
1626
+ player.prebuffer = function (options) {
1627
+ options = options || {};
1628
+ var delta = options.secondsToBuffer || 10;
1629
+ var secondsToWait = options.secondsToWait || 3;
1630
+ var interval = 200;
1631
+ var maxCount = secondsToWait * 1000 / interval;
1632
+ var count = 0;
1633
+
1634
+ if (browser.has('prebuffering support')) {
1635
+ if (!player.isBufferedAhead(delta) && !player.prebufferPromise) {
1636
+ log('prebuffering video ' + player.src());
1637
+ player.prebufferPromise = new Promise(function (resolve, reject) {
1638
+ prebufferPromiseReject = reject;
1639
+ wait();
1640
+
1641
+ function wait() {
1642
+ setTimeout(function () {
1643
+ if (!player.prebufferPromise) {
1644
+ return;
1645
+ }
1646
+
1647
+ count++;
1648
+
1649
+ if (player.isBufferedAhead(delta) || count > maxCount) {
1650
+ log('finished prebuffering video ' + player.src());
1651
+ resolve();
1652
+ player.prebufferPromise = null;
1653
+ } else {
1654
+ wait();
1655
+ }
1656
+ }, interval);
1657
+ }
1658
+ });
1659
+ }
1660
+ }
1661
+
1662
+ return player.prebufferPromise ? player.prebufferPromise : Promise.resolve();
1663
+ };
1664
+
1665
+ player.abortPrebuffering = function () {
1666
+ if (player.prebufferPromise) {
1667
+ log('ABORT prebuffering');
1668
+ prebufferPromiseReject('prebuffering aborted');
1669
+ player.prebufferPromise = null;
1670
+ }
1671
+ };
1672
+
1673
+ var originalPause = player.pause;
1674
+
1675
+ player.pause = function () {
1676
+ player.abortPrebuffering();
1677
+ return originalPause.apply(this, arguments);
1678
+ };
1679
+
1680
+ player.one('dispose', function () {
1681
+ player.abortPrebuffering();
1682
+ });
1683
+ };
1684
+
1685
+ var cueSettingsMethods = function cueSettingsMethods(player) {
1686
+ /**
1687
+ * Specify the display position of text tracks. This method can also
1688
+ * be used to make VideoJS reposition the text tracks after the
1689
+ * margins of the text track display have been changed (e.g. to
1690
+ * translate text tracks when player controls are displayed).
1691
+ *
1692
+ * To force such an update, the passed string has to differ from the
1693
+ * previously passed string. You can append a dot and an arbitrary
1694
+ * string (e.g. `"auto.translated"`), to keep the current setting but
1695
+ * still force repositioning.
1696
+ *
1697
+ * On the other hand, it is possible to change the positioning but
1698
+ * have VideoJS apply the change only when the next cue is
1699
+ * displayed. This way we can prevent moving a cue that the user
1700
+ * might just be reading. Simply append the string `".lazy"`
1701
+ * (e.g. `"auto.lazy"`).
1702
+ *
1703
+ * @param {string} line
1704
+ * Either `"top"` to move text tracks to the first line or
1705
+ * `"auto"` to stick with automatic positioning, followed by a tag
1706
+ * to either force or prevent immediate update.
1707
+ */
1708
+ player.updateCueLineSettings = function (line) {
1709
+ var components = line.split('.');
1710
+ var value = components[0];
1711
+ var command = components[1];
1712
+ value = value == 'top' ? 1 : value;
1713
+ var changed = false;
1714
+ Array.from(player.textTracks()).forEach(function (textTrack) {
1715
+ if (textTrack.mode == 'showing' && textTrack.cues) {
1716
+ for (var i = 0; i < textTrack.cues.length; i++) {
1717
+ if (textTrack.cues[i].line != value) {
1718
+ textTrack.cues[i].line = value;
1719
+ changed = true;
1720
+ }
1721
+ }
1722
+ }
1723
+ }); // Setting `line` does not update display directly, but only when
1724
+ // the next cue is displayed. This is problematic, when we
1725
+ // reposition text tracks to prevent overlap with player
1726
+ // controls. Triggering the event makes VideoJS update positions.
1727
+ // Ensure display is also updated when the current showing text
1728
+ // track changed since the last call, i.e. `line` has been changed
1729
+ // for a cue even though the previous call had the same
1730
+ // parameters.
1731
+
1732
+ if ((this.prevLine !== line || changed) && command != 'lazy') {
1733
+ var tech = player.tech({
1734
+ IWillNotUseThisInPlugins: true
1735
+ });
1736
+ tech && tech.trigger('texttrackchange');
1737
+ }
1738
+
1739
+ this.prevLine = line;
1740
+ };
1741
+ };
1742
+
1743
+ var getMediaElementMethod$1 = function getMediaElementMethod(player) {
1744
+ player.getMediaElement = function () {
1745
+ var tech = player.tech({
1746
+ IWillNotUseThisInPlugins: true
1747
+ });
1748
+ return tech && tech.el();
1749
+ };
1750
+ };
1751
+
1752
+ var mediaEvents$1 = function mediaEvents(player, context) {
1753
+ player.updateMediaEventsContext = function (newContext) {
1754
+ context = newContext;
1755
+ };
1756
+
1757
+ function triggerMediaEvent(name) {
1758
+ if (context) {
1759
+ events.trigger('media:' + name, {
1760
+ fileName: player.currentSrc(),
1761
+ context: context,
1762
+ currentTime: player.currentTime(),
1763
+ duration: player.duration(),
1764
+ volume: player.volume(),
1765
+ bitrate: 3500000
1766
+ });
1767
+ }
1768
+ }
1769
+
1770
+ player.on('play', function () {
1771
+ triggerMediaEvent('play');
1772
+ });
1773
+ player.on('timeupdate', function () {
1774
+ triggerMediaEvent('timeupdate');
1775
+ });
1776
+ player.on('pause', function () {
1777
+ triggerMediaEvent('pause');
1778
+ });
1779
+ player.on('ended', function () {
1780
+ triggerMediaEvent('ended');
1781
+ });
1782
+ };
1783
+
1784
+ var bufferUnderrunWaiting = function bufferUnderrunWaiting(player) {
1785
+ var originalPause = player.pause;
1786
+
1787
+ player.pause = function () {
1788
+ cancelWaiting();
1789
+ originalPause.apply(this, arguments);
1790
+ };
1791
+
1792
+ function pauseAndPreloadOnUnderrun() {
1793
+ if (bufferUnderrun()) {
1794
+ pauseAndPreload();
1795
+ }
1796
+ }
1797
+
1798
+ function bufferUnderrun() {
1799
+ return !player.isBufferedAhead(0.1, true) && !player.waitingOnUnderrun && !ignoringUnderruns();
1800
+ }
1801
+
1802
+ function pauseAndPreload() {
1803
+ log('Buffer underrun');
1804
+ player.trigger('bufferunderrun');
1805
+ player.pause();
1806
+ player.waitingOnUnderrun = true;
1807
+ player.prebuffer({
1808
+ secondsToBuffer: 5,
1809
+ secondsToWait: 5
1810
+ }).then(function () {
1811
+ // do nothing if user aborted waiting by clicking pause
1812
+ if (player.waitingOnUnderrun) {
1813
+ player.waitingOnUnderrun = false;
1814
+ player.trigger('bufferunderruncontinue');
1815
+ player.play();
1816
+ }
1817
+ }, function () {});
1818
+ }
1819
+
1820
+ function cancelWaiting() {
1821
+ if (player.waitingOnUnderrun) {
1822
+ player.ignoreUnderrunsUntil = new Date().getTime() + 5 * 1000;
1823
+ player.waitingOnUnderrun = false;
1824
+ player.trigger('bufferunderruncontinue');
1825
+ }
1826
+ }
1827
+
1828
+ function ignoringUnderruns() {
1829
+ var r = player.ignoreUnderrunsUntil && new Date().getTime() < player.ignoreUnderrunsUntil;
1830
+
1831
+ if (r) {
1832
+ log('ignoring underrun');
1833
+ }
1834
+
1835
+ return r;
1836
+ }
1837
+
1838
+ function stopListeningForProgress() {
1839
+ player.off('progress', pauseAndPreloadOnUnderrun);
1840
+ }
1841
+
1842
+ if (browser.has('buffer underrun waiting support')) {
1843
+ player.on('play', function () {
1844
+ player.on('progress', pauseAndPreloadOnUnderrun);
1845
+ });
1846
+ player.on('pause', stopListeningForProgress);
1847
+ player.on('ended', stopListeningForProgress);
1848
+ }
1849
+ };
1850
+
1851
+ var rewindMethod$1 = function rewindMethod(player) {
1852
+ /**
1853
+ * Seek to beginning of file. If already at the beginning do
1854
+ * nothing.
1855
+ *
1856
+ * @alias pageflow.VideoPlayer#rewind
1857
+ */
1858
+ player.rewind = function () {
1859
+ if (player.currentTime() > 0) {
1860
+ player.currentTime(0);
1861
+ player.trigger('timeupdate', player.currentTime(), player.duration());
1862
+ return Promise.resolve();
1863
+ } else {
1864
+ return Promise.resolve();
1865
+ }
1866
+ };
1867
+ };
1868
+
1869
+ var VideoPlayer = function VideoPlayer(element, options) {
1870
+ options = options || {};
1871
+ element = filterSources(element);
1872
+ var player = VideoJS(element, options);
1873
+
1874
+ if (options.useSlimPlayerControlsDuringPhonePlayback) {
1875
+ useSlimPlayerControlsDuringPhonePlayback(player);
1876
+ }
1877
+
1878
+ prebuffering(player);
1879
+ cueSettingsMethods(player);
1880
+ getMediaElementMethod$1(player);
1881
+ rewindMethod$1(player);
1882
+
1883
+ if (options.mediaEvents) {
1884
+ mediaEvents$1(player, options.context);
1885
+ }
1886
+
1887
+ if (options.bufferUnderrunWaiting) {
1888
+ bufferUnderrunWaiting(player);
1889
+ }
1890
+
1891
+ mediaPlayer.enhance(player, options);
1892
+ return player;
1893
+ };
1894
+
1895
+ VideoPlayer.useSlimPlayerControlsDuringPhonePlayback = useSlimPlayerControlsDuringPhonePlayback;
1896
+ VideoPlayer.prebuffering = prebuffering;
1897
+ VideoPlayer.filterSources = filterSources;
1898
+ VideoPlayer.mediaEvents = mediaEvents$1;
1899
+ VideoPlayer.cueSettingsMethods = cueSettingsMethods;
1900
+ VideoPlayer.bufferUnderrunWaiting = bufferUnderrunWaiting;
1901
+
1902
+ var createMediaPlayer = function createMediaPlayer(options) {
1903
+ var isAudio = options.tagName == 'AUDIO';
1904
+ var player = new VideoPlayer(options.mediaElement, {
1905
+ controlBar: false,
1906
+ loadingSpinner: false,
1907
+ bigPlayButton: false,
1908
+ errorDisplay: false,
1909
+ textTrackSettings: false,
1910
+ poster: options.poster,
1911
+ loop: options.loop,
1912
+ controls: options.controls,
1913
+ html5: {
1914
+ nativeCaptions: !isAudio && browser.has('iphone platform'),
1915
+ // Only used by pageflow-scrolled
1916
+ vhs: {
1917
+ useBandwidthFromLocalStorage: true
1918
+ }
1919
+ },
1920
+ bufferUnderrunWaiting: true,
1921
+ fallbackToMutedAutoplay: !isAudio,
1922
+ volumeFading: true,
1923
+ hooks: {},
1924
+ mediaEvents: true,
1925
+ context: null
1926
+ });
1927
+ player.textTrackSettings = {
1928
+ getValues: function getValues() {
1929
+ return {};
1930
+ }
1931
+ };
1932
+
1933
+ player.playOrPlayOnLoad = function () {
1934
+ if (this.readyState() > 0) {
1935
+ player.play();
1936
+ } else {
1937
+ player.on('loadedmetadata', player.play);
1938
+ }
1939
+ };
1940
+
1941
+ player.addClass('video-js');
1942
+ player.addClass('player');
1943
+ return player;
1944
+ };
1945
+
1946
+ /**
1947
+ * Copyright 2017 The AMP HTML Authors. All Rights Reserved.
1948
+ *
1949
+ * Licensed under the Apache License, Version 2.0 (the "License");
1950
+ * you may not use this file except in compliance with the License.
1951
+ * You may obtain a copy of the License at
1952
+ *
1953
+ * http://www.apache.org/licenses/LICENSE-2.0
1954
+ *
1955
+ * Unless required by applicable law or agreed to in writing, software
1956
+ * distributed under the License is distributed on an "AS-IS" BASIS,
1957
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1958
+ * See the License for the specific language governing permissions and
1959
+ * limitations under the License.
1960
+ */
1961
+ var BLANK_AUDIO_SRC = 'data:audio/wav;base64,UklGRjIAAABXQVZFZm10IBA' + 'AAAABAAEAIlYAAESsAAACABAAZGF0YRAAAAAAAAAAAAAAAAAAAAAAAA==';
1962
+ var BLANK_VIDEO_SRC = 'data:video/mp4;base64,AAAAHGZ0eXBNNFYgAAACAG' + 'lzb21pc28yYXZjMQAAAAhmcmVlAAAGF21kYXTeBAAAbGliZmFhYyAxLjI4AABCAJMgBDIARw' + 'AAArEGBf//rdxF6b3m2Ui3lizYINkj7u94MjY0IC0gY29yZSAxNDIgcjIgOTU2YzhkOCAtIE' + 'guMjY0L01QRUctNCBBVkMgY29kZWMgLSBDb3B5bGVmdCAyMDAzLTIwMTQgLSBodHRwOi8vd3' + 'd3LnZpZGVvbGFuLm9yZy94MjY0Lmh0bWwgLSBvcHRpb25zOiBjYWJhYz0wIHJlZj0zIGRlYm' + 'xvY2s9MTowOjAgYW5hbHlzZT0weDE6MHgxMTEgbWU9aGV4IHN1Ym1lPTcgcHN5PTEgcHN5X3' + 'JkPTEuMDA6MC4wMCBtaXhlZF9yZWY9MSBtZV9yYW5nZT0xNiBjaHJvbWFfbWU9MSB0cmVsbG' + 'lzPTEgOHg4ZGN0PTAgY3FtPTAgZGVhZHpvbmU9MjEsMTEgZmFzdF9wc2tpcD0xIGNocm9tYV' + '9xcF9vZmZzZXQ9LTIgdGhyZWFkcz02IGxvb2thaGVhZF90aHJlYWRzPTEgc2xpY2VkX3Rocm' + 'VhZHM9MCBucj0wIGRlY2ltYXRlPTEgaW50ZXJsYWNlZD0wIGJsdXJheV9jb21wYXQ9MCBjb2' + '5zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MCB3ZWlnaHRwPTAga2V5aW50PTI1MCBrZXlpbn' + 'RfbWluPTI1IHNjZW5lY3V0PTQwIGludHJhX3JlZnJlc2g9MCByY19sb29rYWhlYWQ9NDAgcm' + 'M9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAuNjAgcXBtaW49MCBxcG1heD02OSBxcH' + 'N0ZXA9NCB2YnZfbWF4cmF0ZT03NjggdmJ2X2J1ZnNpemU9MzAwMCBjcmZfbWF4PTAuMCBuYW' + 'xfaHJkPW5vbmUgZmlsbGVyPTAgaXBfcmF0aW89MS40MCBhcT0xOjEuMDAAgAAAAFZliIQL8m' + 'KAAKvMnJycnJycnJycnXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' + 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXiEASZACGQAjgCEASZACGQAjgAAAAAdBmjgX4G' + 'SAIQBJkAIZACOAAAAAB0GaVAX4GSAhAEmQAhkAI4AhAEmQAhkAI4AAAAAGQZpgL8DJIQBJkA' + 'IZACOAIQBJkAIZACOAAAAABkGagC/AySEASZACGQAjgAAAAAZBmqAvwMkhAEmQAhkAI4AhAE' + 'mQAhkAI4AAAAAGQZrAL8DJIQBJkAIZACOAAAAABkGa4C/AySEASZACGQAjgCEASZACGQAjgA' + 'AAAAZBmwAvwMkhAEmQAhkAI4AAAAAGQZsgL8DJIQBJkAIZACOAIQBJkAIZACOAAAAABkGbQC' + '/AySEASZACGQAjgCEASZACGQAjgAAAAAZBm2AvwMkhAEmQAhkAI4AAAAAGQZuAL8DJIQBJkA' + 'IZACOAIQBJkAIZACOAAAAABkGboC/AySEASZACGQAjgAAAAAZBm8AvwMkhAEmQAhkAI4AhAE' + 'mQAhkAI4AAAAAGQZvgL8DJIQBJkAIZACOAAAAABkGaAC/AySEASZACGQAjgCEASZACGQAjgA' + 'AAAAZBmiAvwMkhAEmQAhkAI4AhAEmQAhkAI4AAAAAGQZpAL8DJIQBJkAIZACOAAAAABkGaYC' + '/AySEASZACGQAjgCEASZACGQAjgAAAAAZBmoAvwMkhAEmQAhkAI4AAAAAGQZqgL8DJIQBJkA' + 'IZACOAIQBJkAIZACOAAAAABkGawC/AySEASZACGQAjgAAAAAZBmuAvwMkhAEmQAhkAI4AhAE' + 'mQAhkAI4AAAAAGQZsAL8DJIQBJkAIZACOAAAAABkGbIC/AySEASZACGQAjgCEASZACGQAjgA' + 'AAAAZBm0AvwMkhAEmQAhkAI4AhAEmQAhkAI4AAAAAGQZtgL8DJIQBJkAIZACOAAAAABkGbgC' + 'vAySEASZACGQAjgCEASZACGQAjgAAAAAZBm6AnwMkhAEmQAhkAI4AhAEmQAhkAI4AhAEmQAh' + 'kAI4AhAEmQAhkAI4AAAAhubW9vdgAAAGxtdmhkAAAAAAAAAAAAAAAAAAAD6AAABDcAAQAAAQ' + 'AAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAA' + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAzB0cmFrAAAAXHRraGQAAAADAAAAAAAAAAAAAAABAA' + 'AAAAAAA+kAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAA' + 'BAAAAAALAAAACQAAAAAAAkZWR0cwAAABxlbHN0AAAAAAAAAAEAAAPpAAAAAAABAAAAAAKobW' + 'RpYQAAACBtZGhkAAAAAAAAAAAAAAAAAAB1MAAAdU5VxAAAAAAALWhkbHIAAAAAAAAAAHZpZG' + 'UAAAAAAAAAAAAAAABWaWRlb0hhbmRsZXIAAAACU21pbmYAAAAUdm1oZAAAAAEAAAAAAAAAAA' + 'AAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAhNzdGJsAAAAr3N0c2QAAA' + 'AAAAAAAQAAAJ9hdmMxAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAALAAkABIAAAASAAAAAAAAA' + 'ABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGP//AAAALWF2Y0MBQsAN/+EAFW' + 'dCwA3ZAsTsBEAAAPpAADqYA8UKkgEABWjLg8sgAAAAHHV1aWRraEDyXyRPxbo5pRvPAyPzAA' + 'AAAAAAABhzdHRzAAAAAAAAAAEAAAAeAAAD6QAAABRzdHNzAAAAAAAAAAEAAAABAAAAHHN0c2' + 'MAAAAAAAAAAQAAAAEAAAABAAAAAQAAAIxzdHN6AAAAAAAAAAAAAAAeAAADDwAAAAsAAAALAA' + 'AACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAA' + 'oAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAA' + 'AAiHN0Y28AAAAAAAAAHgAAAEYAAANnAAADewAAA5gAAAO0AAADxwAAA+MAAAP2AAAEEgAABC' + 'UAAARBAAAEXQAABHAAAASMAAAEnwAABLsAAATOAAAE6gAABQYAAAUZAAAFNQAABUgAAAVkAA' + 'AFdwAABZMAAAWmAAAFwgAABd4AAAXxAAAGDQAABGh0cmFrAAAAXHRraGQAAAADAAAAAAAAAA' + 'AAAAACAAAAAAAABDcAAAAAAAAAAAAAAAEBAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAA' + 'AAAAAAAABAAAAAAAAAAAAAAAAAAAAkZWR0cwAAABxlbHN0AAAAAAAAAAEAAAQkAAADcAABAA' + 'AAAAPgbWRpYQAAACBtZGhkAAAAAAAAAAAAAAAAAAC7gAAAykBVxAAAAAAALWhkbHIAAAAAAA' + 'AAAHNvdW4AAAAAAAAAAAAAAABTb3VuZEhhbmRsZXIAAAADi21pbmYAAAAQc21oZAAAAAAAAA' + 'AAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAADT3N0YmwAAABnc3RzZA' + 'AAAAAAAAABAAAAV21wNGEAAAAAAAAAAQAAAAAAAAAAAAIAEAAAAAC7gAAAAAAAM2VzZHMAAA' + 'AAA4CAgCIAAgAEgICAFEAVBbjYAAu4AAAADcoFgICAAhGQBoCAgAECAAAAIHN0dHMAAAAAAA' + 'AAAgAAADIAAAQAAAAAAQAAAkAAAAFUc3RzYwAAAAAAAAAbAAAAAQAAAAEAAAABAAAAAgAAAA' + 'IAAAABAAAAAwAAAAEAAAABAAAABAAAAAIAAAABAAAABgAAAAEAAAABAAAABwAAAAIAAAABAA' + 'AACAAAAAEAAAABAAAACQAAAAIAAAABAAAACgAAAAEAAAABAAAACwAAAAIAAAABAAAADQAAAA' + 'EAAAABAAAADgAAAAIAAAABAAAADwAAAAEAAAABAAAAEAAAAAIAAAABAAAAEQAAAAEAAAABAA' + 'AAEgAAAAIAAAABAAAAFAAAAAEAAAABAAAAFQAAAAIAAAABAAAAFgAAAAEAAAABAAAAFwAAAA' + 'IAAAABAAAAGAAAAAEAAAABAAAAGQAAAAIAAAABAAAAGgAAAAEAAAABAAAAGwAAAAIAAAABAA' + 'AAHQAAAAEAAAABAAAAHgAAAAIAAAABAAAAHwAAAAQAAAABAAAA4HN0c3oAAAAAAAAAAAAAAD' + 'MAAAAaAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAA' + 'AACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAA' + 'kAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAA' + 'AACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAACMc3RjbwAAAA' + 'AAAAAfAAAALAAAA1UAAANyAAADhgAAA6IAAAO+AAAD0QAAA+0AAAQAAAAEHAAABC8AAARLAA' + 'AEZwAABHoAAASWAAAEqQAABMUAAATYAAAE9AAABRAAAAUjAAAFPwAABVIAAAVuAAAFgQAABZ' + '0AAAWwAAAFzAAABegAAAX7AAAGFwAAAGJ1ZHRhAAAAWm1ldGEAAAAAAAAAIWhkbHIAAAAAAA' + 'AAAG1kaXJhcHBsAAAAAAAAAAAAAAAALWlsc3QAAAAlqXRvbwAAAB1kYXRhAAAAAQAAAABMYX' + 'ZmNTUuMzMuMTAw';
1963
+ var blankSources = {
1964
+ audio: {
1965
+ src: BLANK_AUDIO_SRC,
1966
+ type: 'audio/wav'
1967
+ },
1968
+ video: {
1969
+ src: BLANK_VIDEO_SRC,
1970
+ type: 'video/mp4'
1971
+ }
1972
+ };
1973
+
1974
+ /** @const @enum {string} */
1975
+
1976
+ var MediaType = {
1977
+ AUDIO: 'audio',
1978
+ VIDEO: 'video'
1979
+ };
1980
+ var elId = 0;
1981
+ /**
1982
+ * Media pool class handles the pool of Videojs media players
1983
+ */
1984
+
1985
+ var MediaPool =
1986
+ /*#__PURE__*/
1987
+ function () {
1988
+ function MediaPool() {
1989
+ var _this$mediaFactory_;
1990
+
1991
+ var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
1992
+ playerCount: 4
1993
+ };
1994
+
1995
+ _classCallCheck(this, MediaPool);
1996
+
1997
+ this.playerCount = options.playerCount;
1998
+ this.allocatedPlayers = {};
1999
+ this.unAllocatedPlayers = {};
2000
+ this.mediaFactory_ = (_this$mediaFactory_ = {}, _defineProperty(_this$mediaFactory_, MediaType.AUDIO, function () {
2001
+ var audioEl = document.createElement('audio');
2002
+ audioEl.setAttribute('crossorigin', 'anonymous');
2003
+ return audioEl;
2004
+ }), _defineProperty(_this$mediaFactory_, MediaType.VIDEO, function () {
2005
+ var videoEl = document.createElement('video');
2006
+ videoEl.setAttribute('crossorigin', 'anonymous');
2007
+ return videoEl;
2008
+ }), _this$mediaFactory_);
2009
+ }
2010
+
2011
+ _createClass(MediaPool, [{
2012
+ key: "allocatePlayer",
2013
+ value: function allocatePlayer(_ref) {
2014
+ var playerType = _ref.playerType,
2015
+ playerId = _ref.playerId,
2016
+ playsInline = _ref.playsInline,
2017
+ mediaEventsContextData = _ref.mediaEventsContextData,
2018
+ hooks = _ref.hooks,
2019
+ poster = _ref.poster,
2020
+ _ref$loop = _ref.loop,
2021
+ loop = _ref$loop === void 0 ? false : _ref$loop,
2022
+ _ref$controls = _ref.controls,
2023
+ controls = _ref$controls === void 0 ? false : _ref$controls,
2024
+ altText = _ref.altText,
2025
+ onRelease = _ref.onRelease;
2026
+ var player = undefined;
2027
+
2028
+ if (!this.unAllocatedPlayers[playerType]) {
2029
+ this.populateMediaPool_();
2030
+ }
2031
+
2032
+ if (this.unAllocatedPlayers[playerType].length == 0) {
2033
+ this.freeOnePlayer(playerType);
2034
+ }
2035
+
2036
+ player = this.unAllocatedPlayers[playerType].pop();
2037
+
2038
+ if (player) {
2039
+ player.pause();
2040
+ player.getMediaElement().loop = loop;
2041
+ player.getMediaElement().setAttribute('alt', altText);
2042
+ player.poster(poster);
2043
+ player.controls(controls);
2044
+
2045
+ if (playsInline) {
2046
+ player.playsinline(true);
2047
+ }
2048
+
2049
+ player.updateHooks(hooks || {});
2050
+ player.updateMediaEventsContext(mediaEventsContextData);
2051
+ this.allocatedPlayers[playerType].push(player);
2052
+ player.playerId = playerId || this.allocatedPlayers[playerType].length;
2053
+ player.releaseCallback = onRelease;
2054
+ return player;
2055
+ } else {
2056
+ console.log('no player found for allocation');
2057
+ }
2058
+ }
2059
+ }, {
2060
+ key: "freeOnePlayer",
2061
+ value: function freeOnePlayer(type) {
2062
+ this.unAllocatePlayer(this.allocatedPlayers[type][0]); // free up the first allocated player
2063
+ }
2064
+ }, {
2065
+ key: "unAllocatePlayer",
2066
+ value: function unAllocatePlayer(player) {
2067
+ if (player) {
2068
+ var type = this.getMediaTypeFromEl(player.el());
2069
+ this.allocatedPlayers[type] = this.allocatedPlayers[type].filter(function (p) {
2070
+ return p != player;
2071
+ });
2072
+ player.controls(false);
2073
+ player.getMediaElement().loop = false;
2074
+ player.playsinline(false);
2075
+ player.src(blankSources[type]);
2076
+ player.poster('');
2077
+ clearTextTracks(player);
2078
+ this.unAllocatedPlayers[type].push(player);
2079
+
2080
+ if (player.releaseCallback) {
2081
+ player.releaseCallback();
2082
+ player.releaseCallback = null;
2083
+ }
2084
+ }
2085
+ }
2086
+ }, {
2087
+ key: "blessAll",
2088
+ value: function blessAll(value) {
2089
+ var _this = this;
2090
+
2091
+ if (this.unAllocatedPlayers[MediaType.AUDIO] == undefined || this.unAllocatedPlayers[MediaType.VIDEO] == undefined) {
2092
+ this.populateMediaPool_();
2093
+ }
2094
+
2095
+ this.forEachMediaType(function (key) {
2096
+ _this.allPlayersForType(MediaType[key]).forEach(function (player) {
2097
+ player.muted(value);
2098
+ });
2099
+ });
2100
+ }
2101
+ }, {
2102
+ key: "allPlayersForType",
2103
+ value: function allPlayersForType(type) {
2104
+ if (this.unAllocatedPlayers[type]) {
2105
+ return [].concat(_toConsumableArray(this.unAllocatedPlayers[type]), _toConsumableArray(this.allocatedPlayers[type]));
2106
+ }
2107
+
2108
+ return [];
2109
+ }
2110
+ }, {
2111
+ key: "getMediaTypeFromEl",
2112
+ value: function getMediaTypeFromEl(mediaElement) {
2113
+ var tagName = mediaElement.tagName.toLowerCase();
2114
+
2115
+ if (tagName == 'div') {
2116
+ tagName = mediaElement.children[0].tagName.toLowerCase();
2117
+ }
2118
+
2119
+ return this.getMediaType(tagName);
2120
+ }
2121
+ }, {
2122
+ key: "getMediaType",
2123
+ value: function getMediaType(tagName) {
2124
+ switch (tagName) {
2125
+ case 'audio':
2126
+ return MediaType.AUDIO;
2127
+
2128
+ case 'video':
2129
+ return MediaType.VIDEO;
2130
+ }
2131
+ }
2132
+ }, {
2133
+ key: "forEachMediaType",
2134
+ value: function forEachMediaType(callbackFn) {
2135
+ Object.keys(MediaType).forEach(callbackFn.bind(this));
2136
+ }
2137
+ }, {
2138
+ key: "createPlayer_",
2139
+ value: function createPlayer_(type, mediaEl) {
2140
+ mediaEl.setAttribute('pool-element', elId++);
2141
+
2142
+ if (!this.unAllocatedPlayers[type]) {
2143
+ this.unAllocatedPlayers[type] = [];
2144
+ this.allocatedPlayers[type] = [];
2145
+ }
2146
+
2147
+ var player = createMediaPlayer({
2148
+ mediaElement: mediaEl,
2149
+ tagName: type
2150
+ });
2151
+ mediaEl.setAttribute('src', blankSources[type].src);
2152
+ this.unAllocatedPlayers[type].push(player);
2153
+ return player;
2154
+ }
2155
+ }, {
2156
+ key: "initializeMediaPool_",
2157
+ value: function initializeMediaPool_(type, mediaElSeed) {
2158
+ while (this.allPlayersForType(type).length < this.playerCount) {
2159
+ this.createPlayer_(type, mediaElSeed.cloneNode(true));
2160
+ }
2161
+ }
2162
+ }, {
2163
+ key: "populateMediaPool_",
2164
+ value: function populateMediaPool_() {
2165
+ var _this2 = this;
2166
+
2167
+ this.forEachMediaType(function (key) {
2168
+ var type = MediaType[key];
2169
+
2170
+ var mediaEl = _this2.mediaFactory_[type].call(_this2);
2171
+
2172
+ _this2.initializeMediaPool_(type, mediaEl);
2173
+ });
2174
+ }
2175
+ }]);
2176
+
2177
+ return MediaPool;
2178
+ }();
2179
+
2180
+ function clearTextTracks(player) {
2181
+ var tracks = player.textTracks();
2182
+ var i = tracks.length;
2183
+
2184
+ while (i--) {
2185
+ player.removeRemoteTextTrack(tracks[i]);
2186
+ }
2187
+ }
2188
+
2189
+ var media = {
2190
+ playerPool: new MediaPool(),
2191
+ muteState: true,
2192
+
2193
+ get muted() {
2194
+ return this.muteState;
2195
+ },
2196
+
2197
+ mute: function mute(value) {
2198
+ this.muteState = value;
2199
+ this.playerPool.blessAll(value);
2200
+ this.trigger('change:muted', value);
2201
+ },
2202
+ getPlayer: function getPlayer(fileSource, options) {
2203
+ options.playerType = options.tagName || MediaType.VIDEO;
2204
+ var player = this.playerPool.allocatePlayer(options);
2205
+
2206
+ if (player) {
2207
+ player.muted(this.muteState);
2208
+ player.src(fileSource);
2209
+
2210
+ if (options.textTrackSources) {
2211
+ options.textTrackSources.forEach(function (track) {
2212
+ return player.addRemoteTextTrack(track, true);
2213
+ });
2214
+ }
2215
+
2216
+ return player;
2217
+ }
2218
+ },
2219
+ releasePlayer: function releasePlayer(player) {
2220
+ if (player) {
2221
+ this.playerPool.unAllocatePlayer(player);
2222
+ }
2223
+ }
2224
+ };
2225
+ Object.assign(media, BackboneEvents);
2226
+
2227
+ /**
2228
+ * Play and fade between multiple audio files.
2229
+ *
2230
+ * @class
2231
+ */
2232
+
2233
+ var MultiPlayer = function MultiPlayer(pool, options) {
2234
+ if (options.crossFade && options.playFromBeginning) {
2235
+ throw 'pageflow.Audio.MultiPlayer: The options crossFade and playFromBeginning can not be used together at the moment.';
2236
+ }
2237
+
2238
+ var current = new AudioPlayer.Null();
2239
+ var currentId = null;
2240
+ var that = this;
2241
+ /**
2242
+ * Continue playback.
2243
+ */
2244
+
2245
+ this.resume = function () {
2246
+ return current.play();
2247
+ };
2248
+ /**
2249
+ * Continue playback with fade in.
2250
+ */
2251
+
2252
+
2253
+ this.resumeAndFadeIn = function () {
2254
+ return current.playAndFadeIn(options.fadeDuration);
2255
+ };
2256
+
2257
+ this.seek = function (position) {
2258
+ return current.seek(position);
2259
+ };
2260
+
2261
+ this.pause = function () {
2262
+ return current.pause();
2263
+ };
2264
+
2265
+ this.paused = function () {
2266
+ return current.paused();
2267
+ };
2268
+
2269
+ this.fadeOutAndPause = function () {
2270
+ return current.fadeOutAndPause(options.fadeDuration);
2271
+ };
2272
+
2273
+ this.fadeOutIfPlaying = function () {
2274
+ if (current.paused()) {
2275
+ return Promise.resolve();
2276
+ } else {
2277
+ return current.fadeOutAndPause(options.fadeDuration);
2278
+ }
2279
+ };
2280
+
2281
+ this.position = function () {
2282
+ return current.position;
2283
+ };
2284
+
2285
+ this.duration = function () {
2286
+ return current.duration;
2287
+ };
2288
+
2289
+ this.fadeTo = function (id) {
2290
+ return changeCurrent(id, function (player) {
2291
+ return player.playAndFadeIn(options.fadeDuration);
2292
+ });
2293
+ };
2294
+
2295
+ this.play = function (id) {
2296
+ return changeCurrent(id, function (player) {
2297
+ return player.play();
2298
+ });
2299
+ };
2300
+
2301
+ this.changeVolumeFactor = function (factor) {
2302
+ return current.changeVolumeFactor(factor, options.fadeDuration);
2303
+ };
2304
+
2305
+ this.formatTime = function (time) {
2306
+ return current.formatTime(time);
2307
+ };
2308
+
2309
+ function changeCurrent(id, callback) {
2310
+ if (!options.playFromBeginning && id === currentId && !current.paused()) {
2311
+ return Promise.resolve();
2312
+ }
2313
+
2314
+ var player = pool.get(id);
2315
+ currentId = id;
2316
+ var fadeOutPromise = current.fadeOutAndPause(options.fadeDuration);
2317
+
2318
+ if (current._stopMultiPlayerEventPropagation && current.paused()) {
2319
+ current._stopMultiPlayerEventPropagation();
2320
+ }
2321
+
2322
+ return handleCrossFade(fadeOutPromise).then(function () {
2323
+ current = player;
2324
+ startEventPropagation(current, id);
2325
+ return handlePlayFromBeginning(player).then(function () {
2326
+ return callback(player);
2327
+ });
2328
+ });
2329
+ }
2330
+
2331
+ function handleCrossFade(fadePomise) {
2332
+ if (options.crossFade) {
2333
+ return Promise.resolve();
2334
+ } else {
2335
+ return fadePomise;
2336
+ }
2337
+ }
2338
+
2339
+ function handlePlayFromBeginning(player) {
2340
+ if (options.playFromBeginning || options.rewindOnChange) {
2341
+ return player.rewind();
2342
+ } else {
2343
+ return Promise.resolve();
2344
+ }
2345
+ }
2346
+
2347
+ function startEventPropagation(player, id) {
2348
+ var playCallback = function playCallback() {
2349
+ that.trigger('play', {
2350
+ audioFileId: id
2351
+ });
2352
+ };
2353
+
2354
+ var pauseCallback = function pauseCallback() {
2355
+ that.trigger('pause', {
2356
+ audioFileId: id
2357
+ });
2358
+
2359
+ if (currentId !== id) {
2360
+ player._stopMultiPlayerEventPropagation();
2361
+ }
2362
+ };
2363
+
2364
+ var timeUpdateCallback = function timeUpdateCallback() {
2365
+ that.trigger('timeupdate', {
2366
+ audioFileId: id
2367
+ });
2368
+ };
2369
+
2370
+ var endedCallback = function endedCallback() {
2371
+ that.trigger('ended', {
2372
+ audioFileId: id
2373
+ });
2374
+ };
2375
+
2376
+ var playFailedCallback = function playFailedCallback() {
2377
+ that.trigger('playfailed', {
2378
+ audioFileId: id
2379
+ });
2380
+ };
2381
+
2382
+ player.on('play', playCallback);
2383
+ player.on('pause', pauseCallback);
2384
+ player.on('timeupdate', timeUpdateCallback);
2385
+ player.on('ended', endedCallback);
2386
+ player.on('playfailed', playFailedCallback);
2387
+
2388
+ player._stopMultiPlayerEventPropagation = function () {
2389
+ player.off('play', playCallback);
2390
+ player.off('pause', pauseCallback);
2391
+ player.off('timeupdate', timeUpdateCallback);
2392
+ player.off('ended', endedCallback);
2393
+ player.off('playfailed', playFailedCallback);
2394
+ };
2395
+ }
2396
+ };
2397
+ Object.assign(MultiPlayer.prototype, BackboneEvents);
2398
+
2399
+ var PlayerSourceIDMap = function PlayerSourceIDMap(media) {
2400
+ var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
2401
+ playerOptions = _ref.playerOptions;
2402
+
2403
+ return {
2404
+ current: undefined,
2405
+ previous: undefined,
2406
+ mapSources: function mapSources(id, sources) {
2407
+ this[id] = sources;
2408
+ },
2409
+ get: function get(sourceID) {
2410
+ if (!this[sourceID]) {
2411
+ return new AudioPlayer.Null();
2412
+ }
2413
+
2414
+ if (this.current && this.current.playerId === sourceID) {
2415
+ return this.current;
2416
+ }
2417
+
2418
+ if (this.previous && this.previous.playerId === sourceID) {
2419
+ var holder = this.current;
2420
+ this.current = this.previous;
2421
+ this.previous = holder;
2422
+ } else {
2423
+ if (this.previous) {
2424
+ media.releasePlayer(this.previous);
2425
+ }
2426
+
2427
+ this.previous = this.current;
2428
+ this.current = media.getPlayer(this[sourceID], _objectSpread2({
2429
+ filePermaId: sourceID,
2430
+ playerId: sourceID
2431
+ }, playerOptions));
2432
+ }
2433
+
2434
+ return this.current;
2435
+ }
2436
+ };
2437
+ };
2438
+
2439
+ var PlayerPool = function PlayerPool(audio, options) {
2440
+ this.players = {};
2441
+
2442
+ this.get = function (audioFileId) {
2443
+ this.players[audioFileId] = this.players[audioFileId] || audio.createPlayer(audioFileId, options);
2444
+ return this.players[audioFileId];
2445
+ };
2446
+
2447
+ this.dispose = function () {
2448
+ this.players = {};
2449
+ };
2450
+ };
2451
+
2452
+ /**
2453
+ * Playing audio files.
2454
+ * @alias pageflow.audio
2455
+ * @member
2456
+ */
2457
+
2458
+ var Audio = function Audio(options) {
2459
+ this.getSources = options.getSources || function (audioFileId) {
2460
+ return options.audioFiles[audioFileId] || '';
2461
+ };
2462
+ /**
2463
+ * Creates a player for the given audio file.
2464
+ *
2465
+ * @param {string|number} audioFileId
2466
+ * Id of the audio file to play. The id can be of the form
2467
+ * `"5.suffix"` to distinguish multiple occurences of the same
2468
+ * audio file for example inside a pageflow.Audio.PlayerPool;
2469
+ *
2470
+ * @param {Object} [options]
2471
+ * Options to pass on player creation
2472
+ *
2473
+ * @static
2474
+ */
2475
+
2476
+
2477
+ this.createPlayer = function (audioFileId, options) {
2478
+ var sources = this.getSources(removeSuffix(audioFileId));
2479
+
2480
+ if (sources) {
2481
+ return new AudioPlayer(sources, _objectSpread2({
2482
+ volumeFading: true
2483
+ }, options));
2484
+ } else {
2485
+ return new AudioPlayer.Null();
2486
+ }
2487
+ };
2488
+ /**
2489
+ * Create a `MultiPlayer` to play and fade between multiple audio
2490
+ * files.
2491
+ *
2492
+ * @param {Object} [options]
2493
+ * All options supported by pageflow.AudioPlayer can be passed.
2494
+ *
2495
+ * @param {number} [options.fadeDuration]
2496
+ * Time in milliseconds to fade audios in and out.
2497
+ *
2498
+ * @param {boolean} [options.playFromBeginning=false]
2499
+ * Always restart audio files from the beginning.
2500
+ *
2501
+ * @param {boolean} [options.rewindOnChange=false]
2502
+ * Play from beginning when changing audio files.
2503
+ *
2504
+ * @return {pageflow.Audio.MultiPlayer}
2505
+ */
2506
+
2507
+
2508
+ this.createMultiPlayer = function (options) {
2509
+ return new MultiPlayer(new PlayerPool(this, options), options);
2510
+ };
2511
+
2512
+ function removeSuffix(id) {
2513
+ if (!id) {
2514
+ return id;
2515
+ }
2516
+
2517
+ return parseInt(id.toString().split('.')[0], 10);
2518
+ }
2519
+ };
2520
+
2521
+ Audio.setup = function (options) {
2522
+ state.audio = new Audio(options);
2523
+ };
2524
+
2525
+ Audio.PlayerPool = PlayerPool;
2526
+
2527
+ var isEventAdded = false;
2528
+ var callbacks = [];
2529
+
2530
+ var muteInBackground = function muteInBackground() {
2531
+ callbacks.forEach(function (cb) {
2532
+ cb(document.visibilityState);
2533
+ });
2534
+ };
2535
+
2536
+ function documentHiddenState(callback) {
2537
+ callbacks.push(callback);
2538
+
2539
+ if (!isEventAdded) {
2540
+ isEventAdded = true;
2541
+ document.addEventListener('visibilitychange', muteInBackground, false);
2542
+ }
2543
+
2544
+ return {
2545
+ removeCallback: function removeCallback() {
2546
+ callbacks = callbacks.filter(function (c) {
2547
+ return c !== callback;
2548
+ });
2549
+ }
2550
+ };
2551
+ }
2552
+
2553
+ export { Audio, AudioPlayer, Features, MediaPool, MediaType, MultiPlayer, PlayerSourceIDMap, VideoPlayer, assetUrls, audioContext, blankSources, browser, cookies, debugMode, documentHiddenState, events, features, log, media, mediaPlayer, settings };