diff --git a/main/inc/lib/display.lib.php b/main/inc/lib/display.lib.php index 9217f1f8a5..4de0a952cc 100755 --- a/main/inc/lib/display.lib.php +++ b/main/inc/lib/display.lib.php @@ -2925,6 +2925,7 @@ HTML; public static function getFrameReadyBlock($frameName) { $webPublicPath = api_get_path(WEB_PUBLIC_PATH); + $webJsPath = api_get_path(WEB_LIBRARY_JS_PATH); $videoFeatures = [ 'playpause', @@ -2946,19 +2947,19 @@ HTML; continue; } $defaultFeatures[] = $feature; - $videoPluginsJS[] = "mediaelement/plugins/$feature/$feature.js"; - $videoPluginCSS[] = "mediaelement/plugins/$feature/$feature.css"; + $videoPluginsJS[] = "mediaelement/plugins/$feature/$feature.min.js"; + $videoPluginCSS[] = "mediaelement/plugins/$feature/$feature.min.css"; } } $videoPluginFiles = ''; foreach ($videoPluginsJS as $file) { - $videoPluginFiles .= '{type: "script", src: "'.$webPublicPath.'assets/'.$file.'"},'; + $videoPluginFiles .= '{type: "script", src: "'.$webJsPath.$file.'"},'; } $videoPluginCssFiles = ''; foreach ($videoPluginCSS as $file) { - $videoPluginCssFiles .= '{type: "stylesheet", src: "'.$webPublicPath.'assets/'.$file.'"},'; + $videoPluginCssFiles .= '{type: "stylesheet", src: "'.$webJsPath.$file.'"},'; } $translateHtml = ''; @@ -2978,7 +2979,7 @@ HTML; $.frameReady(function() { $(function () { $("video:not(.skip), audio:not(.skip)").mediaelementplayer({ - pluginPath: "'.$webPublicPath.'assets/mediaelement/plugins/", + pluginPath: "'.$webJsPath.'mediaelement/plugins/", features: [\''.$videoFeatures.'\'], success: function(mediaElement, originalNode, instance) { '.ChamiloApi::getQuizMarkersRollsJS().' @@ -2997,8 +2998,8 @@ HTML; {type:"script", src:"'.$webPublicPath.'assets/jquery-ui/jquery-ui.min.js"}, {type:"script", src: "'.$webPublicPath.'assets/mediaelement/build/mediaelement-and-player.min.js", deps: [ - {type:"script", src: "'.$webPublicPath.'assets/mediaelement/plugins/vrview/vrview.js"}, - {type:"script", src: "'.$webPublicPath.'assets/mediaelement/plugins/markersrolls/markersrolls.js"}, + {type:"script", src: "'.$webJsPath.'mediaelement/plugins/vrview/vrview.js"}, + {type:"script", src: "'.$webJsPath.'mediaelement/plugins/markersrolls/markersrolls.min.js"}, '.$videoPluginFiles.' ]}, '.$translateHtml.' @@ -3009,7 +3010,7 @@ HTML; {type:"stylesheet", src:"'.$webPublicPath.'assets/jquery-ui/themes/smoothness/theme.css"}, {type:"stylesheet", src:"'.$webPublicPath.'css/dialog.css"}, {type:"stylesheet", src: "'.$webPublicPath.'assets/mediaelement/build/mediaelementplayer.min.css"}, - {type:"stylesheet", src: "'.$webPublicPath.'assets/mediaelement/plugins/vrview/vrview.css"}, + {type:"stylesheet", src: "'.$webJsPath.'mediaelement/plugins/vrview/vrview.css"}, ]);'; return $frameReady; diff --git a/main/inc/lib/javascript/mediaelement/plugins/markersrolls/markersrolls.js b/main/inc/lib/javascript/mediaelement/plugins/markersrolls/markersrolls.js new file mode 100644 index 0000000000..672bd0b1c2 --- /dev/null +++ b/main/inc/lib/javascript/mediaelement/plugins/markersrolls/markersrolls.js @@ -0,0 +1,109 @@ +/*! + * MediaElement.js + * http://www.mediaelementjs.com/ + * + * Wrapper that mimics native HTML5 MediaElement (audio and video) + * using a variety of technologies (pure JavaScript, Flash, iframe) + * + * Copyright 2010-2017, John Dyer (http://j.hn/) + * License: MIT + * + */(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i currentPosition) { + if (lastMarkerRollCallback > currentPosition) { + lastMarkerRollCallback = -1; + } + } else { + lastPlayedPosition = currentPosition; + } + + if (0 === markersCount || !player.options.markersRolls[currentPosition] || currentPosition === lastMarkerRollCallback) { + return; + } + + lastMarkerRollCallback = currentPosition; + + media.pause(); + + markersRollsLayer.src = player.options.markersRolls[currentPosition]; + markersRollsLayer.style.display = 'block'; + }, false); + media.addEventListener('play', function () { + markersRollsLayer.style.display = 'none'; + markersRollsLayer.src = ''; + }, false); + }, + setmarkersrolls: function setmarkersrolls(controls) { + var markersRolls = controls.querySelectorAll('.' + this.options.classPrefix + 'time-marker'); + + var i = 0; + + for (var position in this.options.markersRolls) { + if (!this.options.markersRolls.hasOwnProperty(position)) { + continue; + } + + position = parseInt(position); + + if (position >= this.media.duration || position < 0) { + continue; + } + + var left = 100 * position / this.media.duration, + marker = markersRolls[i]; + + marker.style.width = this.options.markersRollsWidth + 'px'; + marker.style.left = left + '%'; + marker.style.background = this.options.markersRollsColor; + + i++; + } + } +}); + +},{}]},{},[1]); diff --git a/main/inc/lib/javascript/mediaelement/plugins/markersrolls/markersrolls.min.js b/main/inc/lib/javascript/mediaelement/plugins/markersrolls/markersrolls.min.js new file mode 100644 index 0000000000..2a05cc54fc --- /dev/null +++ b/main/inc/lib/javascript/mediaelement/plugins/markersrolls/markersrolls.min.js @@ -0,0 +1,12 @@ +/*! + * MediaElement.js + * http://www.mediaelementjs.com/ + * + * Wrapper that mimics native HTML5 MediaElement (audio and video) + * using a variety of technologies (pure JavaScript, Flash, iframe) + * + * Copyright 2010-2017, John Dyer (http://j.hn/) + * License: MIT + * + */ +!function i(n,a,l){function p(r,e){if(!a[r]){if(!n[r]){var s="function"==typeof require&&require;if(!e&&s)return s(r,!0);if(c)return c(r,!0);var t=new Error("Cannot find module '"+r+"'");throw t.code="MODULE_NOT_FOUND",t}var o=a[r]={exports:{}};n[r][0].call(o.exports,function(e){return p(n[r][1][e]||e)},o,o.exports,i,n,a,l)}return a[r].exports}for(var c="function"==typeof require&&require,e=0;e=this.media.duration||t<0)){var o=100*t/this.media.duration,i=r[s];i.style.width=this.options.markersRollsWidth+"px",i.style.left=o+"%",i.style.background=this.options.markersRollsColor,s++}}})},{}]},{},[1]); \ No newline at end of file diff --git a/main/inc/lib/javascript/mediaelement/plugins/speed/speed-i18n.js b/main/inc/lib/javascript/mediaelement/plugins/speed/speed-i18n.js new file mode 100644 index 0000000000..feec9d9f96 --- /dev/null +++ b/main/inc/lib/javascript/mediaelement/plugins/speed/speed-i18n.js @@ -0,0 +1,71 @@ +'use strict'; + +if (mejs.i18n.ca !== undefined) { + mejs.i18n.ca['mejs.speed-rate'] = 'Velocitat'; +} +if (mejs.i18n.cs !== undefined) { + mejs.i18n.cs['mejs.speed-rate'] = 'Rychlost'; +} +if (mejs.i18n.de !== undefined) { + mejs.i18n.de['mejs.speed-rate'] = 'Geschwindigkeitsrate'; +} +if (mejs.i18n.es !== undefined) { + mejs.i18n.es['mejs.speed-rate'] = 'Velocidad'; +} +if (mejs.i18n.fa !== undefined) { + mejs.i18n.fa['mejs.speed-rate'] = 'نرخ سرعت'; +} +if (mejs.i18n.fr !== undefined) { + mejs.i18n.fr['mejs.speed-rate'] = 'Vitesse'; +} +if (mejs.i18n.hr !== undefined) { + mejs.i18n.hr['mejs.speed-rate'] = 'Brzina reprodukcije'; +} +if (mejs.i18n.hu !== undefined) { + mejs.i18n.hu['mejs.speed-rate'] = 'Sebesség'; +} +if (mejs.i18n.it !== undefined) { + mejs.i18n.it['mejs.speed-rate'] = 'Velocità'; +} +if (mejs.i18n.ja !== undefined) { + mejs.i18n.ja['mejs.speed-rate'] = '高速'; +} +if (mejs.i18n.ko !== undefined) { + mejs.i18n.ko['mejs.speed-rate'] = '속도 속도'; +} +if (mejs.i18n.ms !== undefined) { + mejs.i18n.ms['mejs.speed-rate'] = 'Kelajuan'; +} +if (mejs.i18n.nl !== undefined) { + mejs.i18n.nl['mejs.speed-rate'] = 'Snelheidsgraad'; +} +if (mejs.i18n.pl !== undefined) { + mejs.i18n.pl['mejs.speed-rate'] = 'Prędkość'; +} +if (mejs.i18n.pt !== undefined) { + mejs.i18n.pt['mejs.speed-rate'] = 'Taxa de velocidade'; +} +if (mejs.i18n.ro !== undefined) { + mejs.i18n.ro['mejs.speed-rate'] = 'Viteză de viteză'; +} +if (mejs.i18n.ru !== undefined) { + mejs.i18n.ru['mejs.speed-rate'] = 'Скорость воспроизведения'; +} +if (mejs.i18n.sk !== undefined) { + mejs.i18n.sk['mejs.speed-rate'] = 'Rýchlosť'; +} +if (mejs.i18n.sv !== undefined) { + mejs.i18n.sv['mejs.speed-rate'] = 'Hastighet'; +} +if (mejs.i18n.tr !== undefined) { + mejs.i18n.tr['mejs.speed-rate'] = 'Hız oranı'; +} +if (mejs.i18n.uk !== undefined) { + mejs.i18n.uk['mejs.speed-rate'] = 'Швидкість відтворення'; +} +if (mejs.i18n.zh !== undefined) { + mejs.i18n.zh['mejs.speed-rate'] = '速度'; +} +if (mejs.i18n['zh-CN'] !== undefined) { + mejs.i18n['zh-CN']['mejs.speed-rate'] = '速度'; +} diff --git a/main/inc/lib/javascript/mediaelement/plugins/speed/speed.css b/main/inc/lib/javascript/mediaelement/plugins/speed/speed.css new file mode 100644 index 0000000000..76579a8895 --- /dev/null +++ b/main/inc/lib/javascript/mediaelement/plugins/speed/speed.css @@ -0,0 +1,94 @@ +.mejs__speed-button, +.mejs-speed-button { + position: relative; +} + +.mejs__speed-button > button, +.mejs-speed-button > button { + background: transparent; + color: #fff; + font-size: 11px; + line-height: normal; + margin: 11px 0 0; + width: 36px; +} + +.mejs__speed-selector, +.mejs-speed-selector { + background: rgba(50, 50, 50, 0.7); + border: solid 1px transparent; + border-radius: 0; + height: 150px; + left: -10px; + overflow: hidden; + padding: 0; + position: absolute; + top: -100px; + visibility: hidden; + width: 60px; +} + +.mejs__speed-selector, +.mejs-speed-selector { + visibility: visible; +} + +.mejs__speed-selector-list, +.mejs-speed-selector-list { + display: block; + list-style-type: none !important; + margin: 0; + overflow: hidden; + padding: 0; +} + +.mejs__speed-selector-list-item, +.mejs-speed-selector-list-item { + color: #fff; + display: block; + list-style-type: none !important; + margin: 0 0 6px; + overflow: hidden; + padding: 0 10px; +} + +.mejs__speed-selector-list-item:hover, +.mejs-speed-selector-list-item:hover { + background-color: rgb(200, 200, 200) !important; + background-color: rgba(255, 255, 255, 0.4) !important; +} + +.mejs__speed-selector-input, +.mejs-speed-selector-input { + clear: both; + float: left; + left: -1000px; + margin: 3px 3px 0 5px; + position: absolute; +} + +.mejs__speed-selector-label, +.mejs-speed-selector-label { + color: white; + cursor: pointer; + float: left; + font-size: 11px; + line-height: 15px; + margin-left: 5px; + padding: 4px 0 0; + width: 60px; +} + +.mejs__speed-selected, +.mejs-speed-selected { + color: rgba(33, 248, 248, 1); +} + +.mejs__speed-selector, +.mejs-speed-selector { + visibility: hidden; +} +.mejs__speed-button:hover .mejs__speed-selector, +.mejs-speed-button:hover .mejs-speed-selector { + visibility: visible; +} diff --git a/main/inc/lib/javascript/mediaelement/plugins/speed/speed.js b/main/inc/lib/javascript/mediaelement/plugins/speed/speed.js new file mode 100644 index 0000000000..4ce065dcdf --- /dev/null +++ b/main/inc/lib/javascript/mediaelement/plugins/speed/speed.js @@ -0,0 +1,200 @@ +/*! + * MediaElement.js + * http://www.mediaelementjs.com/ + * + * Wrapper that mimics native HTML5 MediaElement (audio and video) + * using a variety of technologies (pure JavaScript, Flash, iframe) + * + * Copyright 2010-2017, John Dyer (http://j.hn/) + * License: MIT + * + */(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i' + getSpeedNameFromValue(t.options.defaultSpeed) + '') + ('
') + ('
    ') + '
    '; + + t.addControlElement(player.speedButton, 'speed'); + + for (var _i = 0, _total = speeds.length; _i < _total; _i++) { + + var inputId = t.id + '-speed-' + speeds[_i].value; + + player.speedButton.querySelector('ul').innerHTML += '
  • ' + ('') + ('') + '
  • '; + } + + playbackSpeed = t.options.defaultSpeed; + + player.speedSelector = player.speedButton.querySelector('.' + t.options.classPrefix + 'speed-selector'); + + var inEvents = ['mouseenter', 'focusin'], + outEvents = ['mouseleave', 'focusout'], + radios = player.speedButton.querySelectorAll('input[type="radio"]'), + labels = player.speedButton.querySelectorAll('.' + t.options.classPrefix + 'speed-selector-label'); + + for (var _i2 = 0, _total2 = inEvents.length; _i2 < _total2; _i2++) { + player.speedButton.addEventListener(inEvents[_i2], function () { + mejs.Utils.removeClass(player.speedSelector, t.options.classPrefix + 'offscreen'); + player.speedSelector.style.height = player.speedSelector.querySelector('ul').offsetHeight; + player.speedSelector.style.top = -1 * parseFloat(player.speedSelector.offsetHeight) + 'px'; + }); + } + + for (var _i3 = 0, _total3 = outEvents.length; _i3 < _total3; _i3++) { + player.speedSelector.addEventListener(outEvents[_i3], function () { + mejs.Utils.addClass(this, t.options.classPrefix + 'offscreen'); + }); + } + + for (var _i4 = 0, _total4 = radios.length; _i4 < _total4; _i4++) { + var radio = radios[_i4]; + radio.disabled = false; + radio.addEventListener('click', function () { + var self = this, + newSpeed = self.value; + + playbackSpeed = newSpeed; + media.playbackRate = parseFloat(newSpeed); + player.speedButton.querySelector('button').innerHTML = getSpeedNameFromValue(newSpeed); + var selected = player.speedButton.querySelectorAll('.' + t.options.classPrefix + 'speed-selected'); + for (var _i5 = 0, _total5 = selected.length; _i5 < _total5; _i5++) { + mejs.Utils.removeClass(selected[_i5], t.options.classPrefix + 'speed-selected'); + } + + self.checked = true; + var siblings = mejs.Utils.siblings(self, function (el) { + return mejs.Utils.hasClass(el, t.options.classPrefix + 'speed-selector-label'); + }); + for (var j = 0, _total6 = siblings.length; j < _total6; j++) { + mejs.Utils.addClass(siblings[j], t.options.classPrefix + 'speed-selected'); + } + }); + } + + for (var _i6 = 0, _total7 = labels.length; _i6 < _total7; _i6++) { + labels[_i6].addEventListener('click', function () { + var radio = mejs.Utils.siblings(this, function (el) { + return el.tagName === 'INPUT'; + })[0], + event = mejs.Utils.createEvent('click', radio); + radio.dispatchEvent(event); + }); + } + + t.options.keyActions.push({ + keys: [60, 188], + action: function action(player, media, key, event) { + if (event.key != '<') return; + + for (var _i7 = 0; _i7 < radios.length - 1; _i7++) { + if (radios[_i7].checked) { + var nextRadio = radios[_i7 + 1]; + nextRadio.dispatchEvent(mejs.Utils.createEvent('click', nextRadio)); + } + } + } + }, { + keys: [62, 190], + action: function action(player, media, key, event) { + if (event.key != '>') return; + + for (var _i8 = 1; _i8 < radios.length; _i8++) { + if (radios[_i8].checked) { + var prevRadio = radios[_i8 - 1]; + prevRadio.dispatchEvent(mejs.Utils.createEvent('click', prevRadio)); + } + } + } + }); + + player.speedSelector.addEventListener('keydown', function (e) { + e.stopPropagation(); + }); + + media.addEventListener('loadedmetadata', function () { + if (playbackSpeed) { + media.playbackRate = parseFloat(playbackSpeed); + } + }); + }, + cleanspeed: function cleanspeed(player) { + if (player) { + if (player.speedButton) { + player.speedButton.parentNode.removeChild(player.speedButton); + } + if (player.speedSelector) { + player.speedSelector.parentNode.removeChild(player.speedSelector); + } + } + } +}); + +},{}]},{},[1]); diff --git a/main/inc/lib/javascript/mediaelement/plugins/speed/speed.min.css b/main/inc/lib/javascript/mediaelement/plugins/speed/speed.min.css new file mode 100644 index 0000000000..10d379715f --- /dev/null +++ b/main/inc/lib/javascript/mediaelement/plugins/speed/speed.min.css @@ -0,0 +1 @@ +.mejs-speed-button,.mejs__speed-button{position:relative}.mejs-speed-button>button,.mejs__speed-button>button{background:transparent;color:#fff;font-size:11px;line-height:normal;margin:11px 0 0;width:36px}.mejs-speed-selector,.mejs__speed-selector{background:rgba(50,50,50,.7);border:1px solid transparent;border-radius:0;height:150px;left:-10px;overflow:hidden;padding:0;position:absolute;top:-100px;width:60px;visibility:visible}.mejs-speed-selector-list,.mejs__speed-selector-list{display:block;list-style-type:none!important;margin:0;overflow:hidden;padding:0}.mejs-speed-selector-list-item,.mejs__speed-selector-list-item{color:#fff;display:block;list-style-type:none!important;margin:0 0 6px;overflow:hidden;padding:0 10px}.mejs-speed-selector-list-item:hover,.mejs__speed-selector-list-item:hover{background-color:#c8c8c8!important;background-color:hsla(0,0%,100%,.4)!important}.mejs-speed-selector-input,.mejs__speed-selector-input{clear:both;float:left;left:-1000px;margin:3px 3px 0 5px;position:absolute}.mejs-speed-selector-label,.mejs__speed-selector-label{color:#fff;cursor:pointer;float:left;font-size:11px;line-height:15px;margin-left:5px;padding:4px 0 0;width:60px}.mejs-speed-selected,.mejs__speed-selected{color:#21f8f8}.mejs-speed-selector,.mejs__speed-selector{visibility:hidden}.mejs-speed-button:hover .mejs-speed-selector,.mejs__speed-button:hover .mejs__speed-selector{visibility:visible} \ No newline at end of file diff --git a/main/inc/lib/javascript/mediaelement/plugins/speed/speed.min.js b/main/inc/lib/javascript/mediaelement/plugins/speed/speed.min.js new file mode 100644 index 0000000000..2b82dd34f3 --- /dev/null +++ b/main/inc/lib/javascript/mediaelement/plugins/speed/speed.min.js @@ -0,0 +1,12 @@ +/*! + * MediaElement.js + * http://www.mediaelementjs.com/ + * + * Wrapper that mimics native HTML5 MediaElement (audio and video) + * using a variety of technologies (pure JavaScript, Flash, iframe) + * + * Copyright 2010-2017, John Dyer (http://j.hn/) + * License: MIT + * + */ +!function r(i,l,a){function d(t,e){if(!l[t]){if(!i[t]){var s="function"==typeof require&&require;if(!e&&s)return s(t,!0);if(p)return p(t,!0);var o=new Error("Cannot find module '"+t+"'");throw o.code="MODULE_NOT_FOUND",o}var n=l[t]={exports:{}};i[t][0].call(n.exports,function(e){return d(i[t][1][e]||e)},n,n.exports,r,i,l,a)}return l[t].exports}for(var p="function"==typeof require&&require,e=0;e'+p(d.options.defaultSpeed)+'
      ',d.addControlElement(l.speedButton,"speed");for(var f=0,v=o.length;f"}c=d.options.defaultSpeed,l.speedSelector=l.speedButton.querySelector("."+d.options.classPrefix+"speed-selector");for(var m=["mouseenter","focusin"],S=["mouseleave","focusout"],x=l.speedButton.querySelectorAll('input[type="radio"]'),y=l.speedButton.querySelectorAll("."+d.options.classPrefix+"speed-selector-label"),b=0,g=m.length;b"==o.key)for(var n=1;n6 \ No newline at end of file diff --git a/main/inc/lib/javascript/mediaelement/plugins/vrview/vrview.css b/main/inc/lib/javascript/mediaelement/plugins/vrview/vrview.css new file mode 100644 index 0000000000..cf5cba588b --- /dev/null +++ b/main/inc/lib/javascript/mediaelement/plugins/vrview/vrview.css @@ -0,0 +1,4 @@ +.mejs__vrview-button > button, +.mejs-vrview-button > button { + background: url('cardboard.svg') no-repeat 0 4px; +} \ No newline at end of file diff --git a/main/inc/lib/javascript/mediaelement/plugins/vrview/vrview.js b/main/inc/lib/javascript/mediaelement/plugins/vrview/vrview.js new file mode 100644 index 0000000000..766135e021 --- /dev/null +++ b/main/inc/lib/javascript/mediaelement/plugins/vrview/vrview.js @@ -0,0 +1,375 @@ +/*! + * MediaElement.js + * http://www.mediaelementjs.com/ + * + * Wrapper that mimics native HTML5 MediaElement (audio and video) + * using a variety of technologies (pure JavaScript, Flash, iframe) + * + * Copyright 2010-2017, John Dyer (http://j.hn/) + * License: MIT + * + */(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 0) { + var settings = VrAPI.creationQueue.pop(); + VrAPI.createInstance(settings); + } + }, + + createInstance: function createInstance(settings) { + var player = new VRView.Player('#' + settings.id, settings.options); + window['__ready__' + settings.id](player); + } +}; + +var VrRenderer = { + name: 'vrview', + + options: { + prefix: 'vrview' + }, + + canPlayType: function canPlayType(type) { + return ~['video/mp4', 'application/x-mpegurl', 'vnd.apple.mpegurl', 'application/dash+xml'].indexOf(type.toLowerCase()); + }, + + create: function create(mediaElement, options, mediaFiles) { + var stack = [], + vr = {}, + readyState = 4; + + var vrPlayer = null, + paused = true, + volume = 1, + oldVolume = volume, + bufferedTime = 0, + ended = false, + duration = 0, + url = ''; + + vr.options = options; + vr.id = mediaElement.id + '_' + options.prefix; + vr.mediaElement = mediaElement; + + var props = mejs.html5media.properties, + assignGettersSetters = function assignGettersSetters(propName) { + + var capName = propName.substring(0, 1).toUpperCase() + propName.substring(1); + + vr['get' + capName] = function () { + if (vrPlayer !== null) { + var value = null; + + switch (propName) { + case 'currentTime': + return vrPlayer.getCurrentTime(); + case 'duration': + return vrPlayer.getDuration(); + case 'volume': + volume = vrPlayer.getVolume(); + return volume; + case 'muted': + return volume === 0; + case 'paused': + paused = vrPlayer.isPaused; + return paused; + case 'ended': + return ended; + case 'src': + return url; + case 'buffered': + return { + start: function start() { + return 0; + }, + end: function end() { + return bufferedTime * duration; + }, + length: 1 + }; + case 'readyState': + return readyState; + } + + return value; + } else { + return null; + } + }; + + vr['set' + capName] = function (value) { + + if (vrPlayer !== null) { + switch (propName) { + + case 'src': + var _url = typeof value === 'string' ? value : value[0].src; + vrPlayer.setContentInfo({ video: _url }); + break; + + case 'currentTime': + vrPlayer.setCurrentTime(value); + setTimeout(function () { + var event = mejs.Utils.createEvent('timeupdate', vr); + mediaElement.dispatchEvent(event); + }, 50); + break; + + case 'volume': + vrPlayer.setVolume(value); + setTimeout(function () { + var event = mejs.Utils.createEvent('volumechange', vr); + mediaElement.dispatchEvent(event); + }, 50); + break; + case 'muted': + volume = value ? 0 : oldVolume; + vrPlayer.setVolume(volume); + setTimeout(function () { + var event = mejs.Utils.createEvent('volumechange', vr); + mediaElement.dispatchEvent(event); + }, 50); + break; + case 'readyState': + var event = mejs.Utils.createEvent('canplay', vr); + mediaElement.dispatchEvent(event); + break; + default: + console.log('VRView ' + vr.id, propName, 'UNSUPPORTED property'); + break; + } + } else { + stack.push({ type: 'set', propName: propName, value: value }); + } + }; + }; + for (var i = 0, il = props.length; i < il; i++) { + assignGettersSetters(props[i]); + } + + var methods = mejs.html5media.methods, + assignMethods = function assignMethods(methodName) { + vr[methodName] = function () { + + if (vrPlayer !== null) { + switch (methodName) { + case 'play': + return vrPlayer.play(); + case 'pause': + return vrPlayer.pause(); + case 'load': + return null; + + } + } else { + stack.push({ type: 'call', methodName: methodName }); + } + }; + }; + for (var _i = 0, _il = methods.length; _i < _il; _i++) { + assignMethods(methods[_i]); + } + + var vrContainer = document.createElement('div'); + vrContainer.setAttribute('id', vr.id); + vrContainer.style.width = '100%'; + vrContainer.style.height = '100%'; + + window['__ready__' + vr.id] = function (_vrPlayer) { + + mediaElement.vrPlayer = vrPlayer = _vrPlayer; + + var iframe = vrContainer.querySelector('iframe'); + iframe.style.width = '100%'; + iframe.style.height = '100%'; + + if (stack.length) { + for (var _i2 = 0, _il2 = stack.length; _i2 < _il2; _i2++) { + + var stackItem = stack[_i2]; + + if (stackItem.type === 'set') { + var propName = stackItem.propName, + capName = '' + propName.substring(0, 1).toUpperCase() + propName.substring(1); + + vr['set' + capName](stackItem.value); + } else if (stackItem.type === 'call') { + vr[stackItem.methodName](); + } + } + } + + vrPlayer.on('ready', function () { + + var events = mejs.html5media.events.concat(['mouseover', 'mouseout']); + + var _loop = function _loop(_i3, _il3) { + vrPlayer.on(events[_i3], function () { + var event = mejs.Utils.createEvent(events[_i3], vr); + mediaElement.dispatchEvent(event); + }); + }; + + for (var _i3 = 0, _il3 = events.length; _i3 < _il3; _i3++) { + _loop(_i3, _il3); + } + }); + }; + + mediaElement.originalNode.parentNode.insertBefore(vrContainer, mediaElement.originalNode); + mediaElement.originalNode.style.display = 'none'; + + var vrSettings = { + path: options.vrPath, + is_stereo: options.vrIsStereo, + is_autopan_off: options.vrIsAutopanOff, + is_debug: options.vrDebug, + default_yaw: options.vrDefaultYaw, + is_yaw_only: options.vrIsYawOnly, + loop: options.loop + }; + + if (mediaFiles && mediaFiles.length > 0) { + for (var _i4 = 0, _il4 = mediaFiles.length; _i4 < _il4; _i4++) { + if (mejs.Renderers.renderers[options.prefix].canPlayType(mediaFiles[_i4].type)) { + vrSettings.video = mediaFiles[_i4].src; + vrSettings.width = '100%'; + vrSettings.height = '100%'; + break; + } + } + } + + VrAPI.prepareSettings({ + options: vrSettings, + id: vr.id + }); + + vr.hide = function () { + vr.pause(); + if (vrPlayer) { + vrContainer.style.display = 'none'; + } + }; + + vr.setSize = function () {}; + + vr.show = function () { + if (vrPlayer) { + vrContainer.style.display = ''; + } + }; + + return vr; + } +}; + +mejs.Renderers.add(VrRenderer); + +Object.assign(mejs.MepDefaults, { + vrPath: null, + + vrIsStereo: true, + + vrIsAutopanOff: true, + + vrDebug: false, + + vrDefaultYaw: 0, + + vrIsYawOnly: false +}); + +Object.assign(MediaElementPlayer.prototype, { + buildvrview: function buildvrview(player, controls, layers, media) { + + var t = this; + + if (!t.isVideo || t.isVideo && t.media.rendererName !== null && !t.media.rendererName.match(/(native\_(dash|hls)|html5)/)) { + return; + } + + var button = document.createElement('div'); + + player.detectFullscreenMode(); + + button.className = t.options.classPrefix + 'button ' + t.options.classPrefix + 'vrview-button'; + button.innerHTML = ''; + button.addEventListener('click', function () { + var isFullScreen = mejs.Features.HAS_TRUE_NATIVE_FULLSCREEN && mejs.Features.IS_FULLSCREEN || player.isFullScreen; + + if (isFullScreen) { + player.exitFullScreen(); + } else { + player.enterFullScreen(); + } + }); + + t.globalBind('keydown', function (e) { + var key = e.which || e.keyCode || 0; + if (key === 27 && (mejs.Features.HAS_TRUE_NATIVE_FULLSCREEN && mejs.Features.IS_FULLSCREEN || player.isFullScreen)) { + player.exitFullScreen(); + } + }); + + t.addControlElement(button, 'vrview'); + + var url = media.getSrc(), + mediaFiles = [{ src: url, type: mejs.Utils.getTypeFromFile(url) }], + renderInfo = mejs.Renderers.select(mediaFiles, ['vrview']); + + media.changeRenderer(renderInfo.rendererName, mediaFiles); + } +}); + +},{}]},{},[1]); diff --git a/main/inc/lib/javascript/mediaelement/plugins/vrview/vrview.min.css b/main/inc/lib/javascript/mediaelement/plugins/vrview/vrview.min.css new file mode 100644 index 0000000000..9ebc6e52d7 --- /dev/null +++ b/main/inc/lib/javascript/mediaelement/plugins/vrview/vrview.min.css @@ -0,0 +1 @@ +.mejs-vrview-button>button,.mejs__vrview-button>button{background:url(cardboard.svg) no-repeat 0 4px} \ No newline at end of file diff --git a/main/inc/lib/javascript/mediaelement/plugins/vrview/vrview.min.js b/main/inc/lib/javascript/mediaelement/plugins/vrview/vrview.min.js new file mode 100644 index 0000000000..5c9c0f9c62 --- /dev/null +++ b/main/inc/lib/javascript/mediaelement/plugins/vrview/vrview.min.js @@ -0,0 +1,12 @@ +/*! + * MediaElement.js + * http://www.mediaelementjs.com/ + * + * Wrapper that mimics native HTML5 MediaElement (audio and video) + * using a variety of technologies (pure JavaScript, Flash, iframe) + * + * Copyright 2010-2017, John Dyer (http://j.hn/) + * License: MIT + * + */ +!function i(s,o,u){function l(t,e){if(!o[t]){if(!s[t]){var r="function"==typeof require&&require;if(!e&&r)return r(t,!0);if(c)return c(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var a=o[t]={exports:{}};s[t][0].call(a.exports,function(e){return l(s[t][1][e]||e)},a,a.exports,i,s,o,u)}return o[t].exports}for(var c="function"==typeof require&&require,e=0;e',i.addEventListener("click",function(){mejs.Features.HAS_TRUE_NATIVE_FULLSCREEN&&mejs.Features.IS_FULLSCREEN||t.isFullScreen?t.exitFullScreen():t.enterFullScreen()}),a.globalBind("keydown",function(e){27===(e.which||e.keyCode||0)&&(mejs.Features.HAS_TRUE_NATIVE_FULLSCREEN&&mejs.Features.IS_FULLSCREEN||t.isFullScreen)&&t.exitFullScreen()}),a.addControlElement(i,"vrview");var s=n.getSrc(),o=[{src:s,type:mejs.Utils.getTypeFromFile(s)}],u=mejs.Renderers.select(o,["vrview"]);n.changeRenderer(u.rendererName,o)}}})},{}]},{},[1]); \ No newline at end of file diff --git a/main/inc/lib/template.lib.php b/main/inc/lib/template.lib.php index d6f3668359..59f6926863 100755 --- a/main/inc/lib/template.lib.php +++ b/main/inc/lib/template.lib.php @@ -574,6 +574,9 @@ class Template global $disable_js_and_css_files; $css = []; + $webPublicPath = api_get_path(WEB_PUBLIC_PATH); + $webJsPath = api_get_path(WEB_LIBRARY_JS_PATH); + // Default CSS Bootstrap $bowerCSSFiles = [ 'fontawesome/css/font-awesome.min.css', @@ -586,7 +589,6 @@ class Template 'bootstrap-daterangepicker/daterangepicker.css', 'bootstrap-select/dist/css/bootstrap-select.min.css', 'select2/dist/css/select2.min.css', - 'mediaelement/plugins/vrview/vrview.css', ]; $hide = api_get_configuration_value('hide_flag_language_switcher'); @@ -595,6 +597,12 @@ class Template $bowerCSSFiles[] = 'flag-icon-css/css/flag-icon.min.css'; } + foreach ($bowerCSSFiles as $file) { + $css[] = api_get_cdn_path($webPublicPath.'assets/'.$file); + } + + $css[] = $webJsPath.'mediaelement/plugins/vrview/vrview.css'; + $features = api_get_configuration_value('video_features'); $defaultFeatures = [ 'playpause', @@ -613,19 +621,15 @@ class Template if ($feature === 'vrview') { continue; } - $bowerCSSFiles[] = "mediaelement/plugins/$feature/$feature.css"; + $css[] = $webJsPath."mediaelement/plugins/$feature/$feature.min.css"; $defaultFeatures[] = $feature; } } - foreach ($bowerCSSFiles as $file) { - $css[] = api_get_cdn_path(api_get_path(WEB_PUBLIC_PATH).'assets/'.$file); - } - - $css[] = api_get_path(WEB_LIBRARY_PATH).'javascript/chosen/chosen.css'; + $css[] = $webJsPath.'chosen/chosen.css'; if (api_is_global_chat_enabled()) { - $css[] = api_get_path(WEB_LIBRARY_PATH).'javascript/chat/css/chat.css'; + $css[] = $webJsPath.'chat/css/chat.css'; } $css_file_to_string = ''; foreach ($css as $file) { @@ -722,6 +726,8 @@ class Template // JS files $js_files = [ 'chosen/chosen.jquery.min.js', + 'mediaelement/plugins/vrview/vrview.js', + 'mediaelement/plugins/markersrolls/markersrolls.min.js', ]; if (api_get_setting('accessibility_font_resize') === 'true') { @@ -747,9 +753,7 @@ class Template $selectLink, 'select2/dist/js/select2.min.js', "select2/dist/js/i18n/$isoCode.js", - 'mediaelement/plugins/vrview/vrview.js', 'js-cookie/src/js.cookie.js', - 'mediaelement/plugins/markersrolls/markersrolls.min.js', ]; $viewBySession = api_get_setting('my_courses_view_by_session') === 'true'; @@ -772,7 +776,7 @@ class Template if ($feature === 'vrview') { continue; } - $bowerJsFiles[] = "mediaelement/plugins/$feature/$feature.js"; + $js_files[] = "mediaelement/plugins/$feature/$feature.min.js"; } } diff --git a/main/template/default/layout/main.js.tpl b/main/template/default/layout/main.js.tpl index ebcea8950d..056c14e8c3 100644 --- a/main/template/default/layout/main.js.tpl +++ b/main/template/default/layout/main.js.tpl @@ -281,7 +281,7 @@ $(function() { // Mediaelement if ( {{ show_media_element }} == 1) { $('video:not(.skip), audio:not(.skip)').mediaelementplayer({ - pluginPath: _p.web + 'web/assets/mediaelement/build/', + pluginPath: _p.web_lib + 'javascript/mediaelement/', //renderers: ['html5', 'flash_video', 'native_flv'], features: ['{{ video_features }}'], success: function(mediaElement, originalNode, instance) {