From cdcbe6b67fba6e18d938f705fde7bb663b160483 Mon Sep 17 00:00:00 2001 From: Shadman Date: Fri, 7 Jan 2022 20:30:45 +0600 Subject: [PATCH 1/3] Add latest video tracking code --- amd/build/brightcove.min.js | 2 +- amd/build/brightcove.min.js.map | 2 +- amd/src/brightcove.js | 77 +++++++++++------- .../moodle2/backup_html5player_stepslib.php | 35 ++++++-- .../moodle2/restore_html5player_stepslib.php | 32 ++++++++ classes/external.php | 2 +- db/install.xml | 6 +- db/upgrade.php | 30 ++++++- lang/en/html5player.php | 4 + lib.php | 11 +-- locallib.php | 79 +++++++++++++------ settings.php | 4 + version.php | 2 +- 13 files changed, 204 insertions(+), 82 deletions(-) diff --git a/amd/build/brightcove.min.js b/amd/build/brightcove.min.js index 80beb79..30dc679 100644 --- a/amd/build/brightcove.min.js +++ b/amd/build/brightcove.min.js @@ -1,2 +1,2 @@ -define ("mod_html5player/brightcove",["jquery","core/ajax"],function(a,b){var c,d,e=function(a,b){window.require.config({paths:{bc:"https://players.brightcove.net/".concat(a,"/").concat(b,"_default/index.min")},waitSeconds:30})},f=function(a){return{setSource:function(a,b){b(null,a)},setCurrentTime:function(b){var c=100*(a.currentTime()/a.duration());if(b50){return b}return a.currentTime()}}},g=function(a,b){var d=b.cmid,e=b.video_id;a.on("play",function(){e=a.mediainfo.id;console.info("Video: ".concat(a.mediainfo.id," started playing..."));c=a.setInterval(function(){var c=Math.ceil(a.currentTime());console.log("Video playing. Total length: ".concat(a.duration(),". Video current progress is : ").concat(a.currentTime()));i(b,d,e,c)},+b.progress_interval)});a.on("pause",function(){a.clearInterval(c)})},h=function(a,b){var c=null===b||void 0===b?void 0:b.progress;if(c){var d=a.duration(),e=Math.floor(c)/1e3;console.info("Duration is: ".concat(d," and Video progress is ").concat(e," seconds"));if(d>=e){a.currentTime(e)}}else{console.info("Video progress is ".concat(c))}},i=function(a,c,d,e){var f=4 Switching to new video ...");a.clearInterval(c)});a.on("ended",function(){var d=Math.ceil(a.duration());console.log("Video ended...");i(b,b.cmid,a.mediainfo.id,d,!0);a.clearInterval(c);var e=a.playlist.next();console.info("Start playing to next video : ".concat(e.id))})};return{init:function initBrightCovePlayer(a){a=JSON.parse(a);e(a.account_id,a.player_id);require(["bc"],function(){videojs.use("*",f);console.info("Brightcove player js loaded...");if(a.is_student){var b=videojs.getPlayer("brightcove-player-".concat(a.player_id));if(a.video_type==1){console.info("User is a student and Video type single video...");l(b,a);m(b,a)}else if(a.video_type==2){console.info("User is a student and Video type playlists video...");n(b,a);d=!0;o(b,a)}}})}}}); +define ("mod_html5player/brightcove",["jquery","core/ajax"],function(a,b){var c,d,e=function(a,b){window.require.config({paths:{bc:"https://players.brightcove.net/".concat(a,"/").concat(b,"_default/index.min")},waitSeconds:30})},f=function(a){var b=document.getElementById("btn-completion");if(b){b.disabled=!a}},g=function(a,b){var d=b.cmid,e=b.video_id;a.on("play",function(){e=a.mediainfo.id;console.info("Video: ".concat(a.mediainfo.id," started playing..."));c=a.setInterval(function(){var c=Math.ceil(a.currentTime());console.log("Video playing. Total length: ".concat(a.duration(),". Video current progress is : ").concat(a.currentTime()));i(b,d,e,c)},+b.progress_interval)});a.on("pause",function(){a.clearInterval(c)})},h=function(a,b){var c=null===b||void 0===b?void 0:b.progress;if(c){var d=a.duration(),e=Math.floor(c)/1e3;console.info("Duration is: ".concat(d," and Video progress is ").concat(e," seconds"));if(d>=e){a.currentTime(e)}else{f(!1)}}else{console.info("Video progress is ".concat(c))}},i=function(a,c,d,e){var f=4 Switching to new video ...");a.clearInterval(c)});a.on("ended",function(){var d=Math.ceil(a.duration());console.log("Video ended...");i(b,b.cmid,a.mediainfo.id,d,!0);a.clearInterval(c);var e=a.playlist.next();console.info("Start playing to next video : ".concat(e.id))})};return{init:function initBrightCovePlayer(a){a=JSON.parse(a);f(!1);e(a.account_id,a.player_id);require(["bc"],function(){console.info("Brightcove player js loaded...");if(a.is_student){var b=videojs.getPlayer("brightcove-player-".concat(a.player_id));if(a.video_type==1){console.info("User is a student and Video type single video...");l(b,a);f(!1);m(b,a)}else if(a.video_type==2){console.info("User is a student and Video type playlists video...");n(b,a);d=!0;o(b,a)}}})}}}); //# sourceMappingURL=brightcove.min.js.map diff --git a/amd/build/brightcove.min.js.map b/amd/build/brightcove.min.js.map index 544d6c5..64f216e 100644 --- a/amd/build/brightcove.min.js.map +++ b/amd/build/brightcove.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/brightcove.js"],"names":["define","$","Ajax","interval","onPageLoaded","loadBrightCoveJs","accountId","playerId","window","require","config","waitSeconds","disableForwardScrubbing","player","setSource","srcObj","next","setCurrentTime","ct","percentPlayed","currentTime","duration","html5PlayerGenericPlayerEventListener","html5player","cm","cmid","video_id","on","mediainfo","id","console","info","setInterval","Math","ceil","log","set_course_module_progress","progress_interval","clearInterval","html5playerSetProgress","results","progress","floor","videoid","ended","promise","call","methodname","args","then","completed","toggledEvent","CustomEvent","bubbles","detail","activityname","name","withAvailability","document","dispatchEvent","fail","e","get_single_video_course_module_progress","get_playlist_video_progress","response","progresses","length","playlists","playlist","result","index","findIndex","video","currentItem","currentItemIndex","find","html5playerOnLoadSingleVideoMetaData","html5playerOnPlaySingleVideo","html5playerOnLoadPlaylistMetaData","html5playerOnPlayPlaylist","nextVideo","init","initBrightCovePlayer","JSON","parse","account_id","player_id","videojs","use","is_student","myPlayer","getPlayer","video_type"],"mappings":"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","sourcesContent":["define(['jquery','core/ajax'], function ($, Ajax) {\n\n let interval;\n\n let onPageLoaded;\n\n const VIDEO_TYPE_SINGLE_VIDEO = 1;\n\n const VIDEO_TYPE_PLAYLIST = 2;\n\n /**\n * Load brightcove player javascript.\n * @param accountId\n * @param playerId\n */\n const loadBrightCoveJs = (accountId, playerId) => {\n window.require.config({\n 'paths': {\n 'bc': `https://players.brightcove.net/${accountId}/${playerId}_default/index.min`\n },\n waitSeconds: 30\n });\n }\n\n const disableForwardScrubbing = function(player) {\n return {\n // +++ Implement setSource() +++\n setSource: function setSource(srcObj, next) {\n next(null, srcObj);\n },\n // +++ Alter the setCurrentTime method +++\n setCurrentTime: function setCurrentTime(ct) {\n const percentAllowForward = 50,\n // Determine percentage of video played\n percentPlayed = player.currentTime() / player.duration() * 100;\n // Check if the time scrubbed to is less than the current time\n // or if passed scrub forward percentage\n if ( ct < player.currentTime() || percentPlayed > percentAllowForward ) {\n // If true, move playhead to desired time\n return ct;\n }\n // If time scrubbed to is past current time and not passed percentage\n // leave playhead at current time\n return player.currentTime();\n }\n }\n };\n\n /**\n * Common event listener for brightcove Player.\n * @param player\n * @param html5player\n */\n const html5PlayerGenericPlayerEventListener = (player, html5player) => {\n const cm = html5player.cmid;\n let video_id = html5player.video_id;\n\n player.on('play',(e)=> {\n video_id = player.mediainfo.id;\n console.info(`Video: ${player.mediainfo.id} started playing...`)\n interval = player.setInterval(function(){\n const currentTime = Math.ceil(player.currentTime());\n console.log(`Video playing. Total length: ${player.duration()}. Video current progress is : ${player.currentTime()}`)\n set_course_module_progress(html5player, cm,video_id,currentTime)\n }, +html5player.progress_interval);\n\n })\n\n player.on('pause',(e)=>{\n player.clearInterval(interval);\n })\n }\n\n /**\n * @param player\n * @param results\n */\n const html5playerSetProgress = (player, results) => {\n let progress = results?.progress\n if (progress){\n const duration = player.duration();\n const currentTime = Math.floor(progress) / 1000;\n console.info(`Duration is: ${duration} and Video progress is ${currentTime} seconds`);\n if(duration >= currentTime){\n player.currentTime(currentTime);\n }\n // else {\n // player.currentTime(duration - 1);\n // }\n }else {\n console.info(`Video progress is ${progress}`);\n }\n }\n\n /**\n * Set course module video progress\n * @param id\n * @param videoid\n * @param progress\n * @param ended\n */\n const set_course_module_progress = (html5player, id, videoid, progress, ended=false) => {\n let promise;\n\n promise = Ajax.call([{\n methodname: 'mod_html5player_set_module_progress',\n args: {\n id, // course module id.\n videoid, // Brightcove video id.\n progress, // Progress percentage\n ended, // Progress percentage\n }\n }]);\n\n promise[0].then(function(results) {\n console.info(`Video completed : ${results.completed}`);\n if (results.completed) {\n const toggledEvent = new CustomEvent('core_course:html5player_view_completed', {\n bubbles: true,\n detail: {\n id: id,\n activityname: html5player.name,\n completed: results.completed,\n withAvailability: '',\n }\n });\n // Dispatch the manualCompletionToggled custom event.\n document.dispatchEvent(toggledEvent);\n }\n\n }).fail((e) => {\n console.log(e)\n });\n }\n\n /**\n * Get course module single video progress.\n * @param player\n * @param html5player\n */\n const get_single_video_course_module_progress = (player, html5player) => {\n let promise;\n\n console.info(`Geting course video progress from store...`)\n promise = Ajax.call([{\n methodname: 'mod_html5player_get_module_progress',\n args: {\n id: html5player.cmid, // course module id.\n videoid: html5player.video_id, // html5videos table PK.\n }\n }]);\n\n promise[0].then(function(results) {\n console.info(`Fetched result from store`);\n html5playerSetProgress(player, results);\n }).fail((e) => {\n console.log(e)\n });\n }\n\n /**\n * Get course module single video progress.\n * @param player\n * @param html5player\n */\n const get_playlist_video_progress = (player, html5player) => {\n let promise;\n\n console.info(`Getting course video progresses from store...`)\n promise = Ajax.call([{\n methodname: 'mod_html5player_get_module_progresses',\n args: {\n id: html5player.cmid, // course module id.\n }\n }]);\n\n promise[0].then(function(response) {\n console.info(`Fetched module progresses result from store`);\n if (response.progresses?.length > 0){\n const playlists = player.playlist();\n let result;\n if (onPageLoaded){\n console.info('Current item progress set after first time dom load...');\n result = response.progresses[0];\n const index = playlists.findIndex(video => video.id == result.video_id);\n if (index>=0){\n player.playlist.currentItem(index);\n html5playerSetProgress(player, result);\n onPageLoaded = false;\n }\n }else {\n const currentItemIndex = player.playlist.currentItem();\n const currentItem = playlists[currentItemIndex]\n result = response.progresses.find(video => video.video_id == currentItem.id )\n html5playerSetProgress(player, result);\n }\n\n }\n }).fail((e) => {\n console.log(e)\n });\n }\n\n /**\n * On Load meta data event and listener\n * @param player\n * @param html5player\n */\n const html5playerOnLoadSingleVideoMetaData = (player, html5player) => {\n player.on('loadedmetadata', function(e){\n console.info('Single video player meta data loaded...')\n get_single_video_course_module_progress(player,html5player);\n });\n }\n\n /**\n * Event listener for single video.\n * @param player\n * @param html5player\n */\n const html5playerOnPlaySingleVideo = (player,html5player) => {\n html5PlayerGenericPlayerEventListener(player, html5player);\n\n player.on('ended',(e)=>{\n const currentTime = Math.ceil( player.duration());\n console.log(`Video ended... Video id: ${player.mediainfo.id}, Duration: ${player.duration()}`)\n set_course_module_progress(html5player, html5player.cmid,html5player.video_id,currentTime,true)\n player.clearInterval(interval);\n })\n }\n\n /**\n * On load playlists meta data\n * @param player\n * @param html5player\n * @param onpageload\n */\n const html5playerOnLoadPlaylistMetaData = (player, html5player) => {\n player.on('loadedmetadata',(e) => {\n console.info('playlist videos player meta data loaded...');\n get_playlist_video_progress(player, html5player);\n });\n }\n\n /**\n * Event listener for playlist.\n * @param player\n * @param html5player\n */\n const html5playerOnPlayPlaylist = (player, html5player) => {\n html5PlayerGenericPlayerEventListener(player, html5player);\n player.on('beforeplaylistitem', e => {\n console.log(`Event: beforeplaylistitem -> Switching to new video ...`);\n player.clearInterval(interval) ;\n });\n\n player.on('ended',(e)=>{\n const currentTime = Math.ceil( player.duration());\n console.log(`Video ended...`)\n set_course_module_progress(html5player, html5player.cmid,player.mediainfo.id,currentTime, true)\n player.clearInterval(interval);\n const nextVideo = player.playlist.next();\n console.info(`Start playing to next video : ${nextVideo.id}`)\n })\n }\n\n // const initBrightCovePlayer = (course, cm, accountId, playerId, video_id) => {\n const initBrightCovePlayer = (html5player) => {\n html5player = JSON.parse(html5player);\n // Make brightcove js in Require js module as bc.\n loadBrightCoveJs(html5player.account_id, html5player.player_id);\n\n require(['bc'], function(bc) {\n\n // Register the middleware with the player\n videojs.use('*', disableForwardScrubbing);\n\n console.info(`Brightcove player js loaded...`);\n // Tracking is enabled for only student.\n if (html5player.is_student ){\n const myPlayer = videojs.getPlayer(`brightcove-player-${html5player.player_id}`);\n\n if (html5player.video_type == VIDEO_TYPE_SINGLE_VIDEO){\n // Do meta loaded stuffs here.\n console.info('User is a student and Video type single video...');\n html5playerOnLoadSingleVideoMetaData(myPlayer, html5player);\n // Do Start playing stuffs here.\n html5playerOnPlaySingleVideo(myPlayer,html5player);\n }else if( html5player.video_type == VIDEO_TYPE_PLAYLIST) {\n console.info('User is a student and Video type playlists video...');\n html5playerOnLoadPlaylistMetaData(myPlayer, html5player);\n onPageLoaded = true;\n html5playerOnPlayPlaylist(myPlayer, html5player);\n }\n }\n });\n }\n\n return {\n init: initBrightCovePlayer\n }\n});"],"file":"brightcove.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/brightcove.js"],"names":["define","$","Ajax","interval","onPageLoaded","loadBrightCoveJs","accountId","playerId","window","require","config","waitSeconds","disableCompletionButton","isCompleteAble","markCompleteBtn","document","getElementById","disabled","html5PlayerGenericPlayerEventListener","player","html5player","cm","cmid","video_id","on","mediainfo","id","console","info","setInterval","currentTime","Math","ceil","log","duration","set_course_module_progress","progress_interval","clearInterval","html5playerSetProgress","results","progress","floor","videoid","ended","promise","call","methodname","args","then","completed","toggledEvent","CustomEvent","bubbles","detail","activityname","name","withAvailability","dispatchEvent","fail","e","get_single_video_course_module_progress","get_playlist_video_progress","response","progresses","length","playlists","playlist","result","index","findIndex","video","currentItem","currentItemIndex","find","html5playerOnLoadSingleVideoMetaData","forwardscrubbing","css","html5playerOnPlaySingleVideo","html5playerOnLoadPlaylistMetaData","html5playerOnPlayPlaylist","nextVideo","next","init","initBrightCovePlayer","JSON","parse","account_id","player_id","is_student","myPlayer","videojs","getPlayer","video_type"],"mappings":"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","sourcesContent":["define(['jquery','core/ajax'], function ($, Ajax) {\n\n let interval;\n\n let onPageLoaded;\n\n const VIDEO_TYPE_SINGLE_VIDEO = 1;\n\n const VIDEO_TYPE_PLAYLIST = 2;\n\n /**\n * Load brightcove player javascript.\n * @param accountId\n * @param playerId\n */\n const loadBrightCoveJs = (accountId, playerId) => {\n window.require.config({\n 'paths': {\n 'bc': `https://players.brightcove.net/${accountId}/${playerId}_default/index.min`\n },\n waitSeconds: 30\n });\n }\n \n const disableCompletionButton = (isCompleteAble) => {\n const markCompleteBtn = document.getElementById('btn-completion');\n if (markCompleteBtn){\n markCompleteBtn.disabled = !isCompleteAble;\n }\n\n }\n\n // const disableForwardScrubbing = function(player) {\n // return {\n // // +++ Implement setSource() +++\n // setSource: function setSource(srcObj, next) {\n // next(null, srcObj);\n // },\n // // +++ Alter the setCurrentTime method +++\n // setCurrentTime: function setCurrentTime(ct) {\n // const percentAllowForward = 95,\n // // Determine percentage of video played\n // percentPlayed = player.currentTime() / player.duration() * 100;\n // // Check if the time scrubbed to is less than the current time\n // // or if passed scrub forward percentage\n // if ( ct < player.currentTime() || percentPlayed > percentAllowForward ) {\n // // If true, move playhead to desired time\n // return ct;\n // }\n // // If time scrubbed to is past current time and not passed percentage\n // // leave playhead at current time\n // return player.currentTime();\n // }\n // }\n // };\n\n /**\n * Common event listener for brightcove Player.\n * @param player\n * @param html5player\n */\n const html5PlayerGenericPlayerEventListener = (player, html5player) => {\n const cm = html5player.cmid;\n let video_id = html5player.video_id;\n\n player.on('play',(e)=> {\n video_id = player.mediainfo.id;\n console.info(`Video: ${player.mediainfo.id} started playing...`)\n interval = player.setInterval(function(){\n const currentTime = Math.ceil(player.currentTime());\n console.log(`Video playing. Total length: ${player.duration()}. Video current progress is : ${player.currentTime()}`)\n set_course_module_progress(html5player, cm,video_id,currentTime)\n }, +html5player.progress_interval);\n\n })\n\n player.on('pause',(e)=>{\n player.clearInterval(interval);\n })\n }\n\n /**\n * @param player\n * @param results\n */\n const html5playerSetProgress = (player, results) => {\n let progress = results?.progress\n if (progress){\n const duration = player.duration();\n const currentTime = Math.floor(progress) / 1000;\n console.info(`Duration is: ${duration} and Video progress is ${currentTime} seconds`);\n if(duration >= currentTime){\n player.currentTime(currentTime);\n }\n else {\n disableCompletionButton(false);\n }\n }else {\n console.info(`Video progress is ${progress}`);\n }\n }\n\n /**\n * Set course module video progress\n * @param id\n * @param videoid\n * @param progress\n * @param ended\n */\n const set_course_module_progress = (html5player, id, videoid, progress, ended=false) => {\n let promise;\n\n promise = Ajax.call([{\n methodname: 'mod_html5player_set_module_progress',\n args: {\n id, // course module id.\n videoid, // Brightcove video id.\n progress, // Progress percentage\n ended, // Progress percentage\n }\n }]);\n\n promise[0].then(function(results) {\n console.info(`Video completed : ${results.completed}`);\n if (results.completed) {\n const toggledEvent = new CustomEvent('core_course:html5player_view_completed', {\n bubbles: true,\n detail: {\n id: id,\n activityname: html5player.name,\n completed: results.completed,\n withAvailability: '',\n }\n });\n // Dispatch the manualCompletionToggled custom event.\n document.dispatchEvent(toggledEvent);\n }\n\n }).fail((e) => {\n console.log(e)\n });\n }\n\n /**\n * Get course module single video progress.\n * @param player\n * @param html5player\n */\n const get_single_video_course_module_progress = (player, html5player) => {\n let promise;\n\n console.info(`Geting course video progress from store...`)\n promise = Ajax.call([{\n methodname: 'mod_html5player_get_module_progress',\n args: {\n id: html5player.cmid, // course module id.\n videoid: html5player.video_id, // html5player_html5videos table PK.\n }\n }]);\n\n promise[0].then(function(results) {\n console.info(`Fetched result from store`);\n html5playerSetProgress(player, results);\n }).fail((e) => {\n console.log(e)\n });\n }\n\n /**\n * Get course module single video progress.\n * @param player\n * @param html5player\n */\n const get_playlist_video_progress = (player, html5player) => {\n let promise;\n\n console.info(`Getting course video progresses from store...`)\n promise = Ajax.call([{\n methodname: 'mod_html5player_get_module_progresses',\n args: {\n id: html5player.cmid, // course module id.\n }\n }]);\n\n promise[0].then(function(response) {\n console.info(`Fetched module progresses result from store`);\n if (response.progresses?.length > 0){\n const playlists = player.playlist();\n let result;\n if (onPageLoaded){\n console.info('Current item progress set after first time dom load...');\n result = response.progresses[0];\n const index = playlists.findIndex(video => video.id == result.video_id);\n if (index>=0){\n player.playlist.currentItem(index);\n html5playerSetProgress(player, result);\n onPageLoaded = false;\n }\n }else {\n const currentItemIndex = player.playlist.currentItem();\n const currentItem = playlists[currentItemIndex]\n result = response.progresses.find(video => video.video_id == currentItem.id )\n html5playerSetProgress(player, result);\n }\n\n }\n }).fail((e) => {\n console.log(e)\n });\n }\n\n /**\n * On Load meta data event and listener\n * @param player\n * @param html5player\n */\n const html5playerOnLoadSingleVideoMetaData = (player, html5player) => {\n player.on('loadedmetadata', function(e){\n console.info('Single video player meta data loaded...')\n get_single_video_course_module_progress(player,html5player);\n console.log(html5player.forwardscrubbing);\n if (+html5player.forwardscrubbing){\n console.info('Forward scrubbing enabled. Progress control disabling using css...');\n $(\".vjs-progress-control\").css('pointer-events','none');\n }\n });\n }\n\n /**\n * Event listener for single video.\n * @param player\n * @param html5player\n */\n const html5playerOnPlaySingleVideo = (player,html5player) => {\n html5PlayerGenericPlayerEventListener(player, html5player);\n\n player.on('ended',(e)=>{\n const currentTime = Math.ceil( player.duration());\n console.log(`Video ended... Video id: ${player.mediainfo.id}, Duration: ${player.duration()}`);\n set_course_module_progress(html5player, html5player.cmid,html5player.video_id,currentTime,true)\n player.clearInterval(interval);\n // if (!html5player.cmcompleted){\n // disableCompletionButton(true);\n // }\n })\n }\n\n /**\n * On load playlists meta data\n * @param player\n * @param html5player\n */\n const html5playerOnLoadPlaylistMetaData = (player, html5player) => {\n player.on('loadedmetadata',(e) => {\n console.info('playlist videos player meta data loaded...');\n get_playlist_video_progress(player, html5player);\n });\n }\n\n /**\n * Event listener for playlist.\n * @param player\n * @param html5player\n */\n const html5playerOnPlayPlaylist = (player, html5player) => {\n html5PlayerGenericPlayerEventListener(player, html5player);\n player.on('beforeplaylistitem', e => {\n console.log(`Event: beforeplaylistitem -> Switching to new video ...`);\n player.clearInterval(interval) ;\n });\n\n player.on('ended',(e)=>{\n const currentTime = Math.ceil( player.duration());\n console.log(`Video ended...`)\n set_course_module_progress(html5player, html5player.cmid,player.mediainfo.id,currentTime, true)\n player.clearInterval(interval);\n const nextVideo = player.playlist.next();\n console.info(`Start playing to next video : ${nextVideo.id}`)\n })\n }\n\n // const initBrightCovePlayer = (course, cm, accountId, playerId, video_id) => {\n const initBrightCovePlayer = (html5player) => {\n html5player = JSON.parse(html5player);\n disableCompletionButton(false);\n // Make brightcove js in Require js module as bc.\n loadBrightCoveJs(html5player.account_id, html5player.player_id);\n\n require(['bc'], function(bc) {\n\n // Register the middleware with the player\n //videojs.use('*', disableForwardScrubbing);\n\n console.info(`Brightcove player js loaded...`);\n // Tracking is enabled for only student.\n if (html5player.is_student ){\n const myPlayer = videojs.getPlayer(`brightcove-player-${html5player.player_id}`);\n\n if (html5player.video_type == VIDEO_TYPE_SINGLE_VIDEO){\n // Do meta loaded stuffs here.\n console.info('User is a student and Video type single video...');\n html5playerOnLoadSingleVideoMetaData(myPlayer, html5player);\n disableCompletionButton(false);\n // Do Start playing stuffs here.\n html5playerOnPlaySingleVideo(myPlayer,html5player);\n }else if( html5player.video_type == VIDEO_TYPE_PLAYLIST) {\n console.info('User is a student and Video type playlists video...');\n html5playerOnLoadPlaylistMetaData(myPlayer, html5player);\n onPageLoaded = true;\n html5playerOnPlayPlaylist(myPlayer, html5player);\n }\n }\n });\n }\n\n return {\n init: initBrightCovePlayer\n }\n});"],"file":"brightcove.min.js"} \ No newline at end of file diff --git a/amd/src/brightcove.js b/amd/src/brightcove.js index 6596ed2..acef7da 100644 --- a/amd/src/brightcove.js +++ b/amd/src/brightcove.js @@ -21,30 +21,38 @@ define(['jquery','core/ajax'], function ($, Ajax) { waitSeconds: 30 }); } - - const disableForwardScrubbing = function(player) { - return { - // +++ Implement setSource() +++ - setSource: function setSource(srcObj, next) { - next(null, srcObj); - }, - // +++ Alter the setCurrentTime method +++ - setCurrentTime: function setCurrentTime(ct) { - const percentAllowForward = 50, - // Determine percentage of video played - percentPlayed = player.currentTime() / player.duration() * 100; - // Check if the time scrubbed to is less than the current time - // or if passed scrub forward percentage - if ( ct < player.currentTime() || percentPlayed > percentAllowForward ) { - // If true, move playhead to desired time - return ct; - } - // If time scrubbed to is past current time and not passed percentage - // leave playhead at current time - return player.currentTime(); - } + + const disableCompletionButton = (isCompleteAble) => { + const markCompleteBtn = document.getElementById('btn-completion'); + if (markCompleteBtn){ + markCompleteBtn.disabled = !isCompleteAble; } - }; + + } + + // const disableForwardScrubbing = function(player) { + // return { + // // +++ Implement setSource() +++ + // setSource: function setSource(srcObj, next) { + // next(null, srcObj); + // }, + // // +++ Alter the setCurrentTime method +++ + // setCurrentTime: function setCurrentTime(ct) { + // const percentAllowForward = 95, + // // Determine percentage of video played + // percentPlayed = player.currentTime() / player.duration() * 100; + // // Check if the time scrubbed to is less than the current time + // // or if passed scrub forward percentage + // if ( ct < player.currentTime() || percentPlayed > percentAllowForward ) { + // // If true, move playhead to desired time + // return ct; + // } + // // If time scrubbed to is past current time and not passed percentage + // // leave playhead at current time + // return player.currentTime(); + // } + // } + // }; /** * Common event listener for brightcove Player. @@ -84,9 +92,9 @@ define(['jquery','core/ajax'], function ($, Ajax) { if(duration >= currentTime){ player.currentTime(currentTime); } - // else { - // player.currentTime(duration - 1); - // } + else { + disableCompletionButton(false); + } }else { console.info(`Video progress is ${progress}`); } @@ -146,7 +154,7 @@ define(['jquery','core/ajax'], function ($, Ajax) { methodname: 'mod_html5player_get_module_progress', args: { id: html5player.cmid, // course module id. - videoid: html5player.video_id, // html5videos table PK. + videoid: html5player.video_id, // html5player_html5videos table PK. } }]); @@ -210,6 +218,11 @@ define(['jquery','core/ajax'], function ($, Ajax) { player.on('loadedmetadata', function(e){ console.info('Single video player meta data loaded...') get_single_video_course_module_progress(player,html5player); + console.log(html5player.forwardscrubbing); + if (+html5player.forwardscrubbing){ + console.info('Forward scrubbing enabled. Progress control disabling using css...'); + $(".vjs-progress-control").css('pointer-events','none'); + } }); } @@ -223,9 +236,12 @@ define(['jquery','core/ajax'], function ($, Ajax) { player.on('ended',(e)=>{ const currentTime = Math.ceil( player.duration()); - console.log(`Video ended... Video id: ${player.mediainfo.id}, Duration: ${player.duration()}`) + console.log(`Video ended... Video id: ${player.mediainfo.id}, Duration: ${player.duration()}`); set_course_module_progress(html5player, html5player.cmid,html5player.video_id,currentTime,true) player.clearInterval(interval); + // if (!html5player.cmcompleted){ + // disableCompletionButton(true); + // } }) } @@ -233,7 +249,6 @@ define(['jquery','core/ajax'], function ($, Ajax) { * On load playlists meta data * @param player * @param html5player - * @param onpageload */ const html5playerOnLoadPlaylistMetaData = (player, html5player) => { player.on('loadedmetadata',(e) => { @@ -267,13 +282,14 @@ define(['jquery','core/ajax'], function ($, Ajax) { // const initBrightCovePlayer = (course, cm, accountId, playerId, video_id) => { const initBrightCovePlayer = (html5player) => { html5player = JSON.parse(html5player); + disableCompletionButton(false); // Make brightcove js in Require js module as bc. loadBrightCoveJs(html5player.account_id, html5player.player_id); require(['bc'], function(bc) { // Register the middleware with the player - videojs.use('*', disableForwardScrubbing); + //videojs.use('*', disableForwardScrubbing); console.info(`Brightcove player js loaded...`); // Tracking is enabled for only student. @@ -284,6 +300,7 @@ define(['jquery','core/ajax'], function ($, Ajax) { // Do meta loaded stuffs here. console.info('User is a student and Video type single video...'); html5playerOnLoadSingleVideoMetaData(myPlayer, html5player); + disableCompletionButton(false); // Do Start playing stuffs here. html5playerOnPlaySingleVideo(myPlayer,html5player); }else if( html5player.video_type == VIDEO_TYPE_PLAYLIST) { diff --git a/backup/moodle2/backup_html5player_stepslib.php b/backup/moodle2/backup_html5player_stepslib.php index 8775c22..1bad6db 100644 --- a/backup/moodle2/backup_html5player_stepslib.php +++ b/backup/moodle2/backup_html5player_stepslib.php @@ -39,25 +39,46 @@ protected function define_structure() { $userinfo = $this->get_setting_value('userinfo'); // Define each element separated - $page = new backup_nested_element('html5player', array('id'), array( + $html5player = new backup_nested_element('html5player', array('id'), array( 'name', 'display', 'displayoptions', 'tobemigrated', 'intro', 'introformat','meta_info', 'account_id', 'player_id', 'video_type', 'video_id','playlist_id','sizing','aspect_ratio','units','width','height' )); - // Build the tree - // (love this) + $html5videos = new backup_nested_element('html5videos'); + + $html5video = new backup_nested_element('html5video', array('id'), array( + 'html5player', 'video_id', 'poster', 'thumbnail', 'duration', 'timecreated', 'timemodified')); + + $html5trackings = new backup_nested_element('html5trackings'); + + $html5tracking = new backup_nested_element('html5tracking', array('id'), array( + 'html5player', 'html5video', 'user', 'progress', 'timecreated', 'timemodified')); + + + // Build the tree. + + $html5player->add_child($html5videos); + $html5videos->add_child($html5video); + + $html5player->add_child($html5trackings); + $html5trackings->add_child($html5tracking); + // Define sources - $page->set_source_table('html5player', array('id' => backup::VAR_ACTIVITYID)); + $html5player->set_source_table('html5player', array('id' => backup::VAR_ACTIVITYID)); + $html5video->set_source_table('html5player_html5videos', array('html5player' => backup::VAR_PARENTID)); + if($userinfo) { + $html5tracking->set_source_table('html5player_html5trackings', array('html5player' => '../../id')); + } // Define id annotations // (none) // Define file annotations - $page->annotate_files('mod_html5player', 'intro', null); // This file areas haven't itemid - $page->annotate_files('mod_html5player', 'content', null); // This file areas haven't itemid + $html5player->annotate_files('mod_html5player', 'intro', null); // This file areas haven't itemid + $html5player->annotate_files('mod_html5player', 'content', null); // This file areas haven't itemid // Return the root element (html5player), wrapped into standard activity structure - return $this->prepare_activity_structure($page); + return $this->prepare_activity_structure($html5player); } } diff --git a/backup/moodle2/restore_html5player_stepslib.php b/backup/moodle2/restore_html5player_stepslib.php index 3204e27..1d32074 100644 --- a/backup/moodle2/restore_html5player_stepslib.php +++ b/backup/moodle2/restore_html5player_stepslib.php @@ -34,7 +34,13 @@ class restore_html5player_activity_structure_step extends restore_activity_struc protected function define_structure() { $paths = array(); + $userinfo = $this->get_setting_value('userinfo'); + $paths[] = new restore_path_element('html5player', '/activity/html5player'); + $paths[] = new restore_path_element('html5player_html5videos', '/activity/html5player/html5videos/html5video'); + if ($userinfo) { + $paths[] = new restore_path_element('html5player_html5trackings', '/activity/html5player/html5trackings/html5tracking'); + } // Return the paths wrapped into standard activity structure return $this->prepare_activity_structure($paths); @@ -56,6 +62,32 @@ protected function process_html5player($data) { $this->apply_activity_instance($newitemid); } + protected function process_html5player_html5videos($data) { + global $DB; + + $data = (object)$data; + $oldid = $data->id; + + $data->html5player = $this->get_new_parentid('html5player'); + + $newitemid = $DB->insert_record('html5player_html5videos', $data); + $this->set_mapping('html5player_html5video', $oldid, $newitemid); + } + + protected function process_html5player_html5trackings($data) { + global $DB; + + $data = (object)$data; + + $data->html5player = $this->get_new_parentid('html5player'); + $data->html5videoid = $this->get_mappingid('html5player_html5video', $data->optionid); + $data->user = $this->get_mappingid('user', $data->user); + + $newitemid = $DB->insert_record('html5player_html5trackings', $data); + // No need to save this mapping as far as nothing depend on it + // (child paths, file areas nor links decoder) + } + protected function after_execute() { // Add html5player related files, no need to match by itemname (just internally handled context) $this->add_related_files('mod_html5player', 'intro', null); diff --git a/classes/external.php b/classes/external.php index 502abf5..0c192a2 100644 --- a/classes/external.php +++ b/classes/external.php @@ -225,7 +225,7 @@ public static function html5player_get_progresses(int $id) $html5player = html5player_get_html5player_from_cm($id); $params['html5player'] = $html5player->id; $sql = "SELECT v.video_id, v.duration , IF(v.duration <= t.progress, true, false) as completed, t.* - FROM {html5videos} v LEFT JOIN {html5tracking} t ON v.id = t.html5videoid + FROM {html5player_html5videos} v LEFT JOIN {html5player_html5trackings} t ON v.id = t.html5videoid WHERE v.html5player = :html5player AND t.user = :userid ORDER by completed ASC, t.html5videoid ASC"; $progresses = $DB->get_records_sql($sql, $params); diff --git a/db/install.xml b/db/install.xml index ecc525e..dbd0949 100644 --- a/db/install.xml +++ b/db/install.xml @@ -34,7 +34,7 @@ - +
@@ -49,11 +49,11 @@
- +
- + diff --git a/db/upgrade.php b/db/upgrade.php index 2090202..8a6b09b 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -37,9 +37,9 @@ * Please do not forget to use upgrade_set_timeout() * before any action that may take longer time to finish. * - * @package mod_html5player - * @copyright 2021 Brain station 23 ltd <> {@link https://brainstation-23.com/} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package mod_html5player + * @copyright 2021 Brain station 23 ltd <> {@link https://brainstation-23.com/} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die; @@ -51,6 +51,28 @@ * @return bool */ function xmldb_html5player_upgrade($oldversion) { -// global $CFG, $DB; + global $DB; + + $dbman = $DB->get_manager(); + + + if ($oldversion < 2021113004) { + + $table = new xmldb_table('html5videos'); + // Conditionally launch rename table for html5videos. + if ($dbman->table_exists($table)) { + $dbman->rename_table($table, 'html5player_html5videos'); + } + + $table = new xmldb_table('html5tracking'); + // Conditionally launch rename table for html5tracking. + if ($dbman->table_exists($table)) { + $dbman->rename_table($table, 'html5player_html5trackings'); + } + + // Savepoint reached. + upgrade_plugin_savepoint(true, 2021113004, 'mod', 'html5player'); + } + return true; } diff --git a/lang/en/html5player.php b/lang/en/html5player.php index efe9363..eec3117 100644 --- a/lang/en/html5player.php +++ b/lang/en/html5player.php @@ -26,6 +26,7 @@ // System strings. $string['html5player'] = 'HTML5Player'; +$string['privacy:metadata'] = 'The Html5Player does not store any personal data.'; $string['createhtml5player'] = 'Add a new html5player'; $string['content'] = 'Html5player content'; $string['pluginadministration'] = 'HTML5Player administration'; @@ -86,3 +87,6 @@ $string['trackinginterval'] = 'Tracking interval'; $string['trackinginterval_help'] = 'Brightcove video progress tracking interval in seconds'; + +$string['forwardscrubbing'] = 'Disable forward scrubbing'; +$string['forwardscrubbing_help'] = 'Brightcove video disable forward scrubbing'; diff --git a/lib.php b/lib.php index a63c2e8..cb3019e 100644 --- a/lib.php +++ b/lib.php @@ -28,9 +28,9 @@ const HTML5_TABLE_NAME = 'html5player'; -const HTML5PLYAER_VIDEO_TABLE_NAME = 'html5videos'; +const HTML5PLYAER_VIDEO_TABLE_NAME = 'html5player_html5videos'; -const HTML5PLYAER_VIDEO_TRACKING_TABLE_NAME = 'html5tracking'; +const HTML5PLYAER_VIDEO_TRACKING_TABLE_NAME = 'html5player_html5trackings'; const HTML5PLYAER_VIDEO_TYPE_SINGLE = 1; @@ -190,7 +190,7 @@ function html5player_delete_instance($id) { $DB->delete_records(HTML5_TABLE_NAME, array('id'=>$html5player->id)); // Delete Record sets form html5video table $DB->delete_records(HTML5PLYAER_VIDEO_TABLE_NAME, array('html5player'=>$html5player->id)); - // Delete tracking recrods set form html5tracking table. + // Delete tracking recrods set form html5player_html5trackings table. $DB->delete_records(HTML5PLYAER_VIDEO_TRACKING_TABLE_NAME, array('html5player'=>$html5player->id)); // Commit database transaction $DB->commit_delegated_transaction($transection); @@ -221,8 +221,6 @@ function html5player_get_coursemodule_info($coursemodule) { require_once("$CFG->libdir/resourcelib.php"); require_once($CFG->libdir.'/completionlib.php'); - $context = context_module::instance($coursemodule->id); - if (!$html5player = $DB->get_record('html5player', array('id'=>$coursemodule->instance), 'id, name, display, displayoptions, tobemigrated, intro, introformat,meta_info, account_id, player_id, video_type, video_id,sizing,aspect_ratio,units,width,height')) { return NULL; @@ -246,9 +244,6 @@ function html5player_get_coursemodule_info($coursemodule) { $height = empty($options['popupheight']) ? 450 : $options['popupheight']; $wh = "width=$width,height=$height,toolbar=no,location=no,menubar=no,copyhistory=no,status=no,directories=no,scrollbars=yes,resizable=yes"; $info->onclick = "window.open('$fullurl', '', '$wh'); return false;"; - - return $info; - return $info; } diff --git a/locallib.php b/locallib.php index 1e454e2..90d71fe 100644 --- a/locallib.php +++ b/locallib.php @@ -135,7 +135,7 @@ function html5player_render_embed_html($html5player, $cm, $course, $completioni
- +
render_from_template('theme_allergan_blank/core_course/completion_percentage', $data); ?> @@ -265,11 +265,15 @@ function html5player_get_unit($key) { /** * @param $html5player + * @param $cm + * @param $course + * @return void|null * @throws coding_exception + * @throws dml_exception */ -function html5player_generate_code($html5player, $cm) { +function html5player_generate_code($html5player, $cm, $course=null) { global $OUTPUT, $PAGE, $USER; - echo html_writer::tag('h1', $html5player->name, ['class' => 'mb-5']); +// echo html_writer::tag('h1', $html5player->name, ['class' => 'mb-5']); if ($html5player->video_type == 2) { $html5player->playlist_id = $html5player->video_id; @@ -282,11 +286,36 @@ function html5player_generate_code($html5player, $cm) { $html5player->is_student = is_enrolled($context, $USER->id, '', true) && !has_capability('mod/html5player:addinstance', $module_context); $interval = get_config('html5player','trackinginterval'); + $forwardscrubbing = get_config('html5player','forwardscrubbing'); $html5player->progress_interval = $interval ? $interval * 1000 : 5000; + $html5player->forwardscrubbing = $forwardscrubbing; + + $html5player->cmcompleted = html5player_is_module_completed($course, $cm, $USER->id); echo $OUTPUT->render_from_template('mod_html5player/brightcove/video-renderer',$html5player); $PAGE->requires->js_call_amd('mod_html5player/brightcove', 'init',[json_encode($html5player)]); } +/** + * @param $course + * @param $cm + * @param $userid + * @return bool|int + */ +function html5player_is_module_completed($course,$cm, $userid) { + $completion = new \completion_info($course); + + // First, let's make sure completion is enabled. + if ($completion->is_enabled() && $completion->is_tracked_user($userid)) { + if ($completion->is_course_complete($userid)) { + return true; + } + $data = $completion->get_data($cm, true, $userid); + return !($data->completionstate == COMPLETION_INCOMPLETE); + } + + return false; +} + /** * @param $course * @param $cm @@ -561,31 +590,24 @@ function html5player_get_token(){ * * @returns {string} $response - JSON response received from the OAuth API */ - - - // CORS enablement and other headers - header("Access-Control-Allow-Origin: *"); - header("Content-type: application/json"); - header("X-Content-Type-Options: nosniff"); - header("X-XSS-Protection"); $client_id = get_config('html5player','clientid'); $client_secret= get_config('html5player','clientsecrete'); - // note that if you are using this proxy for a single credential - // you can just hardcode the client id and secret below instead of passing them - - $auth_string = "{$client_id}:{$client_secret}"; - $request = "https://oauth.brightcove.com/v4/access_token?grant_type=client_credentials"; - $ch = curl_init($request); + $auth_string = base64_encode($client_id.':'.$client_secret); + $ch = curl_init(); curl_setopt_array($ch, array( - CURLOPT_POST => TRUE, - CURLOPT_RETURNTRANSFER => TRUE, - CURLOPT_SSL_VERIFYPEER => FALSE, - CURLOPT_TIMEOUT=> 60, - CURLOPT_USERPWD => $auth_string, - CURLOPT_HTTPHEADER => array( - 'Content-type: application/x-www-form-urlencoded', - ) + CURLOPT_URL => 'https://oauth.brightcove.com/v4/access_token?grant_type=client_credentials', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_HTTPHEADER => array( + 'Authorization: Basic '.$auth_string + ), )); + $response = curl_exec($ch); $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); @@ -597,6 +619,11 @@ function html5player_get_token(){ if ($httpcode === 200){ return json_decode($response); } + + if ($httpcode === 400){ + throw new moodle_exception('generalexceptionmessage','error','', + 'Invalid credentials!'); + } throw new moodle_exception('generalexceptionmessage','error','', 'something went wrong in authorization token request'); } @@ -689,8 +716,8 @@ function html5player_get_playlist_videos_description(string $account_id, string function html5player_is_video_view_completed(int $html5player){ global $DB, $USER; $sql = "select p.course, p.name, - IF( (select SUM(v.duration) from {html5videos} v where v.html5player = p.id group by v.html5player)<= - (select SUM(t.progress) from {html5tracking} t where t.html5player = p.id AND t.user = :user group by t.html5player) + IF( (select SUM(v.duration) from {html5player_html5videos} v where v.html5player = p.id group by v.html5player)<= + (select SUM(t.progress) from {html5player_html5trackings} t where t.html5player = p.id AND t.user = :user group by t.html5player) ,true, false) completed from {html5player} p where id= :id limit 1 offset 0"; return $DB->get_record_sql($sql, array('id' => $html5player, 'user' => $USER->id)); } \ No newline at end of file diff --git a/settings.php b/settings.php index 1e9d6fa..edb823d 100644 --- a/settings.php +++ b/settings.php @@ -93,6 +93,10 @@ get_string('trackinginterval', 'mod_html5player'), get_string('trackinginterval_help', 'mod_html5player'), 5, PARAM_INT, 10)); + $settings->add(new admin_setting_configcheckbox('html5player/forwardscrubbing', + get_string('forwardscrubbing', 'mod_html5player'), + get_string('forwardscrubbing_help', 'mod_html5player'), 1, 1, 0)); + // $settings->add(new brightcove_credential('html5player/heightxxx', // 'accountid', // 'accountname', '100', PARAM_TEXT, 50)); diff --git a/version.php b/version.php index cf3ceab..317d680 100644 --- a/version.php +++ b/version.php @@ -25,7 +25,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2021113000; // The current version (Date: YYYYMMDDXX). +$plugin->version = 2021113004; // The current version (Date: YYYYMMDDXX). $plugin->requires = 2019111806; // Requires this Moodle version. From 5a316e52403654a9ccc92f046f65621b703bc678 Mon Sep 17 00:00:00 2001 From: Shadman Date: Mon, 10 Jan 2022 17:31:05 +0600 Subject: [PATCH 2/3] Add video tracking feature with required styling --- locallib.php | 72 +++++++++++++++++++++++++++------------------------- settings.php | 6 ++--- styles.css | 25 ++++++++++++++++++ 3 files changed, 66 insertions(+), 37 deletions(-) create mode 100644 styles.css diff --git a/locallib.php b/locallib.php index 90d71fe..d3b3988 100644 --- a/locallib.php +++ b/locallib.php @@ -76,8 +76,10 @@ function html5player_display_embed_video($html5player, $cm, $course) { $completiondetails = cm_completion_details::get_instance($cminfo, $USER->id); $activitydates = activity_dates::get_dates_for_module($cminfo, $USER->id); $completioninfo = $OUTPUT->activity_information($cminfo, $completiondetails, $activitydates); - + echo $OUTPUT->activity_information($cminfo, $completiondetails, $activitydates); html5player_render_embed_html($html5player, $cm, $course,$completioninfo); + + //echo html_writer::tag('h1', $html5player->name, ['class' => 'heading-1']); echo $OUTPUT->footer(); die; @@ -86,7 +88,7 @@ function html5player_display_embed_video($html5player, $cm, $course) { function html5player_render_embed_html($html5player, $cm, $course, $completioninfo) { global $OUTPUT, $COURSE, $PAGE, $USER; - echo $OUTPUT->activity_navigation(); + //echo $OUTPUT->activity_navigation(); $is_favourite = html5player_is_favourite(); $progressPercentage = progress::get_course_progress_percentage($COURSE); $progressPercentage = floor($progressPercentage); @@ -138,32 +140,32 @@ function html5player_render_embed_html($html5player, $cm, $course, $completioni - render_from_template('theme_allergan_blank/core_course/completion_percentage', $data); ?> - -
-
- -
- -
- meta_info); - if (!empty($html5playermeta_info)) : - $meta_infos = explode("\n", trim($html5player->meta_info)); - echo html_writer::start_tag('ul',array('class' => 'mod-custommod-right-content mt-3')); - foreach ($meta_infos as $meta_info): - $infos = explode(":",$meta_info); - if (isset($infos[0] ) && isset($infos[1])){ - echo "

$infos[0]:$infos[1]

"; - } - endforeach; - echo html_writer::end_tag('ul'); - endif; - ?> -
-
+render_from_template('theme_allergan_blank/core_course/completion_percentage', $data); ?> + + + + + + + +meta_info); +// if (!empty($html5playermeta_info)) : +// $meta_infos = explode("\n", trim($html5player->meta_info)); +// echo html_writer::start_tag('ul',array('class' => 'mod-custommod-right-content mt-3')); +// foreach ($meta_infos as $meta_info): +// $infos = explode(":",$meta_info); +// if (isset($infos[0] ) && isset($infos[1])){ +// echo "

$infos[0]:$infos[1]

"; +// } +// endforeach; +// echo html_writer::end_tag('ul'); +// endif; +// ?> + + 'sub-heading')); - echo $OUTPUT->heading(format_string($html5player->name), 2, 'text-primary'); - echo html_writer::end_div(); - echo html_writer::end_div(); +// echo html_writer::start_div('row mb-5'); +// echo html_writer::start_div('col'); +// echo html_writer::tag('p',get_string('video','mod_html5player'),array('class' => 'sub-heading')); +// echo $OUTPUT->heading(format_string($html5player->name), 2, 'text-primary'); +// echo html_writer::end_div(); +// echo html_writer::end_div(); + + echo $OUTPUT->heading(format_string($html5player->name), 2); } diff --git a/settings.php b/settings.php index edb823d..83c0ebb 100644 --- a/settings.php +++ b/settings.php @@ -17,9 +17,9 @@ /** * html5player plugin settings. * - * @package mod_html5player - * @copyright 2021 Brain station 23 ltd <> {@link https://brainstation-23.com/} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package mod_html5player + * @copyright 2021 Brain station 23 ltd <> {@link https://brainstation-23.com/} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die; diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..c100cea --- /dev/null +++ b/styles.css @@ -0,0 +1,25 @@ +.path-mod-html5player .vjs-live .vjs-time-control { + display: block; +} + +.path-mod-html5player .video-js .vjs-current-time, +.vjs-no-flex .vjs-current-time { + display: block; +} + +.path-mod-html5player .video-js .vjs-duration, +.vjs-no-flex .vjs-duration { + display: block; +} + +.path-mod-html5player .bc-player-default_default .vjs-progress-control { + position: absolute; + left: 0; + right: 0; + width: 100%; + height: 1.5em; + top: -1.5em; +} +.path-mod-html5player .bc-player-default_default .vjs-progress-control .vjs-progress-holder { + margin: 0; +} \ No newline at end of file From 4aeca24af59e828b94efa82ca41787a6c61e12b9 Mon Sep 17 00:00:00 2001 From: Shadman Date: Sat, 15 Jan 2022 15:03:57 +0600 Subject: [PATCH 3/3] Update minor styling changes to the player --- styles.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/styles.css b/styles.css index c100cea..ab12437 100644 --- a/styles.css +++ b/styles.css @@ -12,14 +12,14 @@ display: block; } -.path-mod-html5player .bc-player-default_default .vjs-progress-control { +.path-mod-html5player .vjs-big-play-centered .vjs-progress-control { position: absolute; left: 0; right: 0; width: 100%; - height: 1.5em; - top: -1.5em; + height: 1em; + top: -1em; } -.path-mod-html5player .bc-player-default_default .vjs-progress-control .vjs-progress-holder { +.path-mod-html5player .vjs-big-play-centered .vjs-progress-control .vjs-progress-holder { margin: 0; } \ No newline at end of file