diff --git a/plugin/videojs/amd/build/videotime.min.js b/plugin/videojs/amd/build/videotime.min.js index a5cc4ad9..daa02925 100644 --- a/plugin/videojs/amd/build/videotime.min.js +++ b/plugin/videojs/amd/build/videotime.min.js @@ -6,6 +6,6 @@ define("videotimeplugin_videojs/videotime",["exports","jquery","mod_videotime/vi * @module videotimeplugin_videojs/videotime * @copyright 2022 bdecent gmbh * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_jquery=_interopRequireDefault(_jquery),_videotime=_interopRequireDefault(_videotime),_log=_interopRequireDefault(_log),_notification=_interopRequireDefault(_notification),_videoLazy=_interopRequireDefault(_videoLazy);class VideoTime extends _videotime.default{initialize(){_log.default.debug("Initializing Video Time "+this.elementId);const instance=this.instance,options={autoplay:Number(instance.autoplay),controls:Number(instance.controls),sources:[{type:instance.type,src:instance.vimeo_url}],loop:Number(instance.option_loop),fluid:Number(instance.responsive),playsinline:Number(instance.playsinline),playbackRates:Number(instance.speed)?[.5,.75,1,1.25,1.5,2]:[1],muted:Number(instance.muted)};"video/youtube"===instance.type&&(options.techOrder=["youtube"]),!Number(instance.responsive)&&Number(instance.height)&&Number(instance.width)&&(options.height=Number(instance.height),options.width=Number(instance.width)),_log.default.debug("Initializing VideoJS player with options:"),_log.default.debug(options),this.player=new _videoLazy.default(this.elementId,options),this.player.on("loadedmetadata",(()=>{if(!instance.resume_playback||instance.resume_time<=0||this.resumed)return!0;let duration=this.getPlayer().duration(),resumeTime=instance.resume_time;return resumeTime+1>=Math.floor(duration)&&(_log.default.debug("VIDEO_TIME video finished, resuming at start of video."),resumeTime=0),_log.default.debug("VIDEO_TIME duration is "+duration),_log.default.debug("VIDEO_TIME resuming at "+resumeTime),resumeTime&&setTimeout((()=>{this.setCurrentPosition(resumeTime)}),10),!0})),this.handleStartTime(),this.addListeners();for(let i=0;i(this.played||(this.hasPro&&this.startWatchInterval(),this.view()),!0))),this.hasPro&&(this.player.on("play",function(){this.playing=!0,_log.default.debug("VIDEO_TIME play")}.bind(this)),this.player.on("playing",function(){this.playing=!0,_log.default.debug("VIDEO_TIME playing")}.bind(this)),this.player.on("pause",function(){this.playing=!1,_log.default.debug("VIDEO_TIME pause")}.bind(this)),this.player.on("stalled",function(){this.playing=!1,_log.default.debug("VIDEO_TIME stalled")}.bind(this)),this.player.on("suspend",function(){this.playing=!1,_log.default.debug("VIDEO_TIME suspend")}.bind(this)),this.player.on("abort",function(){this.playing=!1,_log.default.debug("VIDEO_TIME abort")}.bind(this)),this.player.on("playbackrateschange",function(){this.playbackRate=this.player.playbackRate()}.bind(this)),this.player.on("timeupdate",function(){this.currentTime=this.player.currentTime(),this.percent=this.currentTime/this.player.duration(),_log.default.debug("VIDEO_TIME timeupdate. Percent: "+this.percent+". Current time: "+this.currentTime)}.bind(this)),this.player.on("ended",this.handleEnd.bind(this)),this.player.on("pause",this.handleEnd.bind(this)),this.player.options().responsive)){new ResizeObserver((()=>{this.player.height(this.player.videoHeight()/this.player.videoWidth()*this.player.currentWidth())})).observe(document.querySelector("#"+this.elementId))}}else _log.default.debug("Player was not properly initialized for course module "+this.cmId)}async setStartTime(starttime){let time=starttime.match(/((([0-9]+):)?(([0-9]+):))?([0-9]+(\.[0-9]+))/);return time?(this.resumeTime=3600*Number(time[3]||0)+60*Number(time[5]||0)+Number(time[6]),await this.player.currentTime(this.resumeTime)):(_log.default.debug("Set start time:"+starttime),await this.player.currentTime())}getDuration(){return new Promise((resolve=>(resolve(this.player.duration()),!0)))}getPlaybackRate(){return new Promise((resolve=>(resolve(this.player.playbackRate()),!0)))}setCurrentPosition(secs){return new Promise((resolve=>(resolve(this.player.currentTime(secs)),!0)))}async getCurrentPosition(){let position=await this.player.currentTime();return this.plugins.forEach((plugin=>{position=plugin.getCurrentPosition(position)})),position}getPaused(){return this.player.paused()}}return _exports.default=VideoTime,_exports.default})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_jquery=_interopRequireDefault(_jquery),_videotime=_interopRequireDefault(_videotime),_log=_interopRequireDefault(_log),_notification=_interopRequireDefault(_notification),_videoLazy=_interopRequireDefault(_videoLazy);class VideoTime extends _videotime.default{initialize(){_log.default.debug("Initializing Video Time "+this.elementId);const instance=this.instance,options={autoplay:Number(instance.autoplay),controls:Number(instance.controls),sources:[{type:instance.type,src:instance.vimeo_url}],loop:Number(instance.option_loop),fluid:Number(instance.responsive),playsinline:Number(instance.playsinline),playbackRates:Number(instance.speed)?[.5,.75,1,1.25,1.5,2]:[1],muted:Number(instance.muted)};"video/youtube"===instance.type&&(options.techOrder=["youtube"]),!Number(instance.responsive)&&Number(instance.height)&&Number(instance.width)&&(options.height=Number(instance.height),options.width=Number(instance.width)),_log.default.debug("Initializing VideoJS player with options:"),_log.default.debug(options),this.player=new _videoLazy.default(this.elementId,options),this.player.on("loadedmetadata",(()=>{if(!instance.resume_playback||instance.resume_time<=0||this.resumed)return!0;let duration=this.getPlayer().duration(),resumeTime=instance.resume_time;return resumeTime+1>=Math.floor(duration)&&(_log.default.debug("VIDEO_TIME video finished, resuming at start of video."),resumeTime=0),_log.default.debug("VIDEO_TIME duration is "+duration),_log.default.debug("VIDEO_TIME resuming at "+resumeTime),resumeTime&&setTimeout((()=>{this.setCurrentPosition(resumeTime)}),10),!0})),this.handleStartTime(),this.addListeners();for(let i=0;i(this.played||(this.hasPro&&this.startWatchInterval(),this.view()),!0))),this.hasPro&&(this.player.on("play",function(){this.playing=!0,_log.default.debug("VIDEO_TIME play")}.bind(this)),this.player.on("playing",function(){this.playing=!0,_log.default.debug("VIDEO_TIME playing")}.bind(this)),this.player.on("pause",function(){this.playing=!1,_log.default.debug("VIDEO_TIME pause")}.bind(this)),this.player.on("stalled",function(){this.playing=!1,_log.default.debug("VIDEO_TIME stalled")}.bind(this)),this.player.on("suspend",function(){this.playing=!1,_log.default.debug("VIDEO_TIME suspend")}.bind(this)),this.player.on("abort",function(){this.playing=!1,_log.default.debug("VIDEO_TIME abort")}.bind(this)),this.player.on("playbackrateschange",function(){this.playbackRate=this.player.playbackRate()}.bind(this)),this.player.on("timeupdate",function(){this.currentTime=this.player.currentTime(),this.percent=this.currentTime/this.player.duration(),_log.default.debug("VIDEO_TIME timeupdate. Percent: "+this.percent+". Current time: "+this.currentTime)}.bind(this)),this.player.on("ended",this.handleEnd.bind(this)),this.player.on("pause",this.handlePause.bind(this)),this.player.options().responsive)){new ResizeObserver((()=>{this.player.height(this.player.videoHeight()/this.player.videoWidth()*this.player.currentWidth())})).observe(document.querySelector("#"+this.elementId))}}else _log.default.debug("Player was not properly initialized for course module "+this.cmId)}async setStartTime(starttime){let time=starttime.match(/((([0-9]+):)?(([0-9]+):))?([0-9]+(\.[0-9]+))/);return time?(this.resumeTime=3600*Number(time[3]||0)+60*Number(time[5]||0)+Number(time[6]),await this.player.currentTime(this.resumeTime)):(_log.default.debug("Set start time:"+starttime),await this.player.currentTime())}getDuration(){return new Promise((resolve=>(resolve(this.player.duration()),!0)))}getPlaybackRate(){return new Promise((resolve=>(resolve(this.player.playbackRate()),!0)))}setCurrentPosition(secs){return new Promise((resolve=>(resolve(this.player.currentTime(secs)),!0)))}async getCurrentPosition(){let position=await this.player.currentTime();return this.plugins.forEach((plugin=>{position=plugin.getCurrentPosition(position)})),position}getPaused(){return this.player.paused()}}return _exports.default=VideoTime,_exports.default})); //# sourceMappingURL=videotime.min.js.map \ No newline at end of file diff --git a/plugin/videojs/amd/build/videotime.min.js.map b/plugin/videojs/amd/build/videotime.min.js.map index 71697bfd..3664ce4d 100644 --- a/plugin/videojs/amd/build/videotime.min.js.map +++ b/plugin/videojs/amd/build/videotime.min.js.map @@ -1 +1 @@ -{"version":3,"file":"videotime.min.js","sources":["../src/videotime.js"],"sourcesContent":["/*\n * Video time player specific js\n *\n * @package videotimeplugin_videojs\n * @module videotimeplugin_videojs/videotime\n * @copyright 2022 bdecent gmbh \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from \"jquery\";\nimport VideoTimeBase from \"mod_videotime/videotime\";\nimport Log from \"core/log\";\nimport Notification from \"core/notification\";\nimport Player from \"media_videojs/video-lazy\";\nimport \"media_videojs/Youtube-lazy\";\n\nexport default class VideoTime extends VideoTimeBase {\n initialize() {\n Log.debug(\"Initializing Video Time \" + this.elementId);\n\n const instance = this.instance,\n options = {\n autoplay: Number(instance.autoplay),\n controls: Number(instance.controls),\n sources: [{type: instance.type, src: instance.vimeo_url}],\n loop: Number(instance.option_loop),\n fluid: Number(instance.responsive),\n playsinline: Number(instance.playsinline),\n playbackRates: Number(instance.speed)\n ? [0.5, 0.75, 1, 1.25, 1.5, 2]\n : [1],\n muted: Number(instance.muted)\n };\n if (instance.type === \"video/youtube\") {\n options.techOrder = [\"youtube\"];\n }\n if (!Number(instance.responsive) && Number(instance.height) && Number(instance.width)) {\n options.height = Number(instance.height);\n options.width = Number(instance.width);\n }\n Log.debug(\"Initializing VideoJS player with options:\");\n Log.debug(options);\n this.player = new Player(this.elementId, options);\n\n this.player.on(\"loadedmetadata\", () => {\n if (!instance.resume_playback || instance.resume_time <= 0 || this.resumed) {\n return true;\n }\n\n let duration = this.getPlayer().duration(),\n resumeTime = instance.resume_time;\n // Duration is often a little greater than a resume time at the end of the video.\n // A user may have watched 100 seconds when the video ends, but the duration may be\n // 100.56 seconds. BUT, sometimes the duration is rounded depending on when the\n // video loads, so it may be 101 seconds. Hence the +1 and Math.floor usage.\n if (resumeTime + 1 >= Math.floor(duration)) {\n Log.debug(\n \"VIDEO_TIME video finished, resuming at start of video.\"\n );\n resumeTime = 0;\n }\n Log.debug(\"VIDEO_TIME duration is \" + duration);\n Log.debug(\"VIDEO_TIME resuming at \" + resumeTime);\n if (resumeTime) {\n setTimeout(() => {\n this.setCurrentPosition(resumeTime);\n }, 10);\n }\n return true;\n });\n\n this.handleStartTime();\n\n this.addListeners();\n\n for (let i = 0; i < this.plugins.length; i++) {\n const plugin = this.plugins[i];\n plugin.initialize(this, instance);\n }\n\n return true;\n }\n\n /**\n * Register player events to respond to user interaction and play progress.\n */\n async addListeners() {\n // If this is a tab play set time cues and listener.\n $($(\"#\" + this.elementId).closest(\".videotimetabs\")).each(\n function(i, tabs) {\n $(tabs)\n .find('[data-action=\"cue\"]')\n .each(\n async function(index, anchor) {\n let starttime = anchor.getAttribute(\"data-start\"),\n time = starttime.match(\n /((([0-9]+):)?(([0-9]+):))?([0-9]+(\\.[0-9]+))/\n );\n if (time) {\n try {\n await this.player.addCuePoint(\n 3600 * Number(time[3] || 0) +\n 60 * Number(time[5] || 0) +\n Number(time[6]),\n {\n starttime: starttime\n }\n );\n } catch (e) {\n Notification.exception(e);\n }\n }\n }.bind(this)\n );\n\n this.player.on(\"cuepoint\", function(event) {\n if (event.data.starttime) {\n $(tabs)\n .find(\".videotime-highlight\")\n .removeClass(\"videotime-highlight\");\n $(tabs)\n .find(\n '[data-action=\"cue\"][data-start=\"' +\n event.data.starttime +\n '\"]'\n )\n .closest(\".row\")\n .addClass(\"videotime-highlight\");\n $(\".videotime-highlight\").each(function() {\n if (this.offsetTop) {\n this.parentNode.scrollTo({\n top: this.offsetTop - 50,\n left: 0,\n behavior: \"smooth\"\n });\n }\n });\n }\n });\n }.bind(this)\n );\n\n if (!this.player) {\n Log.debug(\n \"Player was not properly initialized for course module \" +\n this.cmId\n );\n return;\n }\n\n // Fire view event in Moodle on first play only.\n this.player.on(\"play\", () => {\n if (!this.played) {\n if (this.hasPro) {\n this.startWatchInterval();\n }\n // Free version can still mark completion on video time view.\n this.view();\n }\n return true;\n });\n\n // Features beyond this point are for pro only.\n if (!this.hasPro) {\n return;\n }\n\n // Note: Vimeo player does not support multiple events in a single on() call. Each requires it's own function.\n\n // Catch all events where video plays.\n this.player.on(\n \"play\",\n function() {\n this.playing = true;\n Log.debug(\"VIDEO_TIME play\");\n }.bind(this)\n );\n this.player.on(\n \"playing\",\n function() {\n this.playing = true;\n Log.debug(\"VIDEO_TIME playing\");\n }.bind(this)\n );\n\n // Catch all events where video stops.\n this.player.on(\n \"pause\",\n function() {\n this.playing = false;\n Log.debug(\"VIDEO_TIME pause\");\n }.bind(this)\n );\n this.player.on(\n \"stalled\",\n function() {\n this.playing = false;\n Log.debug(\"VIDEO_TIME stalled\");\n }.bind(this)\n );\n this.player.on(\n \"suspend\",\n function() {\n this.playing = false;\n Log.debug(\"VIDEO_TIME suspend\");\n }.bind(this)\n );\n this.player.on(\n \"abort\",\n function() {\n this.playing = false;\n Log.debug(\"VIDEO_TIME abort\");\n }.bind(this)\n );\n\n this.player.on(\n \"playbackrateschange\",\n function() {\n this.playbackRate = this.player.playbackRate();\n }.bind(this)\n );\n\n // Always update internal values for percent and current time watched.\n this.player.on(\n \"timeupdate\",\n function() {\n this.currentTime = this.player.currentTime();\n this.percent = this.currentTime / this.player.duration();\n Log.debug(\n \"VIDEO_TIME timeupdate. Percent: \" +\n this.percent +\n \". Current time: \" +\n this.currentTime\n );\n }.bind(this)\n );\n\n // Initiate video finish procedure.\n this.player.on(\"ended\", this.handleEnd.bind(this));\n this.player.on(\"pause\", this.handleEnd.bind(this));\n\n // Readjust height when responsive player is resized.\n if (this.player.options().responsive) {\n let observer = new ResizeObserver(() => {\n this.player.height(\n (this.player.videoHeight() / this.player.videoWidth()) *\n this.player.currentWidth()\n );\n });\n observer.observe(document.querySelector(\"#\" + this.elementId));\n }\n }\n\n /**\n * Parse start time and set player\n *\n * @param {string} starttime\n * @returns {Promise}\n */\n async setStartTime(starttime) {\n let time = starttime.match(\n /((([0-9]+):)?(([0-9]+):))?([0-9]+(\\.[0-9]+))/\n );\n if (time) {\n this.resumeTime =\n 3600 * Number(time[3] || 0) +\n 60 * Number(time[5] || 0) +\n Number(time[6]);\n return await this.player.currentTime(this.resumeTime);\n }\n Log.debug(\"Set start time:\" + starttime);\n return await this.player.currentTime();\n }\n\n /**\n * Get play back rate\n *\n * @returns {Promise}\n */\n getDuration() {\n return new Promise(resolve => {\n resolve(this.player.duration());\n return true;\n });\n }\n\n /**\n * Get duration of video\n *\n * @returns {Promise}\n */\n getPlaybackRate() {\n return new Promise(resolve => {\n resolve(this.player.playbackRate());\n return true;\n });\n }\n\n /**\n * Set current time of player\n *\n * @param {float} secs time\n * @returns {Promise}\n */\n setCurrentPosition(secs) {\n return new Promise(resolve => {\n resolve(this.player.currentTime(secs));\n return true;\n });\n }\n\n /**\n * Get current time of player\n *\n * @returns {Promise}\n */\n async getCurrentPosition() {\n let position = await this.player.currentTime();\n this.plugins.forEach(plugin => {\n position = plugin.getCurrentPosition(position);\n });\n return position;\n }\n\n /**\n * Get pause state\n *\n * @return {bool}\n */\n getPaused() {\n const paused = this.player.paused();\n return paused;\n }\n}\n"],"names":["VideoTime","VideoTimeBase","initialize","debug","this","elementId","instance","options","autoplay","Number","controls","sources","type","src","vimeo_url","loop","option_loop","fluid","responsive","playsinline","playbackRates","speed","muted","techOrder","height","width","player","Player","on","resume_playback","resume_time","resumed","duration","getPlayer","resumeTime","Math","floor","setTimeout","setCurrentPosition","handleStartTime","addListeners","i","plugins","length","closest","each","tabs","find","async","index","anchor","starttime","getAttribute","time","match","addCuePoint","e","exception","bind","event","data","removeClass","addClass","offsetTop","parentNode","scrollTo","top","left","behavior","played","hasPro","startWatchInterval","view","playing","playbackRate","currentTime","percent","handleEnd","ResizeObserver","videoHeight","videoWidth","currentWidth","observe","document","querySelector","cmId","getDuration","Promise","resolve","getPlaybackRate","secs","position","forEach","plugin","getCurrentPosition","getPaused","paused"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"videotime.min.js","sources":["../src/videotime.js"],"sourcesContent":["/*\n * Video time player specific js\n *\n * @package videotimeplugin_videojs\n * @module videotimeplugin_videojs/videotime\n * @copyright 2022 bdecent gmbh \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from \"jquery\";\nimport VideoTimeBase from \"mod_videotime/videotime\";\nimport Log from \"core/log\";\nimport Notification from \"core/notification\";\nimport Player from \"media_videojs/video-lazy\";\nimport \"media_videojs/Youtube-lazy\";\n\nexport default class VideoTime extends VideoTimeBase {\n initialize() {\n Log.debug(\"Initializing Video Time \" + this.elementId);\n\n const instance = this.instance,\n options = {\n autoplay: Number(instance.autoplay),\n controls: Number(instance.controls),\n sources: [{type: instance.type, src: instance.vimeo_url}],\n loop: Number(instance.option_loop),\n fluid: Number(instance.responsive),\n playsinline: Number(instance.playsinline),\n playbackRates: Number(instance.speed)\n ? [0.5, 0.75, 1, 1.25, 1.5, 2]\n : [1],\n muted: Number(instance.muted)\n };\n if (instance.type === \"video/youtube\") {\n options.techOrder = [\"youtube\"];\n }\n if (!Number(instance.responsive) && Number(instance.height) && Number(instance.width)) {\n options.height = Number(instance.height);\n options.width = Number(instance.width);\n }\n Log.debug(\"Initializing VideoJS player with options:\");\n Log.debug(options);\n this.player = new Player(this.elementId, options);\n\n this.player.on(\"loadedmetadata\", () => {\n if (!instance.resume_playback || instance.resume_time <= 0 || this.resumed) {\n return true;\n }\n\n let duration = this.getPlayer().duration(),\n resumeTime = instance.resume_time;\n // Duration is often a little greater than a resume time at the end of the video.\n // A user may have watched 100 seconds when the video ends, but the duration may be\n // 100.56 seconds. BUT, sometimes the duration is rounded depending on when the\n // video loads, so it may be 101 seconds. Hence the +1 and Math.floor usage.\n if (resumeTime + 1 >= Math.floor(duration)) {\n Log.debug(\n \"VIDEO_TIME video finished, resuming at start of video.\"\n );\n resumeTime = 0;\n }\n Log.debug(\"VIDEO_TIME duration is \" + duration);\n Log.debug(\"VIDEO_TIME resuming at \" + resumeTime);\n if (resumeTime) {\n setTimeout(() => {\n this.setCurrentPosition(resumeTime);\n }, 10);\n }\n return true;\n });\n\n this.handleStartTime();\n\n this.addListeners();\n\n for (let i = 0; i < this.plugins.length; i++) {\n const plugin = this.plugins[i];\n plugin.initialize(this, instance);\n }\n\n return true;\n }\n\n /**\n * Register player events to respond to user interaction and play progress.\n */\n async addListeners() {\n // If this is a tab play set time cues and listener.\n $($(\"#\" + this.elementId).closest(\".videotimetabs\")).each(\n function(i, tabs) {\n $(tabs)\n .find('[data-action=\"cue\"]')\n .each(\n async function(index, anchor) {\n let starttime = anchor.getAttribute(\"data-start\"),\n time = starttime.match(\n /((([0-9]+):)?(([0-9]+):))?([0-9]+(\\.[0-9]+))/\n );\n if (time) {\n try {\n await this.player.addCuePoint(\n 3600 * Number(time[3] || 0) +\n 60 * Number(time[5] || 0) +\n Number(time[6]),\n {\n starttime: starttime\n }\n );\n } catch (e) {\n Notification.exception(e);\n }\n }\n }.bind(this)\n );\n\n this.player.on(\"cuepoint\", function(event) {\n if (event.data.starttime) {\n $(tabs)\n .find(\".videotime-highlight\")\n .removeClass(\"videotime-highlight\");\n $(tabs)\n .find(\n '[data-action=\"cue\"][data-start=\"' +\n event.data.starttime +\n '\"]'\n )\n .closest(\".row\")\n .addClass(\"videotime-highlight\");\n $(\".videotime-highlight\").each(function() {\n if (this.offsetTop) {\n this.parentNode.scrollTo({\n top: this.offsetTop - 50,\n left: 0,\n behavior: \"smooth\"\n });\n }\n });\n }\n });\n }.bind(this)\n );\n\n if (!this.player) {\n Log.debug(\n \"Player was not properly initialized for course module \" +\n this.cmId\n );\n return;\n }\n\n // Fire view event in Moodle on first play only.\n this.player.on(\"play\", () => {\n if (!this.played) {\n if (this.hasPro) {\n this.startWatchInterval();\n }\n // Free version can still mark completion on video time view.\n this.view();\n }\n return true;\n });\n\n // Features beyond this point are for pro only.\n if (!this.hasPro) {\n return;\n }\n\n // Note: Vimeo player does not support multiple events in a single on() call. Each requires it's own function.\n\n // Catch all events where video plays.\n this.player.on(\n \"play\",\n function() {\n this.playing = true;\n Log.debug(\"VIDEO_TIME play\");\n }.bind(this)\n );\n this.player.on(\n \"playing\",\n function() {\n this.playing = true;\n Log.debug(\"VIDEO_TIME playing\");\n }.bind(this)\n );\n\n // Catch all events where video stops.\n this.player.on(\n \"pause\",\n function() {\n this.playing = false;\n Log.debug(\"VIDEO_TIME pause\");\n }.bind(this)\n );\n this.player.on(\n \"stalled\",\n function() {\n this.playing = false;\n Log.debug(\"VIDEO_TIME stalled\");\n }.bind(this)\n );\n this.player.on(\n \"suspend\",\n function() {\n this.playing = false;\n Log.debug(\"VIDEO_TIME suspend\");\n }.bind(this)\n );\n this.player.on(\n \"abort\",\n function() {\n this.playing = false;\n Log.debug(\"VIDEO_TIME abort\");\n }.bind(this)\n );\n\n this.player.on(\n \"playbackrateschange\",\n function() {\n this.playbackRate = this.player.playbackRate();\n }.bind(this)\n );\n\n // Always update internal values for percent and current time watched.\n this.player.on(\n \"timeupdate\",\n function() {\n this.currentTime = this.player.currentTime();\n this.percent = this.currentTime / this.player.duration();\n Log.debug(\n \"VIDEO_TIME timeupdate. Percent: \" +\n this.percent +\n \". Current time: \" +\n this.currentTime\n );\n }.bind(this)\n );\n\n // Initiate video finish procedure.\n this.player.on(\"ended\", this.handleEnd.bind(this));\n this.player.on(\"pause\", this.handlePause.bind(this));\n\n // Readjust height when responsive player is resized.\n if (this.player.options().responsive) {\n let observer = new ResizeObserver(() => {\n this.player.height(\n (this.player.videoHeight() / this.player.videoWidth()) *\n this.player.currentWidth()\n );\n });\n observer.observe(document.querySelector(\"#\" + this.elementId));\n }\n }\n\n /**\n * Parse start time and set player\n *\n * @param {string} starttime\n * @returns {Promise}\n */\n async setStartTime(starttime) {\n let time = starttime.match(\n /((([0-9]+):)?(([0-9]+):))?([0-9]+(\\.[0-9]+))/\n );\n if (time) {\n this.resumeTime =\n 3600 * Number(time[3] || 0) +\n 60 * Number(time[5] || 0) +\n Number(time[6]);\n return await this.player.currentTime(this.resumeTime);\n }\n Log.debug(\"Set start time:\" + starttime);\n return await this.player.currentTime();\n }\n\n /**\n * Get play back rate\n *\n * @returns {Promise}\n */\n getDuration() {\n return new Promise(resolve => {\n resolve(this.player.duration());\n return true;\n });\n }\n\n /**\n * Get duration of video\n *\n * @returns {Promise}\n */\n getPlaybackRate() {\n return new Promise(resolve => {\n resolve(this.player.playbackRate());\n return true;\n });\n }\n\n /**\n * Set current time of player\n *\n * @param {float} secs time\n * @returns {Promise}\n */\n setCurrentPosition(secs) {\n return new Promise(resolve => {\n resolve(this.player.currentTime(secs));\n return true;\n });\n }\n\n /**\n * Get current time of player\n *\n * @returns {Promise}\n */\n async getCurrentPosition() {\n let position = await this.player.currentTime();\n this.plugins.forEach(plugin => {\n position = plugin.getCurrentPosition(position);\n });\n return position;\n }\n\n /**\n * Get pause state\n *\n * @return {bool}\n */\n getPaused() {\n const paused = this.player.paused();\n return paused;\n }\n}\n"],"names":["VideoTime","VideoTimeBase","initialize","debug","this","elementId","instance","options","autoplay","Number","controls","sources","type","src","vimeo_url","loop","option_loop","fluid","responsive","playsinline","playbackRates","speed","muted","techOrder","height","width","player","Player","on","resume_playback","resume_time","resumed","duration","getPlayer","resumeTime","Math","floor","setTimeout","setCurrentPosition","handleStartTime","addListeners","i","plugins","length","closest","each","tabs","find","async","index","anchor","starttime","getAttribute","time","match","addCuePoint","e","exception","bind","event","data","removeClass","addClass","offsetTop","parentNode","scrollTo","top","left","behavior","played","hasPro","startWatchInterval","view","playing","playbackRate","currentTime","percent","handleEnd","handlePause","ResizeObserver","videoHeight","videoWidth","currentWidth","observe","document","querySelector","cmId","getDuration","Promise","resolve","getPlaybackRate","secs","position","forEach","plugin","getCurrentPosition","getPaused","paused"],"mappings":";;;;;;;;qTAgBqBA,kBAAkBC,mBACnCC,0BACQC,MAAM,2BAA6BC,KAAKC,iBAEtCC,SAAWF,KAAKE,SAClBC,QAAU,CACNC,SAAUC,OAAOH,SAASE,UAC1BE,SAAUD,OAAOH,SAASI,UAC1BC,QAAS,CAAC,CAACC,KAAMN,SAASM,KAAMC,IAAKP,SAASQ,YAC9CC,KAAMN,OAAOH,SAASU,aACtBC,MAAOR,OAAOH,SAASY,YACvBC,YAAaV,OAAOH,SAASa,aAC7BC,cAAeX,OAAOH,SAASe,OACzB,CAAC,GAAK,IAAM,EAAG,KAAM,IAAK,GAC1B,CAAC,GACPC,MAAOb,OAAOH,SAASgB,QAET,kBAAlBhB,SAASM,OACTL,QAAQgB,UAAY,CAAC,aAEpBd,OAAOH,SAASY,aAAeT,OAAOH,SAASkB,SAAWf,OAAOH,SAASmB,SAC3ElB,QAAQiB,OAASf,OAAOH,SAASkB,QACjCjB,QAAQkB,MAAQhB,OAAOH,SAASmB,qBAEhCtB,MAAM,0DACNA,MAAMI,cACLmB,OAAS,IAAIC,mBAAOvB,KAAKC,UAAWE,cAEpCmB,OAAOE,GAAG,kBAAkB,SACxBtB,SAASuB,iBAAmBvB,SAASwB,aAAe,GAAK1B,KAAK2B,eACxD,MAGPC,SAAW5B,KAAK6B,YAAYD,WAC5BE,WAAa5B,SAASwB,mBAKtBI,WAAa,GAAKC,KAAKC,MAAMJ,yBACzB7B,MACA,0DAEJ+B,WAAa,gBAEb/B,MAAM,0BAA4B6B,uBAClC7B,MAAM,0BAA4B+B,YAClCA,YACAG,YAAW,UACNC,mBAAmBJ,cACrB,KAEA,UAGNK,uBAEAC,mBAEA,IAAIC,EAAI,EAAGA,EAAIrC,KAAKsC,QAAQC,OAAQF,IAAK,CAC3BrC,KAAKsC,QAAQD,GACrBvC,WAAWE,KAAME,iBAGrB,+CAQL,mBAAE,IAAMF,KAAKC,WAAWuC,QAAQ,mBAAmBC,KACjD,SAASJ,EAAGK,0BACNA,MACGC,KAAK,uBACLF,KACGG,eAAeC,MAAOC,YACdC,UAAYD,OAAOE,aAAa,cAChCC,KAAOF,UAAUG,MACb,mDAEJD,eAEUjD,KAAKsB,OAAO6B,YACd,KAAO9C,OAAO4C,KAAK,IAAM,GACrB,GAAK5C,OAAO4C,KAAK,IAAM,GACvB5C,OAAO4C,KAAK,IAChB,CACIF,UAAWA,YAGrB,MAAOK,yBACQC,UAAUD,KAGjCE,KAAKtD,YAGVsB,OAAOE,GAAG,YAAY,SAAS+B,OAC5BA,MAAMC,KAAKT,gCACTL,MACGC,KAAK,wBACLc,YAAY,2CACff,MACGC,KACG,mCACIY,MAAMC,KAAKT,UACX,MAEPP,QAAQ,QACRkB,SAAS,2CACZ,wBAAwBjB,MAAK,WACvBzC,KAAK2D,gBACAC,WAAWC,SAAS,CACrBC,IAAK9D,KAAK2D,UAAY,GACtBI,KAAM,EACNC,SAAU,mBAMhCV,KAAKtD,OAGNA,KAAKsB,gBASLA,OAAOE,GAAG,QAAQ,KACdxB,KAAKiE,SACFjE,KAAKkE,aACAC,0BAGJC,SAEF,KAINpE,KAAKkE,cAOL5C,OAAOE,GACR,OACA,gBACS6C,SAAU,eACXtE,MAAM,oBACZuD,KAAKtD,YAENsB,OAAOE,GACR,UACA,gBACS6C,SAAU,eACXtE,MAAM,uBACZuD,KAAKtD,YAINsB,OAAOE,GACR,QACA,gBACS6C,SAAU,eACXtE,MAAM,qBACZuD,KAAKtD,YAENsB,OAAOE,GACR,UACA,gBACS6C,SAAU,eACXtE,MAAM,uBACZuD,KAAKtD,YAENsB,OAAOE,GACR,UACA,gBACS6C,SAAU,eACXtE,MAAM,uBACZuD,KAAKtD,YAENsB,OAAOE,GACR,QACA,gBACS6C,SAAU,eACXtE,MAAM,qBACZuD,KAAKtD,YAGNsB,OAAOE,GACR,sBACA,gBACS8C,aAAetE,KAAKsB,OAAOgD,gBAClChB,KAAKtD,YAINsB,OAAOE,GACR,aACA,gBACS+C,YAAcvE,KAAKsB,OAAOiD,mBAC1BC,QAAUxE,KAAKuE,YAAcvE,KAAKsB,OAAOM,wBAC1C7B,MACA,mCACIC,KAAKwE,QACL,mBACAxE,KAAKuE,cAEfjB,KAAKtD,YAINsB,OAAOE,GAAG,QAASxB,KAAKyE,UAAUnB,KAAKtD,YACvCsB,OAAOE,GAAG,QAASxB,KAAK0E,YAAYpB,KAAKtD,OAG1CA,KAAKsB,OAAOnB,UAAUW,YAAY,CACnB,IAAI6D,gBAAe,UACzBrD,OAAOF,OACPpB,KAAKsB,OAAOsD,cAAgB5E,KAAKsB,OAAOuD,aACrC7E,KAAKsB,OAAOwD,mBAGfC,QAAQC,SAASC,cAAc,IAAMjF,KAAKC,+BA1G/CF,MACA,yDACIC,KAAKkF,yBAkHFnC,eACXE,KAAOF,UAAUG,MACjB,uDAEAD,WACKnB,WACD,KAAOzB,OAAO4C,KAAK,IAAM,GACzB,GAAK5C,OAAO4C,KAAK,IAAM,GACvB5C,OAAO4C,KAAK,UACHjD,KAAKsB,OAAOiD,YAAYvE,KAAK8B,2BAE1C/B,MAAM,kBAAoBgD,iBACjB/C,KAAKsB,OAAOiD,eAQ7BY,qBACW,IAAIC,SAAQC,UACfA,QAAQrF,KAAKsB,OAAOM,aACb,KASf0D,yBACW,IAAIF,SAAQC,UACfA,QAAQrF,KAAKsB,OAAOgD,iBACb,KAUfpC,mBAAmBqD,aACR,IAAIH,SAAQC,UACfA,QAAQrF,KAAKsB,OAAOiD,YAAYgB,QACzB,oCAUPC,eAAiBxF,KAAKsB,OAAOiD,0BAC5BjC,QAAQmD,SAAQC,SACjBF,SAAWE,OAAOC,mBAAmBH,aAElCA,SAQXI,mBACmB5F,KAAKsB,OAAOuE"} \ No newline at end of file diff --git a/plugin/videojs/amd/src/videotime.js b/plugin/videojs/amd/src/videotime.js index 18c44698..dc312a08 100644 --- a/plugin/videojs/amd/src/videotime.js +++ b/plugin/videojs/amd/src/videotime.js @@ -237,7 +237,7 @@ export default class VideoTime extends VideoTimeBase { // Initiate video finish procedure. this.player.on("ended", this.handleEnd.bind(this)); - this.player.on("pause", this.handleEnd.bind(this)); + this.player.on("pause", this.handlePause.bind(this)); // Readjust height when responsive player is resized. if (this.player.options().responsive) {