@gcorevideo/player 2.18.3 → 2.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (349) hide show
  1. package/assets/audio-selector/style.scss +156 -0
  2. package/assets/audio-selector/track-selector.ejs +12 -0
  3. package/assets/big-mute-button/big-mute-button.ejs +3 -0
  4. package/assets/big-mute-button/big-mute-button.scss +57 -0
  5. package/assets/bottom-gear/bottomgear.ejs +12 -0
  6. package/assets/bottom-gear/gear-sub-menu.scss +95 -0
  7. package/assets/bottom-gear/gear.scss +79 -0
  8. package/assets/clappr-nerd-stats/button.ejs +4 -0
  9. package/assets/clappr-nerd-stats/clappr-nerd-stats.ejs +212 -0
  10. package/assets/clappr-nerd-stats/clappr-nerd-stats.scss +488 -0
  11. package/assets/clappr-nerd-stats/options-list.ejs +9 -0
  12. package/assets/clappr-nerd-stats/settings.ejs +12 -0
  13. package/assets/clappr-nerd-stats/speedtest/speedtest.worker.js +775 -0
  14. package/assets/clips/clips.scss +3 -0
  15. package/assets/context-menu/context_menu.ejs +8 -0
  16. package/assets/context-menu/context_menu.scss +31 -0
  17. package/assets/dvr-controls/dvr_controls.scss +136 -0
  18. package/assets/dvr-controls/index.ejs +2 -0
  19. package/assets/error-screen/error_screen.ejs +13 -0
  20. package/assets/error-screen/error_screen.scss +40 -0
  21. package/assets/icons/new/arrow-left.svg +5 -0
  22. package/assets/icons/new/arrow-right.svg +5 -0
  23. package/assets/icons/new/check.svg +5 -0
  24. package/assets/icons/new/close.svg +12 -0
  25. package/assets/icons/new/full.svg +8 -0
  26. package/assets/icons/new/fullscreen-off.svg +14 -0
  27. package/assets/icons/new/fullscreen-on.svg +14 -0
  28. package/assets/icons/new/gear-hd.svg +16 -0
  29. package/assets/icons/new/gear.svg +12 -0
  30. package/assets/icons/new/hd.svg +8 -0
  31. package/assets/icons/new/pause.svg +5 -0
  32. package/assets/icons/new/pip.svg +5 -0
  33. package/assets/icons/new/play.svg +10 -0
  34. package/assets/icons/new/replayleft.svg +5 -0
  35. package/assets/icons/new/replayright.svg +5 -0
  36. package/assets/icons/new/speed.svg +5 -0
  37. package/assets/icons/new/stats.svg +3 -0
  38. package/assets/icons/new/stop.svg +3 -0
  39. package/assets/icons/new/subtitles-off.svg +5 -0
  40. package/assets/icons/new/subtitles-on.svg +6 -0
  41. package/assets/icons/new/volume-max.svg +5 -0
  42. package/assets/icons/new/volume-min.svg +5 -0
  43. package/assets/icons/new/volume-off.svg +5 -0
  44. package/assets/icons/old/cardboard.svg +4 -0
  45. package/assets/icons/old/close-share.svg +13 -0
  46. package/assets/icons/old/close.svg +13 -0
  47. package/assets/icons/old/fb.svg +13 -0
  48. package/assets/icons/old/fullscreen.svg +12 -0
  49. package/assets/icons/old/language.svg +1 -0
  50. package/assets/icons/old/pause.svg +12 -0
  51. package/assets/icons/old/play.svg +12 -0
  52. package/assets/icons/old/quality-arrow.svg +13 -0
  53. package/assets/icons/old/reload.svg +4 -0
  54. package/assets/icons/old/share.svg +13 -0
  55. package/assets/icons/old/sound-off.svg +15 -0
  56. package/assets/icons/old/sound-on.svg +15 -0
  57. package/assets/icons/old/streams.svg +3 -0
  58. package/assets/icons/old/twitter.svg +13 -0
  59. package/assets/icons/old/wn.svg +15 -0
  60. package/assets/icons/standard/01-play.svg +3 -0
  61. package/assets/icons/standard/02-pause.svg +3 -0
  62. package/assets/icons/standard/03-stop.svg +3 -0
  63. package/assets/icons/standard/04-volume.svg +3 -0
  64. package/assets/icons/standard/05-mute.svg +3 -0
  65. package/assets/icons/standard/06-expand.svg +3 -0
  66. package/assets/icons/standard/07-shrink.svg +3 -0
  67. package/assets/icons/standard/08-hd.svg +3 -0
  68. package/assets/icons/standard/09-cc.svg +8 -0
  69. package/assets/icons/standard/10-reload.svg +4 -0
  70. package/assets/level-selector/button.ejs +8 -0
  71. package/assets/level-selector/list.ejs +22 -0
  72. package/assets/level-selector/style.scss +4 -0
  73. package/assets/logo/styles/logo.scss +10 -0
  74. package/assets/logo/templates/logo.ejs +3 -0
  75. package/assets/media-control/closed-hand.cur +0 -0
  76. package/assets/media-control/container.scss +57 -0
  77. package/assets/media-control/media-control.ejs +133 -0
  78. package/assets/media-control/media-control.scss +390 -0
  79. package/assets/media-control/plugins.scss +94 -0
  80. package/assets/media-control/width270.scss +50 -0
  81. package/assets/media-control/width370.scss +263 -0
  82. package/assets/multi-camera/multicamera.ejs +29 -0
  83. package/assets/multi-camera/style.scss +176 -0
  84. package/assets/picture-in-picture/button.ejs +3 -0
  85. package/assets/picture-in-picture/button.scss +11 -0
  86. package/assets/playback-rate/button.ejs +6 -0
  87. package/assets/playback-rate/list.ejs +14 -0
  88. package/assets/playback-rate/playback-rate-selector.ejs +9 -0
  89. package/assets/poster/poster.ejs +1 -0
  90. package/assets/poster/poster.scss +32 -0
  91. package/assets/seek-time/seek-time.html +2 -0
  92. package/assets/seek-time/seek-time.scss +38 -0
  93. package/assets/share/share.ejs +37 -0
  94. package/assets/share/style.scss +104 -0
  95. package/assets/skip-time/skip-time.ejs +8 -0
  96. package/assets/skip-time/style.scss +24 -0
  97. package/assets/spinner-three-bounce/spinner.ejs +3 -0
  98. package/assets/spinner-three-bounce/spinner.scss +44 -0
  99. package/assets/style/main.scss +50 -0
  100. package/assets/style/theme.scss +42 -0
  101. package/assets/style/variables.scss +7 -0
  102. package/assets/subtitles/combobox copy.ejs +16 -0
  103. package/assets/subtitles/combobox.ejs +16 -0
  104. package/assets/subtitles/string.ejs +3 -0
  105. package/assets/subtitles/style.scss +99 -0
  106. package/assets/thumbnails/scrub-thumbnails.ejs +10 -0
  107. package/assets/thumbnails/style.scss +75 -0
  108. package/assets/vast-ads/style.scss +112 -0
  109. package/assets/video360/button.ejs +1 -0
  110. package/assets/video360/style.scss +8 -0
  111. package/build/vite-raw-plugin.js +18 -0
  112. package/dist/index.js +1 -1
  113. package/dist/plugins/index.css +2164 -0
  114. package/dist/plugins/index.js/index.plugins.js +40837 -0
  115. package/dist/plugins/index.plugins.js +40837 -0
  116. package/lib/index.core.d.ts +15 -0
  117. package/lib/index.core.d.ts.map +1 -0
  118. package/lib/index.core.js +14 -0
  119. package/lib/index.d.ts +2 -14
  120. package/lib/index.d.ts.map +1 -1
  121. package/lib/index.js +2 -14
  122. package/lib/index.plugins.d.ts +38 -0
  123. package/lib/index.plugins.d.ts.map +1 -0
  124. package/lib/index.plugins.js +40 -0
  125. package/lib/plugins/audio-selector/AudioSelector.d.ts +3 -3
  126. package/lib/plugins/audio-selector/AudioSelector.d.ts.map +1 -1
  127. package/lib/plugins/audio-selector/AudioSelector.js +6 -12
  128. package/lib/plugins/big-mute-button/BigMuteButton.d.ts +2 -2
  129. package/lib/plugins/big-mute-button/BigMuteButton.d.ts.map +1 -1
  130. package/lib/plugins/big-mute-button/BigMuteButton.js +7 -12
  131. package/lib/plugins/bottom-gear/BottomGear.d.ts +4 -3
  132. package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
  133. package/lib/plugins/bottom-gear/BottomGear.js +11 -16
  134. package/lib/plugins/build.d.ts +2 -0
  135. package/lib/plugins/build.d.ts.map +1 -0
  136. package/lib/plugins/build.js +1 -0
  137. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts +44 -0
  138. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts.map +1 -0
  139. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.js +294 -0
  140. package/lib/plugins/clappr-nerd-stats/formatter.d.ts +8 -0
  141. package/lib/plugins/clappr-nerd-stats/formatter.d.ts.map +1 -0
  142. package/lib/plugins/clappr-nerd-stats/formatter.js +91 -0
  143. package/lib/plugins/clappr-nerd-stats/speedtest/Speedtest.d.ts +54 -0
  144. package/lib/plugins/clappr-nerd-stats/speedtest/Speedtest.d.ts.map +1 -0
  145. package/lib/plugins/clappr-nerd-stats/speedtest/Speedtest.js +335 -0
  146. package/lib/plugins/clappr-nerd-stats/speedtest/index.d.ts +9 -0
  147. package/lib/plugins/clappr-nerd-stats/speedtest/index.d.ts.map +1 -0
  148. package/lib/plugins/clappr-nerd-stats/speedtest/index.js +154 -0
  149. package/lib/plugins/clappr-nerd-stats/speedtest/types.d.ts +6 -0
  150. package/lib/plugins/clappr-nerd-stats/speedtest/types.d.ts.map +1 -0
  151. package/lib/plugins/clappr-nerd-stats/speedtest/types.js +1 -0
  152. package/lib/plugins/clappr-nerd-stats/types.d.ts +4 -0
  153. package/lib/plugins/clappr-nerd-stats/types.d.ts.map +1 -0
  154. package/lib/plugins/clappr-nerd-stats/types.js +1 -0
  155. package/lib/plugins/clappr-stats/ClapprStats.d.ts +56 -0
  156. package/lib/plugins/clappr-stats/ClapprStats.d.ts.map +1 -0
  157. package/lib/plugins/clappr-stats/ClapprStats.js +332 -0
  158. package/lib/plugins/clappr-stats/types.d.ts +50 -0
  159. package/lib/plugins/clappr-stats/types.d.ts.map +1 -0
  160. package/lib/plugins/clappr-stats/types.js +5 -0
  161. package/lib/plugins/clappr-stats/utils.d.ts +3 -0
  162. package/lib/plugins/clappr-stats/utils.d.ts.map +1 -0
  163. package/lib/plugins/clappr-stats/utils.js +40 -0
  164. package/lib/plugins/click-to-pause/ClickToPause.d.ts +2 -2
  165. package/lib/plugins/click-to-pause/ClickToPause.d.ts.map +1 -1
  166. package/lib/plugins/click-to-pause/ClickToPause.js +4 -6
  167. package/lib/plugins/clips/Clips.d.ts +23 -0
  168. package/lib/plugins/clips/Clips.d.ts.map +1 -0
  169. package/lib/plugins/clips/Clips.js +109 -0
  170. package/lib/plugins/context-menu/ContextMenu.d.ts +36 -0
  171. package/lib/plugins/context-menu/ContextMenu.d.ts.map +1 -0
  172. package/lib/plugins/context-menu/ContextMenu.js +102 -0
  173. package/lib/plugins/disable-controls/DisableControls.d.ts +1 -1
  174. package/lib/plugins/disable-controls/DisableControls.d.ts.map +1 -1
  175. package/lib/plugins/disable-controls/DisableControls.js +3 -5
  176. package/lib/plugins/dvr-controls/DVRControls.d.ts +4 -4
  177. package/lib/plugins/dvr-controls/DVRControls.d.ts.map +1 -1
  178. package/lib/plugins/dvr-controls/DVRControls.js +5 -4
  179. package/lib/plugins/error-screen/ErrorScreen.d.ts +44 -0
  180. package/lib/plugins/error-screen/ErrorScreen.d.ts.map +1 -0
  181. package/lib/plugins/error-screen/ErrorScreen.js +179 -0
  182. package/lib/plugins/favicon/Favicon.d.ts +24 -0
  183. package/lib/plugins/favicon/Favicon.d.ts.map +1 -0
  184. package/lib/plugins/favicon/Favicon.js +106 -0
  185. package/lib/plugins/google-analytics/GoogleAnalytics.d.ts +30 -0
  186. package/lib/plugins/google-analytics/GoogleAnalytics.d.ts.map +1 -0
  187. package/lib/plugins/google-analytics/GoogleAnalytics.js +114 -0
  188. package/lib/plugins/index.d.ts +38 -0
  189. package/lib/plugins/index.d.ts.map +1 -0
  190. package/lib/plugins/index.js +40 -0
  191. package/lib/plugins/kibo/index.d.ts +23 -0
  192. package/lib/plugins/kibo/index.d.ts.map +1 -0
  193. package/lib/plugins/kibo/index.js +199 -0
  194. package/lib/plugins/level-selector/LevelSelector.d.ts +48 -17
  195. package/lib/plugins/level-selector/LevelSelector.d.ts.map +1 -1
  196. package/lib/plugins/level-selector/LevelSelector.js +169 -155
  197. package/lib/plugins/logo/Logo.d.ts +29 -0
  198. package/lib/plugins/logo/Logo.d.ts.map +1 -0
  199. package/lib/plugins/logo/Logo.js +181 -0
  200. package/lib/plugins/logo/utils/index.d.ts +22 -0
  201. package/lib/plugins/logo/utils/index.d.ts.map +1 -0
  202. package/lib/plugins/logo/utils/index.js +32 -0
  203. package/lib/plugins/media-control/MediaControl.d.ts +20 -25
  204. package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
  205. package/lib/plugins/media-control/MediaControl.js +136 -106
  206. package/lib/plugins/multi-camera/MultiCamera.d.ts +59 -0
  207. package/lib/plugins/multi-camera/MultiCamera.d.ts.map +1 -0
  208. package/lib/plugins/multi-camera/MultiCamera.js +353 -0
  209. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts +20 -0
  210. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts.map +1 -0
  211. package/lib/plugins/picture-in-picture/PictureInPicture.js +68 -0
  212. package/lib/plugins/playback-rate/PlaybackRate.d.ts +42 -0
  213. package/lib/plugins/playback-rate/PlaybackRate.d.ts.map +1 -0
  214. package/lib/plugins/playback-rate/PlaybackRate.js +205 -0
  215. package/lib/plugins/poster/Poster.d.ts +18 -17
  216. package/lib/plugins/poster/Poster.d.ts.map +1 -1
  217. package/lib/plugins/poster/Poster.js +83 -37
  218. package/lib/plugins/seek-time/SeekTime.d.ts +38 -0
  219. package/lib/plugins/seek-time/SeekTime.d.ts.map +1 -0
  220. package/lib/plugins/seek-time/SeekTime.js +153 -0
  221. package/lib/plugins/share/Share.d.ts +38 -0
  222. package/lib/plugins/share/Share.d.ts.map +1 -0
  223. package/lib/plugins/share/Share.js +122 -0
  224. package/lib/plugins/skip-time/SkipTime.d.ts +28 -0
  225. package/lib/plugins/skip-time/SkipTime.d.ts.map +1 -0
  226. package/lib/plugins/skip-time/SkipTime.js +86 -0
  227. package/lib/plugins/source-controller/SourceController.d.ts +41 -0
  228. package/lib/plugins/source-controller/SourceController.d.ts.map +1 -0
  229. package/lib/plugins/source-controller/SourceController.js +199 -0
  230. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts +26 -0
  231. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts.map +1 -0
  232. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.js +117 -0
  233. package/lib/plugins/statistics/Statistics.d.ts +52 -0
  234. package/lib/plugins/statistics/Statistics.d.ts.map +1 -0
  235. package/lib/plugins/statistics/Statistics.js +130 -0
  236. package/lib/plugins/subtitles/Subtitles.d.ts +61 -0
  237. package/lib/plugins/subtitles/Subtitles.d.ts.map +1 -0
  238. package/lib/plugins/subtitles/Subtitles.js +354 -0
  239. package/lib/plugins/thumbnails/Thumbnails.d.ts +47 -0
  240. package/lib/plugins/thumbnails/Thumbnails.d.ts.map +1 -0
  241. package/lib/plugins/thumbnails/Thumbnails.js +414 -0
  242. package/lib/plugins/types.d.ts +8 -0
  243. package/lib/plugins/types.d.ts.map +1 -0
  244. package/lib/plugins/types.js +1 -0
  245. package/lib/plugins/utils.d.ts +5 -0
  246. package/lib/plugins/utils.d.ts.map +1 -0
  247. package/lib/plugins/utils.js +68 -0
  248. package/lib/plugins/vast-ads/VastAds.d.ts +72 -0
  249. package/lib/plugins/vast-ads/VastAds.d.ts.map +1 -0
  250. package/lib/plugins/vast-ads/VastAds.js +686 -0
  251. package/lib/plugins/vast-ads/loaderxml.d.ts +32 -0
  252. package/lib/plugins/vast-ads/loaderxml.d.ts.map +1 -0
  253. package/lib/plugins/vast-ads/loaderxml.js +226 -0
  254. package/lib/plugins/vast-ads/roll.d.ts +60 -0
  255. package/lib/plugins/vast-ads/roll.d.ts.map +1 -0
  256. package/lib/plugins/vast-ads/roll.js +415 -0
  257. package/lib/plugins/vast-ads/rollmanager.d.ts +62 -0
  258. package/lib/plugins/vast-ads/rollmanager.d.ts.map +1 -0
  259. package/lib/plugins/vast-ads/rollmanager.js +347 -0
  260. package/lib/plugins/vast-ads/sctemanager.d.ts +18 -0
  261. package/lib/plugins/vast-ads/sctemanager.d.ts.map +1 -0
  262. package/lib/plugins/vast-ads/sctemanager.js +116 -0
  263. package/lib/plugins/vast-ads/types.d.ts +12 -0
  264. package/lib/plugins/vast-ads/types.d.ts.map +1 -0
  265. package/lib/plugins/vast-ads/types.js +1 -0
  266. package/lib/plugins/vast-ads/urlhandler.d.ts +4 -0
  267. package/lib/plugins/vast-ads/urlhandler.d.ts.map +1 -0
  268. package/lib/plugins/vast-ads/urlhandler.js +30 -0
  269. package/lib/plugins/vast-ads/xmlhttprequest.d.ts +6 -0
  270. package/lib/plugins/vast-ads/xmlhttprequest.d.ts.map +1 -0
  271. package/lib/plugins/vast-ads/xmlhttprequest.js +39 -0
  272. package/lib/plugins/vast-ads/xmlmerge.d.ts +12 -0
  273. package/lib/plugins/vast-ads/xmlmerge.d.ts.map +1 -0
  274. package/lib/plugins/vast-ads/xmlmerge.js +82 -0
  275. package/lib/plugins/volume-fade/VolumeFade.d.ts +21 -0
  276. package/lib/plugins/volume-fade/VolumeFade.d.ts.map +1 -0
  277. package/lib/plugins/volume-fade/VolumeFade.js +90 -0
  278. package/package.json +10 -2
  279. package/rollup.config.js +32 -2
  280. package/src/index.core.ts +15 -0
  281. package/src/index.plugins.ts +42 -0
  282. package/src/index.ts +2 -15
  283. package/src/plugins/audio-selector/AudioSelector.ts +370 -0
  284. package/src/plugins/big-mute-button/BigMuteButton.ts +187 -0
  285. package/src/plugins/bottom-gear/BottomGear.ts +122 -0
  286. package/src/plugins/build.ts +1 -0
  287. package/src/plugins/clappr-nerd-stats/ClapprNerdStats.ts +369 -0
  288. package/src/plugins/clappr-nerd-stats/formatter.ts +109 -0
  289. package/src/plugins/clappr-nerd-stats/speedtest/Speedtest.ts +414 -0
  290. package/src/plugins/clappr-nerd-stats/speedtest/index.ts +183 -0
  291. package/src/plugins/clappr-nerd-stats/speedtest/types.ts +5 -0
  292. package/src/plugins/clappr-nerd-stats/types.ts +3 -0
  293. package/src/plugins/clappr-stats/ClapprStats.ts +441 -0
  294. package/src/plugins/clappr-stats/types.ts +52 -0
  295. package/src/plugins/clappr-stats/utils.ts +42 -0
  296. package/src/plugins/click-to-pause/ClickToPause.ts +93 -0
  297. package/src/plugins/clips/Clips.ts +152 -0
  298. package/src/plugins/context-menu/ContextMenu.ts +134 -0
  299. package/src/plugins/disable-controls/DisableControls.ts +81 -0
  300. package/src/plugins/dvr-controls/DvrControls.ts +131 -0
  301. package/src/plugins/error-screen/ErrorScreen.ts +241 -0
  302. package/src/plugins/favicon/Favicon.ts +137 -0
  303. package/src/plugins/ga-events/GaEvents.js +395 -0
  304. package/src/plugins/ga-events/ga-tracking.js +46 -0
  305. package/src/plugins/google-analytics/GoogleAnalytics.ts +147 -0
  306. package/src/plugins/index.ts +42 -0
  307. package/src/plugins/kibo/index.ts +244 -0
  308. package/src/plugins/level-selector/LevelSelector.ts +400 -0
  309. package/src/plugins/level-selector/__tests__/LevelSelector.test.ts +72 -0
  310. package/src/plugins/level-selector/__tests__/__snapshots__/LevelSelector.test.ts.snap +11 -0
  311. package/src/plugins/logo/Logo.ts +233 -0
  312. package/src/plugins/logo/utils/index.ts +46 -0
  313. package/src/plugins/media-control/MediaControl.ts +1383 -0
  314. package/src/plugins/multi-camera/MultiCamera copy.xts +414 -0
  315. package/src/plugins/multi-camera/MultiCamera.ts +426 -0
  316. package/src/plugins/picture-in-picture/PictureInPicture.ts +87 -0
  317. package/src/plugins/playback-rate/PlaybackRate.ts +269 -0
  318. package/src/plugins/poster/Poster.ts +298 -0
  319. package/src/plugins/seek-time/SeekTime.ts +191 -0
  320. package/src/plugins/share/Share.ts +148 -0
  321. package/src/plugins/skip-time/SkipTime.ts +109 -0
  322. package/src/plugins/source-controller/SourceController.ts +239 -0
  323. package/src/plugins/source-controller/__tests__/SourceController.test.ts +230 -0
  324. package/src/plugins/spinner-three-bounce/SpinnerThreeBounce.ts +135 -0
  325. package/src/plugins/statistics/Statistics copy.xts +296 -0
  326. package/src/plugins/statistics/Statistics.ts +207 -0
  327. package/src/plugins/subtitles/Subtitles.ts +505 -0
  328. package/src/plugins/thumbnails/Thumbnails.ts +530 -0
  329. package/src/plugins/types.ts +7 -0
  330. package/src/plugins/typings/globals.d.ts +10 -0
  331. package/src/plugins/typings/parse-srt.d.ts +14 -0
  332. package/src/plugins/typings/workers.d.ts +3 -0
  333. package/src/plugins/utils.ts +77 -0
  334. package/src/plugins/vast-ads/VastAds.ts +915 -0
  335. package/src/plugins/vast-ads/loaderxml.ts +260 -0
  336. package/src/plugins/vast-ads/roll.ts +492 -0
  337. package/src/plugins/vast-ads/rollmanager.ts +403 -0
  338. package/src/plugins/vast-ads/sctemanager.ts +134 -0
  339. package/src/plugins/vast-ads/types.ts +14 -0
  340. package/src/plugins/vast-ads/urlhandler.ts +37 -0
  341. package/src/plugins/vast-ads/xmlhttprequest.ts +44 -0
  342. package/src/plugins/vast-ads/xmlmerge.ts +96 -0
  343. package/src/plugins/video360/VRControls.js +104 -0
  344. package/src/plugins/video360/VREffect.js +422 -0
  345. package/src/plugins/video360/Video360.js +979 -0
  346. package/src/plugins/video360/orbit-oriention-controls.js +1002 -0
  347. package/src/plugins/video360/utils.js +49 -0
  348. package/src/plugins/volume-fade/VolumeFade.ts +109 -0
  349. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,530 @@
1
+ import { UICorePlugin, Events, template, $, Container } from '@clappr/core';
2
+ import { reportError, trace } from '@gcorevideo/utils';
3
+ import parseSRT, { type ParsedSRT } from 'parse-srt';
4
+
5
+ import { TimeValue } from '../..//playback.types';
6
+
7
+ import { CLAPPR_VERSION } from '../build.js';
8
+
9
+ import pluginHtml from '../../../assets/thumbnails/scrub-thumbnails.ejs';
10
+ import '../../../assets/thumbnails/style.scss';
11
+ import { ZeptoResult } from '../types.js';
12
+ import { getPageX } from '../utils.js';
13
+
14
+ type ThumbnailsOptions = {
15
+ backdropHeight: number;
16
+ spotlightHeight: number;
17
+ backdropMaxOpacity: number;
18
+ backdropMinOpacity: number;
19
+ vtt: string;
20
+ sprint: string;
21
+ }
22
+
23
+ type Thumb = {
24
+ url: string;
25
+ time: number;
26
+ w: number;
27
+ h: number;
28
+ x: number;
29
+ y: number;
30
+ duration?: number;
31
+ imageH?: number;
32
+ }
33
+
34
+ const T = 'plugins.thumbnails';
35
+
36
+ export class Thumbnails extends UICorePlugin {
37
+ private _$spotlight: ZeptoResult | null = null;
38
+
39
+ private _$backdrop: ZeptoResult | null = null;
40
+
41
+ private $container: ZeptoResult | null = null;
42
+
43
+ private $img: ZeptoResult | null = null;
44
+
45
+ private _$carousel: ZeptoResult | null = null;
46
+
47
+ private $textThumbnail: ZeptoResult | null = null;
48
+
49
+ private _$backdropCarouselImgs: ZeptoResult[] = [];
50
+
51
+ private spriteSheetHeight: number = 0;
52
+
53
+ private _hoverPosition = 0;
54
+
55
+ private _show = false;
56
+
57
+ private _thumbsLoaded = false;
58
+
59
+ private _oldContainer: Container | null = null;
60
+
61
+ private _thumbs: Thumb[] = [];
62
+
63
+ get name() {
64
+ return 'thumbnails';
65
+ }
66
+
67
+ get supportedVersion() {
68
+ return { min: CLAPPR_VERSION };
69
+ }
70
+
71
+ override get attributes() {
72
+ return {
73
+ 'class': this.name
74
+ };
75
+ }
76
+
77
+ get template() {
78
+ return template(pluginHtml);
79
+ }
80
+
81
+ /*
82
+ * Helper to build the "thumbs" property for a sprite sheet.
83
+ *
84
+ * spriteSheetUrl- The url to the sprite sheet image
85
+ * numThumbs- The number of thumbnails on the sprite sheet
86
+ * thumbWidth- The width of each thumbnail.
87
+ * thumbHeight- The height of each thumbnail.
88
+ * numColumns- The number of columns in the sprite sheet.
89
+ * timeInterval- The interval (in seconds) between the thumbnails.
90
+ * startTime- The time (in seconds) that the first thumbnail represents. (defaults to 0)
91
+ */
92
+ // buildSpriteConfig(vtt, spriteSheetUrl, numThumbs, thumbWidth, thumbHeight, numColumns, timeInterval, startTime) {
93
+ private buildSpriteConfig(vtt: ParsedSRT[], spriteSheetUrl: string): Thumb[] {
94
+ const thumbs: Thumb[] = [];
95
+ // let coor: string[] = [];
96
+
97
+ for (const vt of vtt) {
98
+ const el = vt.text;
99
+ // if (el && el.search(/\d*,\d*,\d*,\d*/g) > -1) {
100
+ // el = el.match(/\d*,\d*,\d*,\d*/g)[0];
101
+ // coor = el.split(',');
102
+ // }
103
+ if (el) {
104
+ const m = el.match(/xywh=\d*,\d*,\d*,\d*/g);
105
+ if (m) {
106
+ const coor = m[0].split(',');
107
+ const w = parseInt(coor[2], 10);
108
+ const h = parseInt(coor[3], 10);
109
+ if (w > 0 && h > 0) {
110
+ thumbs.push({
111
+ url: spriteSheetUrl,
112
+ time: vt.start,
113
+ w,
114
+ h,
115
+ x: parseInt(coor[0], 10) || 0,
116
+ y: parseInt(coor[1], 10) || 0,
117
+ });
118
+ }
119
+ }
120
+ }
121
+ }
122
+
123
+ return thumbs;
124
+ }
125
+
126
+ // TODO check if seek enabled
127
+
128
+ override bindEvents() {
129
+ this.listenToOnce(this.core, Events.CORE_READY, this._onCoreReady);
130
+ this.listenTo(this.core.mediaControl, Events.MEDIACONTROL_MOUSEMOVE_SEEKBAR, this._onMouseMove);
131
+ this.listenTo(this.core.mediaControl, Events.MEDIACONTROL_MOUSELEAVE_SEEKBAR, this._onMouseLeave);
132
+ this.listenTo(this.core.mediaControl, Events.MEDIACONTROL_RENDERED, this._init);
133
+ this.listenTo(this.core.mediaControl, Events.MEDIACONTROL_CONTAINERCHANGED, this._onMediaControlContainerChanged);
134
+ }
135
+
136
+ private _bindContainerEvents() {
137
+ if (this._oldContainer) {
138
+ this.stopListening(this._oldContainer, Events.CONTAINER_TIMEUPDATE, this._renderPlugin);
139
+ }
140
+ this._oldContainer = this.core.mediaControl.container;
141
+ this.listenTo(this.core.mediaControl.container, Events.CONTAINER_TIMEUPDATE, this._renderPlugin);
142
+ }
143
+
144
+ private _onCoreReady() {
145
+ try {
146
+ if (!this.options.thumbnails || !this.options.thumbnails.sprite || !this.options.thumbnails.vtt) {
147
+ this.destroy();
148
+
149
+ return;
150
+ }
151
+ } catch (error) {
152
+ reportError(error);
153
+
154
+ return;
155
+ }
156
+ // TODO options
157
+ const spriteSheet = this.options.thumbnails.sprite;
158
+ this._thumbs = this.buildSpriteConfig(parseSRT(this.options.thumbnails.vtt), spriteSheet);
159
+ if (!this._thumbs.length) {
160
+ this.destroy();
161
+ return;
162
+ }
163
+ this.loadSpriteSheet(spriteSheet).then(() => {
164
+ this._thumbsLoaded = true;
165
+ this.core.options.thumbnails.spotlightHeight = this._thumbs[0].h;
166
+ this._init();
167
+ })
168
+ }
169
+
170
+ private async loadSpriteSheet(spriteSheetUrl: string): Promise<void> {
171
+ return new Promise((resolve, reject) => {
172
+ const img = new Image();
173
+ img.onload = () => {
174
+ this.spriteSheetHeight = img.height;
175
+ resolve();
176
+ };
177
+ img.onerror = reject;
178
+ img.src = spriteSheetUrl;
179
+ });
180
+ }
181
+
182
+ private _onMediaControlContainerChanged() {
183
+ this._bindContainerEvents();
184
+ }
185
+
186
+ private _init() {
187
+ if (!this._thumbsLoaded) {
188
+ // _init() will be called when the thumbs are loaded,
189
+ // and whenever the media control rendered event is fired as just before this the dom elements get wiped in IE (https://github.com/tjenkinson/clappr-thumbnails-plugin/issues/5)
190
+ return;
191
+ }
192
+ // Init the backdropCarousel as array to keep reference of thumbnail images
193
+ this._$backdropCarouselImgs = [];
194
+ // create/recreate the dom elements for the plugin
195
+ this._createElements();
196
+ this._loadBackdrop();
197
+ this._renderPlugin();
198
+ }
199
+
200
+ private _getOptions(): ThumbnailsOptions {
201
+ if (!('thumbnails' in this.core.options)) {
202
+ throw '\'thumbnail property missing from options object.';
203
+ }
204
+
205
+ return this.core.options.thumbnails;
206
+ }
207
+
208
+ private _appendElToMediaControl() {
209
+ // insert after the background
210
+ this.core.mediaControl.$el.find('.seek-time').css('bottom', 56);
211
+ this.core.mediaControl.$el.first().after(this.el);
212
+ }
213
+
214
+ private _onMouseMove(e: MouseEvent) {
215
+ // trace(`${T} _onMouseMove`, {
216
+ // e: (e as any).name,
217
+ // t: typeof e,
218
+ // t2: typeof arguments[1],
219
+ // });
220
+ this._calculateHoverPosition(e);
221
+ this._show = true;
222
+ this._renderPlugin();
223
+ }
224
+
225
+ private _onMouseLeave() {
226
+ this._show = false;
227
+ this._renderPlugin();
228
+ }
229
+
230
+ private _calculateHoverPosition(e: MouseEvent) {
231
+ const offset = getPageX(e) - this.core.mediaControl.$seekBarContainer.offset().left;
232
+
233
+ // proportion into the seek bar that the mouse is hovered over 0-1
234
+ this._hoverPosition = Math.min(1, Math.max(offset / this.core.mediaControl.$seekBarContainer.width(), 0));
235
+ }
236
+
237
+ // private _buildThumbsFromOptions() {
238
+ // const thumbs = this._thumbs;
239
+ // const promises = thumbs.map((thumb) => {
240
+ // return this._addThumbFromSrc(thumb);
241
+ // });
242
+
243
+ // return Promise.all(promises);
244
+ // }
245
+
246
+ // private _addThumbFromSrc(thumbSrc) {
247
+ // return new Promise((resolve, reject) => {
248
+ // const img = new Image();
249
+
250
+ // img.onload = () => {
251
+ // resolve(img);
252
+ // };
253
+ // img.onerror = reject;
254
+ // img.src = thumbSrc.url;
255
+ // }).then((img) => {
256
+ // const startTime = thumbSrc.time;
257
+ // // determine the thumb index
258
+ // let index = null;
259
+
260
+ // this._thumbs.some((thumb, i) => {
261
+ // if (startTime < thumb.time) {
262
+ // index = i;
263
+
264
+ // return true;
265
+ // }
266
+
267
+ // return false;
268
+ // });
269
+ // if (index === null) {
270
+ // index = this._thumbs.length;
271
+ // }
272
+
273
+ // const next = index < this._thumbs.length ? this._thumbs[index] : null;
274
+ // const prev = index > 0 ? this._thumbs[index - 1] : null;
275
+
276
+ // if (prev) {
277
+ // // update the duration of the previous thumbnail
278
+ // prev.duration = startTime - prev.time;
279
+ // }
280
+ // // the duration this thumb lasts for
281
+ // // if it is the last thumb then duration will be null
282
+ // const duration = next ? next.time - thumbSrc.time : null;
283
+ // const imageW = img.width;
284
+ // const imageH = img.height;
285
+ // const thumb = {
286
+ // imageW: imageW, // actual width of image
287
+ // imageH: imageH, // actual height of image
288
+ // x: thumbSrc.x || 0, // x coord in image of sprite
289
+ // y: thumbSrc.y || 0, // y coord in image of sprite
290
+ // w: thumbSrc.w || imageW, // width of sprite
291
+ // h: thumbSrc.h || imageH, // height of sprite
292
+ // url: thumbSrc.url,
293
+ // time: startTime, // time this thumb represents
294
+ // duration: duration, // how long (from time) this thumb represents
295
+ // src: thumbSrc
296
+ // };
297
+
298
+ // this._thumbs.splice(index, 0, thumb);
299
+
300
+ // return thumb;
301
+ // });
302
+ // }
303
+
304
+ // builds a dom element which represents the thumbnail
305
+ // scaled to the provided height
306
+ private _buildImg(thumb: Thumb, height: number) {
307
+ const scaleFactor = height / thumb.h;
308
+
309
+ if (!this.$img) {
310
+ this.$img = $('<img />').addClass('thumbnail-img').attr('src', thumb.url);
311
+ }
312
+
313
+ // the container will contain the image positioned so that the correct sprite
314
+ // is visible
315
+ if (!this.$container) {
316
+ this.$container = $('<div />').addClass('thumbnail-container');
317
+ }
318
+
319
+ this.$container.css('width', thumb.w * scaleFactor);
320
+ this.$container.css('height', height);
321
+ this.$img.css({
322
+ height: this.spriteSheetHeight * scaleFactor,
323
+ left: -1 * thumb.x * scaleFactor,
324
+ top: -1 * thumb.y * scaleFactor
325
+ });
326
+ if (this.$container.find(this.$img).length === 0) {
327
+ this.$container.append(this.$img);
328
+ }
329
+
330
+ return this.$container;
331
+ }
332
+
333
+ private _loadBackdrop() {
334
+ if (!this._getOptions().backdropHeight) {
335
+ // disabled
336
+ return;
337
+ }
338
+
339
+ // append each of the thumbnails to the backdrop carousel
340
+ const $carousel = this._$carousel;
341
+
342
+ for (const thumb of this._thumbs) {
343
+ const $img = this._buildImg(thumb, this._getOptions().backdropHeight);
344
+
345
+ // Keep reference to thumbnail
346
+ this._$backdropCarouselImgs.push($img);
347
+ // Add thumbnail to DOM
348
+ $carousel.append($img);
349
+ }
350
+ }
351
+
352
+ setText(time: TimeValue) {
353
+ if (this.core.getPlugin('clips')) {
354
+ const txt = this.core.getPlugin('clips').getText(time);
355
+
356
+ this.$textThumbnail.text(txt);
357
+ }
358
+ }
359
+
360
+ // calculate how far along the carousel should currently be slid
361
+ // depending on where the user is hovering on the progress bar
362
+ private _updateCarousel() {
363
+ trace(`${T} _updateCarousel`, {
364
+ backdropHeight: this._getOptions().backdropHeight,
365
+ });
366
+ if (!this._getOptions().backdropHeight) {
367
+ // disabled
368
+ return;
369
+ }
370
+
371
+ const hoverPosition = this._hoverPosition;
372
+ const videoDuration = this.core.mediaControl.container.getDuration();
373
+ const startTimeOffset = this.core.mediaControl.container.getStartTimeOffset();
374
+ // the time into the video at the current hover position
375
+ const hoverTime = startTimeOffset + (videoDuration * hoverPosition);
376
+ const backdropWidth = this._$backdrop.width();
377
+ const $carousel = this._$carousel;
378
+ const carouselWidth = $carousel.width();
379
+
380
+ // slide the carousel so that the image on the carousel that is above where the person
381
+ // is hovering maps to that position in time.
382
+ // Thumbnails may not be distributed at even times along the video
383
+ const thumbs = this._thumbs;
384
+
385
+ // assuming that each thumbnail has the same width
386
+ const thumbWidth = carouselWidth / thumbs.length;
387
+
388
+ // determine which thumbnail applies to the current time
389
+ const thumbIndex = this._getThumbIndexForTime(hoverTime);
390
+ const thumb = thumbs[thumbIndex];
391
+ let thumbDuration = thumb.duration;
392
+
393
+ if (!thumbDuration) {
394
+ // the last thumbnail duration will be null as it can't be determined
395
+ // e.g the duration of the video may increase over time (live stream)
396
+ // so calculate the duration now so this last thumbnail lasts till the end
397
+ thumbDuration = Math.max(videoDuration + startTimeOffset - thumb.time, 0);
398
+ }
399
+
400
+ // determine how far accross that thumbnail we are
401
+ const timeIntoThumb = hoverTime - thumb.time;
402
+ const positionInThumb = timeIntoThumb / thumbDuration;
403
+ const xCoordInThumb = thumbWidth * positionInThumb;
404
+
405
+ // now calculate the position along carousel that we want to be above the hover position
406
+ const xCoordInCarousel = (thumbIndex * thumbWidth) + xCoordInThumb;
407
+ // and finally the position of the carousel when the hover position is taken in to consideration
408
+ const carouselXCoord = xCoordInCarousel - (hoverPosition * backdropWidth);
409
+
410
+ $carousel.css('left', -carouselXCoord);
411
+
412
+ const maxOpacity = this._getOptions().backdropMaxOpacity || 0.6;
413
+ const minOpacity = this._getOptions().backdropMinOpacity || 0.08;
414
+
415
+ // now update the transparencies so that they fade in around the active one
416
+ for (let i = 0; i < thumbs.length; i++) {
417
+ const thumbXCoord = thumbWidth * i;
418
+ let distance = thumbXCoord - xCoordInCarousel;
419
+
420
+ if (distance < 0) {
421
+ // adjust so that distance is always a measure away from
422
+ // each side of the active thumbnail
423
+ // at every point on the active thumbnail the distance should
424
+ // be 0
425
+ distance = Math.min(0, distance + thumbWidth);
426
+ }
427
+ // fade over the width of 2 thumbnails
428
+ const opacity = Math.max(maxOpacity - (Math.abs(distance) / (2 * thumbWidth)), minOpacity);
429
+
430
+ this._$backdropCarouselImgs[i].css('opacity', opacity);
431
+ }
432
+ }
433
+
434
+ private _updateSpotlightThumb() {
435
+ trace(`${T} _updateSpotlightThumb`, {
436
+ spotlightHeight: this._getOptions().spotlightHeight,
437
+ });
438
+ if (!this._getOptions().spotlightHeight) {
439
+ // disabled
440
+ return;
441
+ }
442
+
443
+ const hoverPosition = this._hoverPosition;
444
+ const videoDuration = this.core.mediaControl.container.getDuration();
445
+ // the time into the video at the current hover position
446
+ const startTimeOffset = this.core.mediaControl.container.getStartTimeOffset();
447
+ const hoverTime = startTimeOffset + (videoDuration * hoverPosition);
448
+
449
+ this.setText(hoverTime);
450
+
451
+ // determine which thumbnail applies to the current time
452
+ const thumbIndex = this._getThumbIndexForTime(hoverTime);
453
+ const thumb = this._thumbs[thumbIndex];
454
+
455
+ // update thumbnail
456
+ const $spotlight = this._$spotlight;
457
+
458
+ $spotlight.empty();
459
+ $spotlight.append(this._buildImg(thumb, this._getOptions().spotlightHeight));
460
+
461
+ const elWidth = this.$el.width();
462
+ const thumbWidth = $spotlight.width();
463
+ const thumbHeight = $spotlight.height();
464
+
465
+ let spotlightXPos = (elWidth * hoverPosition) - (thumbWidth / 2);
466
+
467
+ // adjust so the entire thumbnail is always visible
468
+ spotlightXPos = Math.max(Math.min(spotlightXPos, elWidth - thumbWidth), 0);
469
+
470
+ $spotlight.css('left', spotlightXPos);
471
+
472
+ this.$textThumbnail.css('left', spotlightXPos);
473
+ this.$textThumbnail.css('width', thumbWidth);
474
+ this.$textThumbnail.css('bottom', thumbHeight + 1);
475
+ }
476
+
477
+ // returns the thumbnail which represents a time in the video
478
+ // or null if there is no thumbnail that can represent the time
479
+ private _getThumbIndexForTime(time: TimeValue) {
480
+ const thumbs = this._thumbs;
481
+
482
+ for (let i = thumbs.length - 1; i >= 0; i--) {
483
+ const thumb = thumbs[i];
484
+
485
+ if (thumb.time <= time) {
486
+ return i;
487
+ }
488
+ }
489
+
490
+ // stretch the first thumbnail back to the start
491
+ return 0;
492
+ }
493
+
494
+ private _renderPlugin() {
495
+ trace(`${T} _renderPlugin`, {
496
+ show: this._show,
497
+ thumbsLoaded: this._thumbsLoaded,
498
+ thumbs: this._thumbs.length,
499
+ });
500
+ if (!this._thumbsLoaded) {
501
+ return;
502
+ }
503
+ if (this._show && this._thumbs.length > 0) {
504
+ this.$el.removeClass('hidden');
505
+ this._updateCarousel();
506
+ this._updateSpotlightThumb();
507
+ } else {
508
+ this.$el.addClass('hidden');
509
+ }
510
+ }
511
+
512
+ private _createElements() {
513
+ trace(`${T} _createElements`);
514
+ this.$el.html(
515
+ this.template(
516
+ {
517
+ 'backdropHeight': this._getOptions().backdropHeight,
518
+ 'spotlightHeight': this._getOptions().spotlightHeight
519
+ }
520
+ )
521
+ );
522
+ // cache dom references
523
+ this._$spotlight = this.$el.find('.spotlight');
524
+ this._$backdrop = this.$el.find('.backdrop');
525
+ this._$carousel = this._$backdrop.find('.carousel');
526
+ this.$textThumbnail = this.$el.find('.thumbnails-text');
527
+ this.$el.addClass('hidden');
528
+ this._appendElToMediaControl();
529
+ }
530
+ }
@@ -0,0 +1,7 @@
1
+ import { $ } from "@clappr/core";
2
+
3
+ export type ZeptoResult = ReturnType<typeof $>;
4
+
5
+ export type TimePosition = { current: number; total: number };
6
+
7
+ export type TimerId = ReturnType<typeof setTimeout>;
@@ -0,0 +1,10 @@
1
+ declare interface HTMLVideoElement {
2
+ webkitDisplayingFullscreen?: boolean;
3
+ }
4
+
5
+ declare module "*.css";
6
+ declare module "*.ejs";
7
+ declare module "*.ejs?raw";
8
+ declare module "*.html";
9
+ declare module "*.scss";
10
+ declare module "*.svg";
@@ -0,0 +1,14 @@
1
+ // import * from 'parse-srt';
2
+
3
+ declare module 'parse-srt' {
4
+ export declare type ParsedSRT = {
5
+ id: number;
6
+ start: number;
7
+ end: number;
8
+ text: string;
9
+ };
10
+
11
+ declare function parseSRT(srt: string): ParsedSRT[];
12
+
13
+ export default parseSRT;
14
+ }
@@ -0,0 +1,3 @@
1
+ declare module "*.worker.js" {
2
+ export default string;
3
+ }
@@ -0,0 +1,77 @@
1
+ import { Browser } from '@clappr/core';
2
+ import { reportError } from '@gcorevideo/utils';
3
+
4
+ export function getLocation(href: string) {
5
+ const l = document.createElement('a');
6
+
7
+ l.href = href;
8
+
9
+ return l;
10
+ }
11
+
12
+ export function strtimeToMiliseconds(str: string): number {
13
+ if (!str) {
14
+ return 0;
15
+ }
16
+ const arr = str.split(/:/);
17
+ let h = 0, m = 0, s = 0;
18
+
19
+ if (arr.length >= 3) {
20
+ h = parseInt(arr[arr.length - 3]) * 60 * 60;
21
+ } else {
22
+ h = 0;
23
+ }
24
+ if (arr.length >= 2) {
25
+ m = parseInt(arr[arr.length - 2]) * 60;
26
+ } else {
27
+ m = 0;
28
+ }
29
+
30
+ if (arr.length >= 1) {
31
+ s = parseInt(arr[arr.length - 1]);
32
+ } else {
33
+ s = 0;
34
+ }
35
+
36
+ return (h + m + s);
37
+ }
38
+
39
+ // TODO refactor
40
+ export function isFullscreen(el: HTMLElement): boolean {
41
+ const video = el.nodeName === "video" ? el as HTMLVideoElement : el.querySelector('video');
42
+ if (!video) {
43
+ return false;
44
+ }
45
+ if (Browser.isiOS) {
46
+ return FullscreenIOS.isFullscreen(video);
47
+ }
48
+ return !!(document.fullscreenElement);
49
+ }
50
+
51
+ const FullscreenIOS = {
52
+ isFullscreen: function (el: HTMLVideoElement): boolean {
53
+ try {
54
+ // @ts-ignore
55
+ if (el.webkitDisplayingFullscreen !== undefined) {
56
+ // @ts-ignore
57
+ return !!(el.webkitDisplayingFullscreen);
58
+ }
59
+ } catch (e) {
60
+ reportError(e);
61
+ }
62
+
63
+ return false;
64
+ }
65
+ };
66
+
67
+ export function getPageX(event: MouseEvent | TouchEvent): number {
68
+ if ((event as MouseEvent).pageX) {
69
+ return (event as MouseEvent).pageX;
70
+ }
71
+
72
+ if ((event as TouchEvent).changedTouches) {
73
+ return (event as TouchEvent).changedTouches[(event as TouchEvent).changedTouches.length - 1].pageX;
74
+ }
75
+
76
+ return 0;
77
+ }