/** * @license videogular v1.4.4 http://videogular.com * Two Fucking Developers http://twofuckingdevelopers.com * License: MIT */ /** * @ngdoc directive * @name com.2fdevs.videogular.plugins.controls.directive:vgControls * @restrict E * @description * This directive acts as a container and you will need other directives to control the media. * Inside this directive you can add other directives like vg-play-pause-button and vg-scrub-bar. * *
** * @param {boolean=false} vgAutohide Boolean variable or value to activate autohide. * @param {number=2000} vgAutohideTime Number variable or value that represents the time in milliseconds that will wait vgControls until it hides. * * */ "use strict"; angular.module("com.2fdevs.videogular.plugins.controls", []) .run( ["$templateCache", function ($templateCache) { $templateCache.put("vg-templates/vg-controls", ''); }] ) .directive("vgControls", ["$timeout", "VG_STATES", function ($timeout, VG_STATES) { return { restrict: "E", require: "^videogular", transclude: true, templateUrl: function (elem, attrs) { return attrs.vgTemplate || 'vg-templates/vg-controls'; }, scope: { vgAutohide: "=?", vgAutohideTime: "=?" }, link: function (scope, elem, attr, API) { var w = 0; var h = 0; var autoHideTime = 2000; var hideInterval; scope.API = API; scope.onMouseMove = function onMouseMove() { if (scope.vgAutohide) scope.showControls(); }; scope.setAutohide = function setAutohide(value) { if (value && API.currentState == VG_STATES.PLAY) { hideInterval = $timeout(scope.hideControls, autoHideTime); } else { scope.animationClass = ""; $timeout.cancel(hideInterval); scope.showControls(); } }; scope.setAutohideTime = function setAutohideTime(value) { autoHideTime = value; }; scope.hideControls = function hideControls() { scope.animationClass = "hide-animation"; }; scope.showControls = function showControls() { scope.animationClass = "show-animation"; $timeout.cancel(hideInterval); if (scope.vgAutohide && API.currentState == VG_STATES.PLAY) hideInterval = $timeout(scope.hideControls, autoHideTime); }; if (API.isConfig) { scope.$watch("API.config", function () { if (scope.API.config) { var ahValue = scope.API.config.plugins.controls.autohide || false; var ahtValue = scope.API.config.plugins.controls.autohideTime || 2000; scope.vgAutohide = ahValue; scope.vgAutohideTime = ahtValue; scope.setAutohideTime(ahtValue); scope.setAutohide(ahValue); } } ); } else { // If vg-autohide has been set if (scope.vgAutohide != undefined) { scope.$watch("vgAutohide", scope.setAutohide); } // If vg-autohide-time has been set if (scope.vgAutohideTime != undefined) { scope.$watch("vgAutohideTime", scope.setAutohideTime); } } scope.$watch( function () { return API.currentState; }, function (newVal, oldVal) { if (scope.vgAutohide) scope.showControls(); } ); } } }] ); /** * @ngdoc directive * @name com.2fdevs.videogular.plugins.controls.directive:vgFullscreenButton * @restrict E * @description * Directive to switch between fullscreen and normal mode. * ** ** * *
** */ angular.module("com.2fdevs.videogular.plugins.controls") .run( ["$templateCache", function ($templateCache) { $templateCache.put("vg-templates/vg-fullscreen-button", ''); }] ) .directive("vgFullscreenButton", [function () { return { restrict: "E", require: "^videogular", scope: {}, templateUrl: function (elem, attrs) { return attrs.vgTemplate || 'vg-templates/vg-fullscreen-button'; }, link: function (scope, elem, attr, API) { scope.onChangeFullScreen = function onChangeFullScreen(isFullScreen) { scope.fullscreenIcon = {enter: !isFullScreen, exit: isFullScreen}; }; scope.onClickFullScreen = function onClickFullScreen() { API.toggleFullScreen(); }; scope.fullscreenIcon = {enter: true}; scope.$watch( function () { return API.isFullScreen; }, function (newVal, oldVal) { if (newVal != oldVal) { scope.onChangeFullScreen(newVal); } } ); } } }] ); /** * @ngdoc directive * @name com.2fdevs.videogular.plugins.controls.directive:vgPlayPauseButton * @restrict E * @description * Adds a button inside vg-controls to play and pause media. * ** ** * * **
** */ angular.module("com.2fdevs.videogular.plugins.controls") .run( ["$templateCache", function ($templateCache) { $templateCache.put("vg-templates/vg-play-pause-button", ''); }] ) .directive("vgPlayPauseButton", ["VG_STATES", function (VG_STATES) { return { restrict: "E", require: "^videogular", scope: {}, templateUrl: function (elem, attrs) { return attrs.vgTemplate || 'vg-templates/vg-play-pause-button'; }, link: function (scope, elem, attr, API) { scope.setState = function setState(newState) { switch (newState) { case VG_STATES.PLAY: scope.playPauseIcon = {pause: true}; break; case VG_STATES.PAUSE: scope.playPauseIcon = {play: true}; break; case VG_STATES.STOP: scope.playPauseIcon = {play: true}; break; } }; scope.onClickPlayPause = function onClickPlayPause() { API.playPause(); }; scope.playPauseIcon = {play: true}; scope.$watch( function () { return API.currentState; }, function (newVal, oldVal) { scope.setState(newVal); } ); } } }] ); /** * @ngdoc directive * @name com.2fdevs.videogular.plugins.controls.directive:ngPlaybackButton * @restrict E * @description * Directive to display a playback buttom to control the playback rate. * * @param {array} vgSpeeds Bindable array with a list of speed options as strings. Default ['0.5', '1', '1.5', '2'] ** ** * * **
** */ angular.module("com.2fdevs.videogular.plugins.controls") .run( ["$templateCache", function ($templateCache) { $templateCache.put("vg-templates/vg-playback-button", ''); }] ) .directive("vgPlaybackButton", [function () { return { restrict: "E", require: "^videogular", templateUrl: function (elem, attrs) { return attrs.vgTemplate || 'vg-templates/vg-playback-button'; }, scope: { vgSpeeds: '=?' }, link: function (scope, elem, attr, API) { scope.playback = '1'; scope.setPlayback = function(playback) { scope.playback = playback; API.setPlayback(parseFloat(playback)); }; scope.onClickPlayback = function onClickPlayback() { var playbackOptions = scope.vgSpeeds || ['0.5', '1', '1.5', '2']; var nextPlaybackRate = playbackOptions.indexOf(scope.playback.toString()) + 1; if (nextPlaybackRate >= playbackOptions.length) { scope.playback = playbackOptions[0]; } else { scope.playback = playbackOptions[nextPlaybackRate]; } scope.setPlayback(scope.playback); }; scope.$watch( function () { return API.playback; }, function(newVal, oldVal) { if (newVal != oldVal) { scope.setPlayback(newVal); } } ); } } }] ); /** * @ngdoc directive * @name com.2fdevs.videogular.plugins.controls.directive:vgScrubBarBuffer * @restrict E * @description * Layer inside vg-scrub-bar to display the buffer. * ** ** * * **
** */ angular.module("com.2fdevs.videogular.plugins.controls") .directive("vgScrubBarBuffer", [function () { return { restrict: "E", require: "^videogular", link: function (scope, elem, attr, API) { var percentTime = 0; scope.onUpdateBuffer = function onUpdateBuffer(newBuffer) { if (typeof newBuffer === 'number' && API.totalTime) { percentTime = 100 * (newBuffer / API.totalTime); elem.css("width", percentTime + "%"); } else { elem.css("width", 0); } }; scope.$watch( function () { return API.bufferEnd; }, function (newVal, oldVal) { scope.onUpdateBuffer(newVal); } ); } } }] ); /** * @ngdoc directive * @name com.2fdevs.videogular.plugins.controls.directive:vgScrubBarCuePoints * @restrict E * @description * Layer inside vg-scrub-bar to display a cue point timeline. * ** ** * * ** **
** */ angular.module("com.2fdevs.videogular.plugins.controls") .run(["$templateCache", function ($templateCache) { $templateCache.put("vg-templates/vg-scrub-bar-cue-points", '* ** * * ** **
** */ angular.module("com.2fdevs.videogular.plugins.controls") .directive("vgScrubBarCurrentTime", [function () { return { restrict: "E", require: "^videogular", link: function (scope, elem, attr, API) { var percentTime = 0; scope.onUpdateTime = function onUpdateTime(newCurrentTime) { if (typeof newCurrentTime === 'number' && API.totalTime) { percentTime = 100 * (newCurrentTime / API.totalTime); elem.css("width", percentTime + "%"); } else { elem.css("width", 0); } }; scope.$watch( function () { return API.currentTime; }, function (newVal, oldVal) { scope.onUpdateTime(newVal); } ); } } }] ); /** * @ngdoc directive * @name com.2fdevs.videogular.plugins.controls.directive:vgScrubBarThumbnails * @restrict E * @description * Layer inside vg-scrub-bar to display thumbnails. * * Param thumbnails could be a string url pointing to a strip of thumbnails or an array of objects with the same * format that you can find in cue points. * * **Strip of thumbnails** * Must be an image with exactly 100 thumbnails. Recommended size per each thumbnail 107x60 * Example of param value: "assets/images/strip-of-thumbnails.jpg" * * To create a strip of thumbnails you can use ffmpeg: * ffmpeg -loglevel panic -y -i app/assets/videos/videogular.mp4 -frames 1 -q:v 1 -vf * "select=not(mod(n\,29)),scale=-1:60,tile=100x1" app/assets/thumbnails/thumbnail.jpg * * **List of thumbnails** * Array with a list of cue points as images. You can specify start or a lapse with start and end. * Example of param value: * * [ * { * "timeLapse": { * "start": 5 * }, * params: { * "thumbnail": "assets/thumbnails/thumbnail-shown-at-second-5.jpg" * } * }, * { * "timeLapse": { * "start": 49, * "end": 60 * }, * "params": { * "thumbnail": "assets/thumbnails/thumbnail-shown-between-seconds-49-and-60.jpg" * } * } * ] * ** ** * * ** **
** */ angular.module("com.2fdevs.videogular.plugins.controls") .run(["$templateCache", function ($templateCache) { $templateCache.put("vg-templates/vg-scrub-bar-thumbnails", '* ** * * ** **
** */ angular.module("com.2fdevs.videogular.plugins.controls") .run(["$templateCache", function ($templateCache) { $templateCache.put("vg-templates/vg-scrub-bar", '* ** * * **
** */ angular.module("com.2fdevs.videogular.plugins.controls") .directive("vgTimeDisplay", [function () { return { require: "^videogular", restrict: "E", link: function (scope, elem, attr, API) { scope.currentTime = API.currentTime; scope.timeLeft = API.timeLeft; scope.totalTime = API.totalTime; scope.isLive = API.isLive; scope.$watch( function () { return API.currentTime; }, function (newVal, oldVal) { scope.currentTime = newVal; } ); scope.$watch( function () { return API.timeLeft; }, function (newVal, oldVal) { scope.timeLeft = newVal; } ); scope.$watch( function () { return API.totalTime; }, function (newVal, oldVal) { scope.totalTime = newVal; } ); scope.$watch( function () { return API.isLive; }, function (newVal, oldVal) { scope.isLive = newVal; } ); } } }] ); /** * @ngdoc directive * @name com.2fdevs.videogular.plugins.controls.directive:vgMuteButton * @restrict E * @description * Directive to display a button to mute volume. * ** ** * * *{{currentTime | date:'hh:mm'}} *{{timeLeft | date:'mm:ss'}} *{{totalTime | date:'hh:mm:ss'}} *
** */ angular.module("com.2fdevs.videogular.plugins.controls") .run( ["$templateCache", function ($templateCache) { $templateCache.put("vg-templates/vg-mute-button", ''); }] ) .directive("vgMuteButton", [function () { return { restrict: "E", require: "^videogular", templateUrl: function (elem, attrs) { return attrs.vgTemplate || 'vg-templates/vg-mute-button'; }, link: function (scope, elem, attr, API) { var isMuted = false; var UP = 38; var DOWN = 40; var CHANGE_PER_PRESS = 0.05; scope.onClickMute = function onClickMute() { if (isMuted) { scope.currentVolume = scope.defaultVolume; } else { scope.currentVolume = 0; scope.muteIcon = {mute: true}; } isMuted = !isMuted; API.setVolume(scope.currentVolume); }; scope.onMuteButtonFocus = function onMuteButtonFocus() { scope.volumeVisibility = "visible"; }; scope.onMuteButtonLoseFocus = function onMuteButtonLoseFocus() { scope.volumeVisibility = "hidden"; }; scope.onMuteButtonLeave = function onMuteButtonLeave() { document.activeElement.blur(); }; scope.onMuteButtonKeyDown = function onMuteButtonKeyDown(event) { var currentVolume = (API.volume != null) ? API.volume : 1; var newVolume; if (event.which === UP || event.keyCode === UP) { newVolume = currentVolume + CHANGE_PER_PRESS; if (newVolume > 1) newVolume = 1; API.setVolume(newVolume); event.preventDefault(); } else if (event.which === DOWN || event.keyCode === DOWN) { newVolume = currentVolume - CHANGE_PER_PRESS; if (newVolume < 0) newVolume = 0; API.setVolume(newVolume); event.preventDefault(); } }; scope.onSetVolume = function onSetVolume(newVolume) { scope.currentVolume = newVolume; isMuted = (scope.currentVolume === 0); // if it's not muted we save the default volume if (!isMuted) { scope.defaultVolume = newVolume; } else { // if was muted but the user changed the volume if (newVolume > 0) { scope.defaultVolume = newVolume; } } var percentValue = Math.round(newVolume * 100); if (percentValue == 0) { scope.muteIcon = {mute: true}; } else if (percentValue > 0 && percentValue < 25) { scope.muteIcon = {level0: true}; } else if (percentValue >= 25 && percentValue < 50) { scope.muteIcon = {level1: true}; } else if (percentValue >= 50 && percentValue < 75) { scope.muteIcon = {level2: true}; } else if (percentValue >= 75) { scope.muteIcon = {level3: true}; } }; scope.defaultVolume = 1; scope.currentVolume = scope.defaultVolume; scope.muteIcon = {level3: true}; //Update the mute button on initialization, then watch for changes scope.onSetVolume(API.volume); scope.$watch( function () { return API.volume; }, function (newVal, oldVal) { if (newVal != oldVal) { scope.onSetVolume(newVal); } } ); } } }] ); /** * @ngdoc directive * @name com.2fdevs.videogular.plugins.controls.directive:vgVolumeBar * @restrict E * @description * Directive to display a vertical volume bar to control the volume. * This directive must be inside vg-volume directive and requires vg-mute-button to be displayed. * ** ** * * ** **
** */ angular.module("com.2fdevs.videogular.plugins.controls") .run( ["$templateCache", function ($templateCache) { $templateCache.put("vg-templates/vg-volume-bar", '* ** * * ** ** *
** */ angular.module("com.2fdevs.videogular.plugins.controls") .directive("vgVolume", ["VG_UTILS", function (VG_UTILS) { return { restrict: "E", link: function (scope, elem, attr) { scope.onMouseOverVolume = function onMouseOverVolume() { scope.$evalAsync(function () { scope.volumeVisibility = "visible"; }); }; scope.onMouseLeaveVolume = function onMouseLeaveVolume() { scope.$evalAsync(function () { scope.volumeVisibility = "hidden"; }); }; scope.onDestroy = function() { elem.unbind("mouseover", scope.onScrubBarTouchStart); elem.unbind("mouseleave", scope.onScrubBarTouchEnd); }; // We hide volume controls on mobile devices if (VG_UTILS.isMobileDevice()) { elem.css("display", "none"); } else { scope.volumeVisibility = "hidden"; elem.bind("mouseover", scope.onMouseOverVolume); elem.bind("mouseleave", scope.onMouseLeaveVolume); } scope.$on('destroy', scope.onDestroy.bind(scope)); } } }] );* ** * * **