diff options
Diffstat (limited to 'www/lib/videogular-controls')
| -rw-r--r-- | www/lib/videogular-controls/.bower.json | 14 | ||||
| -rw-r--r-- | www/lib/videogular-controls/bower.json | 4 | ||||
| -rw-r--r-- | www/lib/videogular-controls/index.js | 1 | ||||
| -rw-r--r-- | www/lib/videogular-controls/package.json | 5 | ||||
| -rw-r--r-- | www/lib/videogular-controls/vg-controls.js | 741 | ||||
| -rw-r--r-- | www/lib/videogular-controls/vg-controls.min.js | 2 |
6 files changed, 551 insertions, 216 deletions
diff --git a/www/lib/videogular-controls/.bower.json b/www/lib/videogular-controls/.bower.json index 363047f2..133d2a58 100644 --- a/www/lib/videogular-controls/.bower.json +++ b/www/lib/videogular-controls/.bower.json @@ -1,19 +1,19 @@ { "name": "videogular-controls", - "version": "1.3.2", + "version": "1.4.4", "main": "./vg-controls.js", "dependencies": { - "videogular": "~1.3.2" + "videogular": "~1.4.4" }, "homepage": "https://github.com/2fdevs/bower-videogular-controls", - "_release": "1.3.2", + "_release": "1.4.4", "_resolution": { "type": "version", - "tag": "v1.3.2", - "commit": "6fa5a2cb079b995cca749573576eed82bddc3eb6" + "tag": "v1.4.4", + "commit": "07a9b7f3f4066016dcb5959da36232874d180358" }, - "_source": "git://github.com/2fdevs/bower-videogular-controls.git", - "_target": "~1.3.2", + "_source": "https://github.com/2fdevs/bower-videogular-controls.git", + "_target": "1.4.4", "_originalSource": "videogular-controls", "_direct": true }
\ No newline at end of file diff --git a/www/lib/videogular-controls/bower.json b/www/lib/videogular-controls/bower.json index 4cd2b307..91990ff5 100644 --- a/www/lib/videogular-controls/bower.json +++ b/www/lib/videogular-controls/bower.json @@ -1,8 +1,8 @@ { "name": "videogular-controls", - "version": "1.3.2", + "version": "1.4.4", "main": "./vg-controls.js", "dependencies": { - "videogular": "~1.3.2" + "videogular": "~1.4.4" } } diff --git a/www/lib/videogular-controls/index.js b/www/lib/videogular-controls/index.js index 346eb418..7c75799a 100644 --- a/www/lib/videogular-controls/index.js +++ b/www/lib/videogular-controls/index.js @@ -1,3 +1,4 @@ +require('videogular'); require('./vg-controls'); module.exports = 'com.2fdevs.videogular.plugins.controls'; diff --git a/www/lib/videogular-controls/package.json b/www/lib/videogular-controls/package.json index 195fa399..a5cc0b7a 100644 --- a/www/lib/videogular-controls/package.json +++ b/www/lib/videogular-controls/package.json @@ -1,7 +1,10 @@ { "name": "videogular-controls", - "version": "1.3.2", + "version": "1.4.4", "main": "index.js", + "dependencies": { + "videogular": "~1.4.4" + }, "devDependencies": { "grunt": "~0.4.1", "grunt-release": "~0.7.0" diff --git a/www/lib/videogular-controls/vg-controls.js b/www/lib/videogular-controls/vg-controls.js index ef0efd9a..2c79e4bb 100644 --- a/www/lib/videogular-controls/vg-controls.js +++ b/www/lib/videogular-controls/vg-controls.js @@ -1,5 +1,5 @@ /** - * @license videogular v1.3.2 http://videogular.com + * @license videogular v1.4.4 http://videogular.com * Two Fucking Developers http://twofuckingdevelopers.com * License: MIT */ @@ -108,7 +108,14 @@ angular.module("com.2fdevs.videogular.plugins.controls", []) } } - + scope.$watch( + function () { + return API.currentState; + }, + function (newVal, oldVal) { + if (scope.vgAutohide) scope.showControls(); + } + ); } } }] @@ -251,12 +258,13 @@ angular.module("com.2fdevs.videogular.plugins.controls") * @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'] * <pre> * <videogular vg-theme="config.theme.url"> * <vg-media vg-src="sources"></vg-media> * * <vg-controls vg-autohide='config.autohide' vg-autohide-time='config.autohideTime'> - * <vg-playback-button></vg-playback-button> + * <vg-playback-button vg-speeds='config.playbackSpeeds'></vg-playback-button> * </vg-controls> * </videogular> * </pre> @@ -277,6 +285,9 @@ angular.module("com.2fdevs.videogular.plugins.controls") templateUrl: function (elem, attrs) { return attrs.vgTemplate || 'vg-templates/vg-playback-button'; }, + scope: { + vgSpeeds: '=?' + }, link: function (scope, elem, attr, API) { scope.playback = '1'; @@ -286,7 +297,7 @@ angular.module("com.2fdevs.videogular.plugins.controls") }; scope.onClickPlayback = function onClickPlayback() { - var playbackOptions = ['0.5', '1', '1.5', '2']; + var playbackOptions = scope.vgSpeeds || ['0.5', '1', '1.5', '2']; var nextPlaybackRate = playbackOptions.indexOf(scope.playback.toString()) + 1; if (nextPlaybackRate >= playbackOptions.length) { @@ -313,6 +324,7 @@ angular.module("com.2fdevs.videogular.plugins.controls") } }] ); + /** * @ngdoc directive * @name com.2fdevs.videogular.plugins.controls.directive:vgScrubBarBuffer @@ -385,67 +397,67 @@ angular.module("com.2fdevs.videogular.plugins.controls") * */ angular.module("com.2fdevs.videogular.plugins.controls") - .run( - ["$templateCache", function ($templateCache) { - $templateCache.put("vg-templates/vg-scrub-bar-cue-points", - '<div class="cue-point-timeline" ng-style="timelineWidth">' + - '<div ng-repeat="cuePoint in vgCuePoints" class="cue-point" ng-style="cuePoint.$$style"></div>' + - '</div>'); - }] -) - .directive("vgScrubBarCuePoints", - [function () { - return { - restrict: "E", - require: "^videogular", - templateUrl: function (elem, attrs) { - return attrs.vgTemplate || 'vg-templates/vg-scrub-bar-cue-points'; - }, - scope: { - "vgCuePoints": "=" - }, - link: function (scope, elem, attr, API) { - scope.onPlayerReady = function onPlayerReady() { - scope.updateCuePoints(scope.vgCuePoints); - }; - - scope.updateCuePoints = function onUpdateCuePoints(cuePoints) { - var totalWidth; - - if (cuePoints) { - totalWidth = parseInt(elem[0].clientWidth); - - for (var i = 0, l = cuePoints.length; i < l; i++) { - var cuePointDuration = (cuePoints[i].timeLapse.end - cuePoints[i].timeLapse.start) * 1000; - var position = (cuePoints[i].timeLapse.start * 100 / API.totalTime * 1000) + "%"; - var percentWidth = 0; - - if (typeof cuePointDuration === 'number' && API.totalTime) { - percentWidth = ((cuePointDuration * 100) / API.totalTime) + "%"; + .run(["$templateCache", + function ($templateCache) { + $templateCache.put("vg-templates/vg-scrub-bar-cue-points", + '<div class="cue-point-timeline">' + + '<div ng-repeat="cuePoint in vgCuePoints" class="cue-point" ng-style="cuePoint.$$style"></div>' + + '</div>'); + } + ]) + .directive("vgScrubBarCuePoints", [ + function () { + return { + restrict: "E", + require: "^videogular", + templateUrl: function (elem, attrs) { + return attrs.vgTemplate || 'vg-templates/vg-scrub-bar-cue-points'; + }, + scope: { + "vgCuePoints": "=" + }, + link: function (scope, elem, attr, API) { + scope.onPlayerReady = function onPlayerReady() { + scope.updateCuePoints(scope.vgCuePoints); + }; + scope.updateCuePoints = function onUpdateCuePoints(cuePoints) { + var totalWidth; + + if (cuePoints) { + totalWidth = parseInt(elem[0].clientWidth); + + for (var i = 0, l = cuePoints.length; i < l; i++) { + var end = (cuePoints[i].timeLapse.end >= 0) ? cuePoints[i].timeLapse.end : cuePoints[i].timeLapse.start + 1; + var cuePointDuration = (end - cuePoints[i].timeLapse.start) * 1000; + var position = (cuePoints[i].timeLapse.start * 100 / (Math.round(API.totalTime / 1000))) + "%"; + var percentWidth = 0; + + if (typeof cuePointDuration === 'number' && API.totalTime) { + percentWidth = ((cuePointDuration * 100) / API.totalTime) + "%"; + } + + cuePoints[i].$$style = { + width: percentWidth, + left: position + }; } - - cuePoints[i].$$style = { - width: percentWidth, - left: position - }; } - } - }; + }; - scope.$watch("vgCuePoints", scope.updateCuePoints); + scope.$watch("vgCuePoints", scope.updateCuePoints); - scope.$watch( - function () { - return API.totalTime; - }, - function (newVal, oldVal) { - if (newVal > 0) scope.onPlayerReady(); - } - ); + scope.$watch( + function () { + return API.totalTime; + }, + function (newVal, oldVal) { + if (newVal > 0) scope.onPlayerReady(); + } + ); + } } } - }] -); + ]); /** * @ngdoc directive @@ -500,6 +512,240 @@ angular.module("com.2fdevs.videogular.plugins.controls") /** * @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" + * } + * } + * ] + * + * <pre> + * <videogular vg-theme="config.theme.url"> + * <vg-media vg-src="sources"></vg-media> + * + * <vg-controls> + * <vg-scrub-bar> + * <vg-scrub-bar-thumbnails vg-thumbnails='config.thumbnails'></vg-scrub-bar-thumbnails> + * </vg-scrub-bar> + * </vg-controls> + * </videogular> + * </pre> + * + */ +angular.module("com.2fdevs.videogular.plugins.controls") + .run(["$templateCache", + function ($templateCache) { + $templateCache.put("vg-templates/vg-scrub-bar-thumbnails", + '<div class="vg-thumbnails" ng-show="thumbnails" ng-style="thumbnailContainer">' + + '<div class="image-thumbnail" ng-style="thumbnails"></div>' + + '</div>' + + '<div class="background"></div>' + ); + } + ]) + .directive("vgScrubBarThumbnails", ["VG_UTILS", + function (VG_UTILS) { + return { + restrict: "E", + require: "^videogular", + templateUrl: function (elem, attrs) { + return attrs.vgTemplate || 'vg-templates/vg-scrub-bar-thumbnails'; + }, + scope: { + "vgThumbnails": "=" + }, + link: function (scope, elem, attr, API) { + var thumbnailsWidth = 0; + var thumbWidth = 0; + var slider = elem[0].querySelector(".background"); + var isStrip = (typeof scope.vgThumbnails === "string"); + + scope.thumbnails = false; + scope.thumbnailContainer = {}; + + scope.getOffset = function getOffset(event) { + var el = event.target, + x = 0; + + while (el && !isNaN(el.offsetLeft)) { + x += el.offsetLeft - el.scrollLeft; + el = el.offsetParent; + } + + return event.clientX - x; + }; + + scope.onLoadThumbnails = function(event) { + thumbnailsWidth = event.currentTarget.naturalWidth; + thumbWidth = thumbnailsWidth / 100; + }; + + scope.onLoadThumbnail = function(event) { + thumbWidth = event.currentTarget.naturalWidth; + }; + + scope.updateThumbnails = function(second) { + var percentage = Math.round(second * 100 / (API.totalTime / 1000)); + var thPos = (slider.scrollWidth * percentage / 100) - (thumbWidth / 2); + + if (isStrip) { + var bgPos = Math.round(thumbnailsWidth * percentage / 100); + + scope.thumbnailContainer = { + "width": thumbWidth + "px", + "left": thPos + "px" + }; + + scope.thumbnails = { + "background-image": 'url("' + scope.vgThumbnails + '")', + "background-position": -bgPos + "px 0px" + }; + } + else { + var secondsByPixel = API.totalTime / slider.scrollWidth / 1000; + var lapse = { + start: Math.floor(second - (secondsByPixel / 2)), + end: Math.ceil(second) + }; + + if (lapse.start < 0) lapse.start = 0; + if (lapse.end > API.totalTime) lapse.end = API.totalTime; + + scope.thumbnailContainer = { + "left": thPos + "px" + }; + + scope.thumbnails = { + "background-image": 'none' + }; + + if (scope.vgThumbnails) { + for (var i=0, l=scope.vgThumbnails.length; i<l; i++) { + var th = scope.vgThumbnails[i]; + + if (th.timeLapse.end >= 0) { + if (lapse.start >= th.timeLapse.start && (lapse.end <= th.timeLapse.end || lapse.end <= th.timeLapse.start)) { + scope.thumbnails = { + "background-image": 'url("' + th.params.thumbnail + '")' + }; + break; + } + } + else { + if (th.timeLapse.start >= lapse.start && th.timeLapse.start <= lapse.end) { + scope.thumbnails = { + "background-image": 'url("' + th.params.thumbnail + '")' + }; + break; + } + } + } + } + } + }; + + scope.onMouseMove = function($event) { + var second = Math.round($event.offsetX * API.mediaElement[0].duration / slider.scrollWidth); + + scope.updateThumbnails(second); + + scope.$digest(); + }; + + scope.onTouchMove = function($event) { + var touches = $event.touches; + var touchX = scope.getOffset(touches[0]); + var second = Math.round(touchX * API.mediaElement[0].duration / slider.scrollWidth); + + scope.updateThumbnails(second); + + scope.$digest(); + }; + + scope.onMouseLeave = function(event) { + scope.thumbnails = false; + + scope.$digest(); + }; + + scope.onTouchLeave = function(event) { + scope.thumbnails = false; + + scope.$digest(); + }; + + scope.onDestroy = function() { + elem.unbind("touchmove", scope.onTouchMove); + elem.unbind("touchleave", scope.onTouchLeave); + elem.unbind("touchend", scope.onTouchLeave); + elem.unbind("mousemove", scope.onMouseMove); + elem.unbind("mouseleave", scope.onMouseLeave); + }; + + var thLoader; + if (isStrip) { + thLoader = new Image(); + thLoader.onload = scope.onLoadThumbnails.bind(scope); + thLoader.src = scope.vgThumbnails; + } + else { + thLoader = new Image(); + thLoader.onload = scope.onLoadThumbnail.bind(scope); + thLoader.src = scope.vgThumbnails[0].params.thumbnail; + } + + // Touch move is really buggy in Chrome for Android, maybe we could use mouse move that works ok + if (VG_UTILS.isMobileDevice()) { + elem.bind("touchmove", scope.onTouchMove); + elem.bind("touchleave", scope.onTouchLeave); + elem.bind("touchend", scope.onTouchLeave); + } + else { + elem.bind("mousemove", scope.onMouseMove); + elem.bind("mouseleave", scope.onMouseLeave); + } + + scope.$on('destroy', scope.onDestroy.bind(scope)); + } + } + } + ]); + +/** + * @ngdoc directive * @name com.2fdevs.videogular.plugins.controls.directive:vgScrubBar * @restrict E * @description @@ -518,187 +764,261 @@ angular.module("com.2fdevs.videogular.plugins.controls") * */ angular.module("com.2fdevs.videogular.plugins.controls") - .run( - ["$templateCache", function ($templateCache) { - $templateCache.put("vg-templates/vg-scrub-bar", - '<div role="slider" aria-valuemax="{{ariaTime(API.totalTime)}}" aria-valuenow="{{ariaTime(API.currentTime)}}" aria-valuemin="0" aria-label="Time scrub bar" tabindex="0" ng-transclude ng-keydown="onScrubBarKeyDown($event)"></div>'); - }] -) - .directive("vgScrubBar", - ["VG_STATES", "VG_UTILS", function (VG_STATES, VG_UTILS) { - return { - restrict: "E", - require: "^videogular", - transclude: true, - templateUrl: function (elem, attrs) { - return attrs.vgTemplate || 'vg-templates/vg-scrub-bar'; - }, - link: function (scope, elem, attr, API) { - var isSeeking = false; - var isPlaying = false; - var isPlayingWhenSeeking = false; - var LEFT = 37; - var RIGHT = 39; - var NUM_PERCENT = 5; + .run(["$templateCache", + function ($templateCache) { + $templateCache.put("vg-templates/vg-scrub-bar", + '<div role="slider" ' + + 'aria-valuemax="{{ariaTime(API.totalTime)}}" ' + + 'aria-valuenow="{{ariaTime(API.currentTime)}}" ' + + 'aria-valuemin="0" ' + + 'aria-label="Time scrub bar" ' + + 'tabindex="0" ' + + 'ng-keydown="onScrubBarKeyDown($event)">' + + '</div>' + + '<div class="container" ng-transclude></div>' + ); + }] + ) + .directive("vgScrubBar", ["VG_STATES", "VG_UTILS", + function (VG_STATES, VG_UTILS) { + return { + restrict: "E", + require: "^videogular", + transclude: true, + templateUrl: function (elem, attrs) { + return attrs.vgTemplate || 'vg-templates/vg-scrub-bar'; + }, + scope: { + vgThumbnails: "=" + }, + link: function (scope, elem, attr, API) { + var isSeeking = false; + var isPlaying = false; + var isPlayingWhenSeeking = false; + var LEFT = 37; + var RIGHT = 39; + var NUM_PERCENT = 5; + var thumbnailsWidth = 0; + var thumbWidth = 0; + var slider = elem[0].querySelector("div[role=slider]"); + + scope.thumbnails = false; + scope.thumbnailContainer = {}; + + scope.API = API; + + scope.onLoadThumbnails = function(event) { + thumbnailsWidth = event.path[0].naturalWidth; + thumbWidth = thumbnailsWidth / 100; + }; + + scope.ariaTime = function (time) { + return Math.round(time / 1000); + }; + + scope.getOffset = function getOffset(event) { + var el = event.target, + x = 0; + + while (el && !isNaN(el.offsetLeft)) { + x += el.offsetLeft - el.scrollLeft; + el = el.offsetParent; + } - scope.API = API; - scope.ariaTime = function (time) { - return Math.round(time / 1000); - }; + return event.clientX - x; + }; - scope.getOffset = function getOffset(event) { - var el = event.target, - x = 0; + scope.onScrubBarTouchStart = function onScrubBarTouchStart($event) { + var event = $event.originalEvent || $event; + var touches = event.touches; + var touchX = scope.getOffset(touches[0]); - while (el && !isNaN(el.offsetLeft)) { - x += el.offsetLeft - el.scrollLeft; - el = el.offsetParent; - } + isSeeking = true; + if (isPlaying) isPlayingWhenSeeking = true; + API.pause(); + API.seekTime(touchX * API.mediaElement[0].duration / slider.scrollWidth); - return event.clientX - x; - }; + scope.$digest(); + }; - scope.onScrubBarTouchStart = function onScrubBarTouchStart($event) { - var event = $event.originalEvent || $event; - var touches = event.touches; - var touchX = scope.getOffset(touches[0]); + scope.onScrubBarTouchEnd = function onScrubBarTouchEnd($event) { + var event = $event.originalEvent || $event; + if (isPlayingWhenSeeking) { + isPlayingWhenSeeking = false; + API.play(); + } + isSeeking = false; - isSeeking = true; - if (isPlaying) isPlayingWhenSeeking = true; - API.pause(); - API.seekTime(touchX * API.mediaElement[0].duration / elem[0].scrollWidth); + scope.$digest(); + }; - scope.$apply(); - }; + scope.onScrubBarTouchMove = function onScrubBarTouchMove($event) { + var event = $event.originalEvent || $event; + var touches = event.touches; + var touchX = scope.getOffset(touches[0]); - scope.onScrubBarTouchEnd = function onScrubBarTouchEnd($event) { - var event = $event.originalEvent || $event; - if (isPlayingWhenSeeking) { - isPlayingWhenSeeking = false; - API.play(); - } - isSeeking = false; + if (scope.vgThumbnails && scope.vgThumbnails.length) { + var second = Math.round(touchX * API.mediaElement[0].duration / slider.scrollWidth); + var percentage = Math.round(second * 100 / (API.totalTime / 1000)); - scope.$apply(); - }; + scope.updateThumbnails(percentage); + } - scope.onScrubBarTouchMove = function onScrubBarTouchMove($event) { - var event = $event.originalEvent || $event; - var touches = event.touches; - var touchX = scope.getOffset(touches[0]); + if (isSeeking) { + API.seekTime(touchX * API.mediaElement[0].duration / slider.scrollWidth); + } - if (isSeeking) { - API.seekTime(touchX * API.mediaElement[0].duration / elem[0].scrollWidth); - } + scope.$digest(); + }; - scope.$apply(); - }; + scope.onScrubBarTouchLeave = function onScrubBarTouchLeave(event) { + isSeeking = false; + scope.thumbnails = false; - scope.onScrubBarTouchLeave = function onScrubBarTouchLeave(event) { - isSeeking = false; + scope.$digest(); + }; - scope.$apply(); - }; + scope.onScrubBarMouseDown = function onScrubBarMouseDown(event) { + event = VG_UTILS.fixEventOffset(event); - scope.onScrubBarMouseDown = function onScrubBarMouseDown(event) { - event = VG_UTILS.fixEventOffset(event); + isSeeking = true; + if (isPlaying) isPlayingWhenSeeking = true; + API.pause(); - isSeeking = true; - if (isPlaying) isPlayingWhenSeeking = true; - API.pause(); + API.seekTime(event.offsetX * API.mediaElement[0].duration / slider.scrollWidth); - API.seekTime(event.offsetX * API.mediaElement[0].duration / elem[0].scrollWidth); + scope.$digest(); + }; - scope.$apply(); - }; + scope.onScrubBarMouseUp = function onScrubBarMouseUp(event) { + //event = VG_UTILS.fixEventOffset(event); - scope.onScrubBarMouseUp = function onScrubBarMouseUp(event) { - //event = VG_UTILS.fixEventOffset(event); + if (isPlayingWhenSeeking) { + isPlayingWhenSeeking = false; + API.play(); + } + isSeeking = false; + //API.seekTime(event.offsetX * API.mediaElement[0].duration / slider.scrollWidth); - if (isPlayingWhenSeeking) { - isPlayingWhenSeeking = false; - API.play(); - } - isSeeking = false; - //API.seekTime(event.offsetX * API.mediaElement[0].duration / elem[0].scrollWidth); + scope.$digest(); + }; - scope.$apply(); - }; + scope.onScrubBarMouseMove = function onScrubBarMouseMove(event) { + if (scope.vgThumbnails && scope.vgThumbnails.length) { + var second = Math.round(event.offsetX * API.mediaElement[0].duration / slider.scrollWidth); + var percentage = Math.round(second * 100 / (API.totalTime / 1000)); - scope.onScrubBarMouseMove = function onScrubBarMouseMove(event) { - if (isSeeking) { - event = VG_UTILS.fixEventOffset(event); - API.seekTime(event.offsetX * API.mediaElement[0].duration / elem[0].scrollWidth); - } + scope.updateThumbnails(percentage); + } - scope.$apply(); - }; + if (isSeeking) { + event = VG_UTILS.fixEventOffset(event); + API.seekTime(event.offsetX * API.mediaElement[0].duration / slider.scrollWidth); + } - scope.onScrubBarMouseLeave = function onScrubBarMouseLeave(event) { - isSeeking = false; + scope.$digest(); + }; - scope.$apply(); - }; + scope.onScrubBarMouseLeave = function onScrubBarMouseLeave(event) { + isSeeking = false; + scope.thumbnails = false; - scope.onScrubBarKeyDown = function onScrubBarKeyDown(event) { - var currentPercent = (API.currentTime / API.totalTime) * 100; + scope.$digest(); + }; - if (event.which === LEFT || event.keyCode === LEFT) { - API.seekTime(currentPercent - NUM_PERCENT, true); - event.preventDefault(); - } - else if (event.which === RIGHT || event.keyCode === RIGHT) { - API.seekTime(currentPercent + NUM_PERCENT, true); - event.preventDefault(); - } - }; + scope.onScrubBarKeyDown = function onScrubBarKeyDown(event) { + var currentPercent = (API.currentTime / API.totalTime) * 100; - scope.setState = function setState(newState) { - if (!isSeeking) { - switch (newState) { - case VG_STATES.PLAY: - isPlaying = true; - break; - - case VG_STATES.PAUSE: - isPlaying = false; - break; - - case VG_STATES.STOP: - isPlaying = false; - break; + if (event.which === LEFT || event.keyCode === LEFT) { + API.seekTime(currentPercent - NUM_PERCENT, true); + event.preventDefault(); + } + else if (event.which === RIGHT || event.keyCode === RIGHT) { + API.seekTime(currentPercent + NUM_PERCENT, true); + event.preventDefault(); + } + }; + + scope.updateThumbnails = function updateThumbnails(percentage) { + var bgPos = Math.round(thumbnailsWidth * percentage / 100); + var thPos = (slider.scrollWidth * percentage / 100) - (thumbWidth / 2); + + scope.thumbnailContainer = { + "width": thumbWidth + "px", + "left": thPos + "px" + }; + + scope.thumbnails = { + "background-image": 'url("' + scope.vgThumbnails + '")', + "background-position": -bgPos + "px 0px" + }; + }; + + scope.setState = function setState(newState) { + if (!isSeeking) { + switch (newState) { + case VG_STATES.PLAY: + isPlaying = true; + break; + + case VG_STATES.PAUSE: + isPlaying = false; + break; + + case VG_STATES.STOP: + isPlaying = false; + break; + } + } + }; + + scope.onDestroy = function() { + elem.unbind("touchstart", scope.onScrubBarTouchStart); + elem.unbind("touchend", scope.onScrubBarTouchEnd); + elem.unbind("touchmove", scope.onScrubBarTouchMove); + elem.unbind("touchleave", scope.onScrubBarTouchLeave); + elem.unbind("mousedown", scope.onScrubBarMouseDown); + elem.unbind("mouseup", scope.onScrubBarMouseUp); + elem.unbind("mousemove", scope.onScrubBarMouseMove); + elem.unbind("mouseleave", scope.onScrubBarMouseLeave); + }; + + scope.$watch( + function () { + return API.currentState; + }, + function (newVal, oldVal) { + if (newVal != oldVal) { + scope.setState(newVal); + } } + ); + + if (scope.vgThumbnails) { + var thLoader = new Image(); + thLoader.onload = scope.onLoadThumbnails.bind(scope); + thLoader.src = scope.vgThumbnails; } - }; - scope.$watch( - function () { - return API.currentState; - }, - function (newVal, oldVal) { - if (newVal != oldVal) { - scope.setState(newVal); - } + // Touch move is really buggy in Chrome for Android, maybe we could use mouse move that works ok + if (VG_UTILS.isMobileDevice()) { + elem.bind("touchstart", scope.onScrubBarTouchStart); + elem.bind("touchend", scope.onScrubBarTouchEnd); + elem.bind("touchmove", scope.onScrubBarTouchMove); + elem.bind("touchleave", scope.onScrubBarTouchLeave); + } + else { + elem.bind("mousedown", scope.onScrubBarMouseDown); + elem.bind("mouseup", scope.onScrubBarMouseUp); + elem.bind("mousemove", scope.onScrubBarMouseMove); + elem.bind("mouseleave", scope.onScrubBarMouseLeave); } - ); - // Touch move is really buggy in Chrome for Android, maybe we could use mouse move that works ok - if (VG_UTILS.isMobileDevice()) { - elem.bind("touchstart", scope.onScrubBarTouchStart); - elem.bind("touchend", scope.onScrubBarTouchEnd); - elem.bind("touchmove", scope.onScrubBarTouchMove); - elem.bind("touchleave", scope.onScrubBarTouchLeave); - } - else { - elem.bind("mousedown", scope.onScrubBarMouseDown); - elem.bind("mouseup", scope.onScrubBarMouseUp); - elem.bind("mousemove", scope.onScrubBarMouseMove); - elem.bind("mouseleave", scope.onScrubBarMouseLeave); + scope.$on('destroy', scope.onDestroy.bind(scope)); } } } - }] -); + ]); /** * @ngdoc directive @@ -799,7 +1119,7 @@ angular.module("com.2fdevs.videogular.plugins.controls") .run( ["$templateCache", function ($templateCache) { $templateCache.put("vg-templates/vg-mute-button", - '<button type="button" class="iconButton" ng-class="muteIcon" ng-click="onClickMute()" ng-focus="onMuteButtonFocus()" ng-blur="onMuteButtonLoseFocus()" ng-keydown="onMuteButtonKeyDown($event)" aria-label="Mute"></button>'); + '<button type="button" class="iconButton" ng-class="muteIcon" ng-click="onClickMute()" ng-focus="onMuteButtonFocus()" ng-blur="onMuteButtonLoseFocus()" ng-mouseleave="onMuteButtonLeave()" ng-keydown="onMuteButtonKeyDown($event)" aria-label="Mute"></button>'); }] ) .directive("vgMuteButton", @@ -838,6 +1158,10 @@ angular.module("com.2fdevs.videogular.plugins.controls") 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; @@ -1061,6 +1385,11 @@ angular.module("com.2fdevs.videogular.plugins.controls") }); }; + 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"); @@ -1071,6 +1400,8 @@ angular.module("com.2fdevs.videogular.plugins.controls") elem.bind("mouseover", scope.onMouseOverVolume); elem.bind("mouseleave", scope.onMouseLeaveVolume); } + + scope.$on('destroy', scope.onDestroy.bind(scope)); } } }] diff --git a/www/lib/videogular-controls/vg-controls.min.js b/www/lib/videogular-controls/vg-controls.min.js index 07fa4c65..27d47e4a 100644 --- a/www/lib/videogular-controls/vg-controls.min.js +++ b/www/lib/videogular-controls/vg-controls.min.js @@ -1 +1 @@ -"use strict";angular.module("com.2fdevs.videogular.plugins.controls",[]).run(["$templateCache",function(a){a.put("vg-templates/vg-controls",'<div class="controls-container" ng-mousemove="onMouseMove()" ng-class="animationClass" ng-transclude></div>')}]).directive("vgControls",["$timeout","VG_STATES",function(a,b){return{restrict:"E",require:"^videogular",transclude:!0,templateUrl:function(a,b){return b.vgTemplate||"vg-templates/vg-controls"},scope:{vgAutohide:"=?",vgAutohideTime:"=?"},link:function(c,d,e,f){var g,h=2e3;c.API=f,c.onMouseMove=function(){c.vgAutohide&&c.showControls()},c.setAutohide=function(d){d&&f.currentState==b.PLAY?g=a(c.hideControls,h):(c.animationClass="",a.cancel(g),c.showControls())},c.setAutohideTime=function(a){h=a},c.hideControls=function(){c.animationClass="hide-animation"},c.showControls=function(){c.animationClass="show-animation",a.cancel(g),c.vgAutohide&&f.currentState==b.PLAY&&(g=a(c.hideControls,h))},f.isConfig?c.$watch("API.config",function(){if(c.API.config){var a=c.API.config.plugins.controls.autohide||!1,b=c.API.config.plugins.controls.autohideTime||2e3;c.vgAutohide=a,c.vgAutohideTime=b,c.setAutohideTime(b),c.setAutohide(a)}}):(void 0!=c.vgAutohide&&c.$watch("vgAutohide",c.setAutohide),void 0!=c.vgAutohideTime&&c.$watch("vgAutohideTime",c.setAutohideTime))}}}]),angular.module("com.2fdevs.videogular.plugins.controls").run(["$templateCache",function(a){a.put("vg-templates/vg-fullscreen-button",'<button class="iconButton" ng-click="onClickFullScreen()" ng-class="fullscreenIcon" aria-label="Toggle full screen" type="button"> </button>')}]).directive("vgFullscreenButton",[function(){return{restrict:"E",require:"^videogular",scope:{},templateUrl:function(a,b){return b.vgTemplate||"vg-templates/vg-fullscreen-button"},link:function(a,b,c,d){a.onChangeFullScreen=function(b){a.fullscreenIcon={enter:!b,exit:b}},a.onClickFullScreen=function(){d.toggleFullScreen()},a.fullscreenIcon={enter:!0},a.$watch(function(){return d.isFullScreen},function(b,c){b!=c&&a.onChangeFullScreen(b)})}}}]),angular.module("com.2fdevs.videogular.plugins.controls").run(["$templateCache",function(a){a.put("vg-templates/vg-play-pause-button",'<button class="iconButton" ng-click="onClickPlayPause()" ng-class="playPauseIcon" aria-label="Play/Pause" type="button"></button>')}]).directive("vgPlayPauseButton",["VG_STATES",function(a){return{restrict:"E",require:"^videogular",scope:{},templateUrl:function(a,b){return b.vgTemplate||"vg-templates/vg-play-pause-button"},link:function(b,c,d,e){b.setState=function(c){switch(c){case a.PLAY:b.playPauseIcon={pause:!0};break;case a.PAUSE:b.playPauseIcon={play:!0};break;case a.STOP:b.playPauseIcon={play:!0}}},b.onClickPlayPause=function(){e.playPause()},b.playPauseIcon={play:!0},b.$watch(function(){return e.currentState},function(a,c){b.setState(a)})}}}]),angular.module("com.2fdevs.videogular.plugins.controls").run(["$templateCache",function(a){a.put("vg-templates/vg-playback-button",'<button class="playbackValue iconButton" ng-click="onClickPlayback()">{{playback}}x</button>')}]).directive("vgPlaybackButton",[function(){return{restrict:"E",require:"^videogular",templateUrl:function(a,b){return b.vgTemplate||"vg-templates/vg-playback-button"},link:function(a,b,c,d){a.playback="1",a.setPlayback=function(b){a.playback=b,d.setPlayback(parseFloat(b))},a.onClickPlayback=function(){var b=["0.5","1","1.5","2"],c=b.indexOf(a.playback.toString())+1;c>=b.length?a.playback=b[0]:a.playback=b[c],a.setPlayback(a.playback)},a.$watch(function(){return d.playback},function(b,c){b!=c&&a.setPlayback(b)})}}}]),angular.module("com.2fdevs.videogular.plugins.controls").directive("vgScrubBarBuffer",[function(){return{restrict:"E",require:"^videogular",link:function(a,b,c,d){var e=0;a.onUpdateBuffer=function(a){"number"==typeof a&&d.totalTime?(e=100*(a/d.totalTime),b.css("width",e+"%")):b.css("width",0)},a.$watch(function(){return d.bufferEnd},function(b,c){a.onUpdateBuffer(b)})}}}]),angular.module("com.2fdevs.videogular.plugins.controls").run(["$templateCache",function(a){a.put("vg-templates/vg-scrub-bar-cue-points",'<div class="cue-point-timeline" ng-style="timelineWidth"><div ng-repeat="cuePoint in vgCuePoints" class="cue-point" ng-style="cuePoint.$$style"></div></div>')}]).directive("vgScrubBarCuePoints",[function(){return{restrict:"E",require:"^videogular",templateUrl:function(a,b){return b.vgTemplate||"vg-templates/vg-scrub-bar-cue-points"},scope:{vgCuePoints:"="},link:function(a,b,c,d){a.onPlayerReady=function(){a.updateCuePoints(a.vgCuePoints)},a.updateCuePoints=function(a){var c;if(a){c=parseInt(b[0].clientWidth);for(var e=0,f=a.length;f>e;e++){var g=1e3*(a[e].timeLapse.end-a[e].timeLapse.start),h=100*a[e].timeLapse.start/d.totalTime*1e3+"%",i=0;"number"==typeof g&&d.totalTime&&(i=100*g/d.totalTime+"%"),a[e].$$style={width:i,left:h}}}},a.$watch("vgCuePoints",a.updateCuePoints),a.$watch(function(){return d.totalTime},function(b,c){b>0&&a.onPlayerReady()})}}}]),angular.module("com.2fdevs.videogular.plugins.controls").directive("vgScrubBarCurrentTime",[function(){return{restrict:"E",require:"^videogular",link:function(a,b,c,d){var e=0;a.onUpdateTime=function(a){"number"==typeof a&&d.totalTime?(e=100*(a/d.totalTime),b.css("width",e+"%")):b.css("width",0)},a.$watch(function(){return d.currentTime},function(b,c){a.onUpdateTime(b)})}}}]),angular.module("com.2fdevs.videogular.plugins.controls").run(["$templateCache",function(a){a.put("vg-templates/vg-scrub-bar",'<div role="slider" aria-valuemax="{{ariaTime(API.totalTime)}}" aria-valuenow="{{ariaTime(API.currentTime)}}" aria-valuemin="0" aria-label="Time scrub bar" tabindex="0" ng-transclude ng-keydown="onScrubBarKeyDown($event)"></div>')}]).directive("vgScrubBar",["VG_STATES","VG_UTILS",function(a,b){return{restrict:"E",require:"^videogular",transclude:!0,templateUrl:function(a,b){return b.vgTemplate||"vg-templates/vg-scrub-bar"},link:function(c,d,e,f){var g=!1,h=!1,i=!1,j=37,k=39,l=5;c.API=f,c.ariaTime=function(a){return Math.round(a/1e3)},c.getOffset=function(a){for(var b=a.target,c=0;b&&!isNaN(b.offsetLeft);)c+=b.offsetLeft-b.scrollLeft,b=b.offsetParent;return a.clientX-c},c.onScrubBarTouchStart=function(a){var b=a.originalEvent||a,e=b.touches,j=c.getOffset(e[0]);g=!0,h&&(i=!0),f.pause(),f.seekTime(j*f.mediaElement[0].duration/d[0].scrollWidth),c.$apply()},c.onScrubBarTouchEnd=function(a){a.originalEvent||a;i&&(i=!1,f.play()),g=!1,c.$apply()},c.onScrubBarTouchMove=function(a){var b=a.originalEvent||a,e=b.touches,h=c.getOffset(e[0]);g&&f.seekTime(h*f.mediaElement[0].duration/d[0].scrollWidth),c.$apply()},c.onScrubBarTouchLeave=function(a){g=!1,c.$apply()},c.onScrubBarMouseDown=function(a){a=b.fixEventOffset(a),g=!0,h&&(i=!0),f.pause(),f.seekTime(a.offsetX*f.mediaElement[0].duration/d[0].scrollWidth),c.$apply()},c.onScrubBarMouseUp=function(a){i&&(i=!1,f.play()),g=!1,c.$apply()},c.onScrubBarMouseMove=function(a){g&&(a=b.fixEventOffset(a),f.seekTime(a.offsetX*f.mediaElement[0].duration/d[0].scrollWidth)),c.$apply()},c.onScrubBarMouseLeave=function(a){g=!1,c.$apply()},c.onScrubBarKeyDown=function(a){var b=f.currentTime/f.totalTime*100;a.which===j||a.keyCode===j?(f.seekTime(b-l,!0),a.preventDefault()):(a.which===k||a.keyCode===k)&&(f.seekTime(b+l,!0),a.preventDefault())},c.setState=function(b){if(!g)switch(b){case a.PLAY:h=!0;break;case a.PAUSE:h=!1;break;case a.STOP:h=!1}},c.$watch(function(){return f.currentState},function(a,b){a!=b&&c.setState(a)}),b.isMobileDevice()?(d.bind("touchstart",c.onScrubBarTouchStart),d.bind("touchend",c.onScrubBarTouchEnd),d.bind("touchmove",c.onScrubBarTouchMove),d.bind("touchleave",c.onScrubBarTouchLeave)):(d.bind("mousedown",c.onScrubBarMouseDown),d.bind("mouseup",c.onScrubBarMouseUp),d.bind("mousemove",c.onScrubBarMouseMove),d.bind("mouseleave",c.onScrubBarMouseLeave))}}}]),angular.module("com.2fdevs.videogular.plugins.controls").directive("vgTimeDisplay",[function(){return{require:"^videogular",restrict:"E",link:function(a,b,c,d){a.currentTime=d.currentTime,a.timeLeft=d.timeLeft,a.totalTime=d.totalTime,a.isLive=d.isLive,a.$watch(function(){return d.currentTime},function(b,c){a.currentTime=b}),a.$watch(function(){return d.timeLeft},function(b,c){a.timeLeft=b}),a.$watch(function(){return d.totalTime},function(b,c){a.totalTime=b}),a.$watch(function(){return d.isLive},function(b,c){a.isLive=b})}}}]),angular.module("com.2fdevs.videogular.plugins.controls").run(["$templateCache",function(a){a.put("vg-templates/vg-mute-button",'<button type="button" class="iconButton" ng-class="muteIcon" ng-click="onClickMute()" ng-focus="onMuteButtonFocus()" ng-blur="onMuteButtonLoseFocus()" ng-keydown="onMuteButtonKeyDown($event)" aria-label="Mute"></button>')}]).directive("vgMuteButton",[function(){return{restrict:"E",require:"^videogular",templateUrl:function(a,b){return b.vgTemplate||"vg-templates/vg-mute-button"},link:function(a,b,c,d){var e=!1,f=38,g=40,h=.05;a.onClickMute=function(){e?a.currentVolume=a.defaultVolume:(a.currentVolume=0,a.muteIcon={mute:!0}),e=!e,d.setVolume(a.currentVolume)},a.onMuteButtonFocus=function(){a.volumeVisibility="visible"},a.onMuteButtonLoseFocus=function(){a.volumeVisibility="hidden"},a.onMuteButtonKeyDown=function(a){var b,c=null!=d.volume?d.volume:1;a.which===f||a.keyCode===f?(b=c+h,b>1&&(b=1),d.setVolume(b),a.preventDefault()):(a.which===g||a.keyCode===g)&&(b=c-h,0>b&&(b=0),d.setVolume(b),a.preventDefault())},a.onSetVolume=function(b){a.currentVolume=b,e=0===a.currentVolume,e?b>0&&(a.defaultVolume=b):a.defaultVolume=b;var c=Math.round(100*b);0==c?a.muteIcon={mute:!0}:c>0&&25>c?a.muteIcon={level0:!0}:c>=25&&50>c?a.muteIcon={level1:!0}:c>=50&&75>c?a.muteIcon={level2:!0}:c>=75&&(a.muteIcon={level3:!0})},a.defaultVolume=1,a.currentVolume=a.defaultVolume,a.muteIcon={level3:!0},a.onSetVolume(d.volume),a.$watch(function(){return d.volume},function(b,c){b!=c&&a.onSetVolume(b)})}}}]),angular.module("com.2fdevs.videogular.plugins.controls").run(["$templateCache",function(a){a.put("vg-templates/vg-volume-bar",'<div class="verticalVolumeBar"> <div class="volumeBackground" ng-click="onClickVolume($event)" ng-mousedown="onMouseDownVolume()" ng-mouseup="onMouseUpVolume()" ng-mousemove="onMouseMoveVolume($event)" ng-mouseleave="onMouseLeaveVolume()"> <div class="volumeValue"></div> <div class="volumeClickArea"></div> </div> </div>')}]).directive("vgVolumeBar",["VG_UTILS",function(a){return{restrict:"E",require:"^videogular",templateUrl:function(a,b){return b.vgTemplate||"vg-templates/vg-volume-bar"},link:function(b,c,d,e){var f=!1,g=angular.element(c[0].getElementsByClassName("volumeBackground")),h=angular.element(c[0].getElementsByClassName("volumeValue"));b.onClickVolume=function(b){b=a.fixEventOffset(b);var c=parseInt(g.prop("offsetHeight")),d=100*b.offsetY/c,f=1-d/100;e.setVolume(f)},b.onMouseDownVolume=function(){f=!0},b.onMouseUpVolume=function(){f=!1},b.onMouseLeaveVolume=function(){f=!1},b.onMouseMoveVolume=function(b){if(f){b=a.fixEventOffset(b);var c=parseInt(g.prop("offsetHeight")),d=100*b.offsetY/c,h=1-d/100;e.setVolume(h)}},b.updateVolumeView=function(a){a=100*a,h.css("height",a+"%"),h.css("top",100-a+"%")},b.onChangeVisibility=function(a){c.css("visibility",a)},c.css("visibility",b.volumeVisibility),b.$watch("volumeVisibility",b.onChangeVisibility),b.updateVolumeView(e.volume),b.$watch(function(){return e.volume},function(a,c){a!=c&&b.updateVolumeView(a)})}}}]),angular.module("com.2fdevs.videogular.plugins.controls").directive("vgVolume",["VG_UTILS",function(a){return{restrict:"E",link:function(b,c,d){b.onMouseOverVolume=function(){b.$evalAsync(function(){b.volumeVisibility="visible"})},b.onMouseLeaveVolume=function(){b.$evalAsync(function(){b.volumeVisibility="hidden"})},a.isMobileDevice()?c.css("display","none"):(b.volumeVisibility="hidden",c.bind("mouseover",b.onMouseOverVolume),c.bind("mouseleave",b.onMouseLeaveVolume))}}}]);
\ No newline at end of file +"use strict";angular.module("com.2fdevs.videogular.plugins.controls",[]).run(["$templateCache",function(a){a.put("vg-templates/vg-controls",'<div class="controls-container" ng-mousemove="onMouseMove()" ng-class="animationClass" ng-transclude></div>')}]).directive("vgControls",["$timeout","VG_STATES",function(a,b){return{restrict:"E",require:"^videogular",transclude:!0,templateUrl:function(a,b){return b.vgTemplate||"vg-templates/vg-controls"},scope:{vgAutohide:"=?",vgAutohideTime:"=?"},link:function(c,d,e,f){var g,h=2e3;c.API=f,c.onMouseMove=function(){c.vgAutohide&&c.showControls()},c.setAutohide=function(d){d&&f.currentState==b.PLAY?g=a(c.hideControls,h):(c.animationClass="",a.cancel(g),c.showControls())},c.setAutohideTime=function(a){h=a},c.hideControls=function(){c.animationClass="hide-animation"},c.showControls=function(){c.animationClass="show-animation",a.cancel(g),c.vgAutohide&&f.currentState==b.PLAY&&(g=a(c.hideControls,h))},f.isConfig?c.$watch("API.config",function(){if(c.API.config){var a=c.API.config.plugins.controls.autohide||!1,b=c.API.config.plugins.controls.autohideTime||2e3;c.vgAutohide=a,c.vgAutohideTime=b,c.setAutohideTime(b),c.setAutohide(a)}}):(void 0!=c.vgAutohide&&c.$watch("vgAutohide",c.setAutohide),void 0!=c.vgAutohideTime&&c.$watch("vgAutohideTime",c.setAutohideTime)),c.$watch(function(){return f.currentState},function(a,b){c.vgAutohide&&c.showControls()})}}}]),angular.module("com.2fdevs.videogular.plugins.controls").run(["$templateCache",function(a){a.put("vg-templates/vg-fullscreen-button",'<button class="iconButton" ng-click="onClickFullScreen()" ng-class="fullscreenIcon" aria-label="Toggle full screen" type="button"> </button>')}]).directive("vgFullscreenButton",[function(){return{restrict:"E",require:"^videogular",scope:{},templateUrl:function(a,b){return b.vgTemplate||"vg-templates/vg-fullscreen-button"},link:function(a,b,c,d){a.onChangeFullScreen=function(b){a.fullscreenIcon={enter:!b,exit:b}},a.onClickFullScreen=function(){d.toggleFullScreen()},a.fullscreenIcon={enter:!0},a.$watch(function(){return d.isFullScreen},function(b,c){b!=c&&a.onChangeFullScreen(b)})}}}]),angular.module("com.2fdevs.videogular.plugins.controls").run(["$templateCache",function(a){a.put("vg-templates/vg-play-pause-button",'<button class="iconButton" ng-click="onClickPlayPause()" ng-class="playPauseIcon" aria-label="Play/Pause" type="button"></button>')}]).directive("vgPlayPauseButton",["VG_STATES",function(a){return{restrict:"E",require:"^videogular",scope:{},templateUrl:function(a,b){return b.vgTemplate||"vg-templates/vg-play-pause-button"},link:function(b,c,d,e){b.setState=function(c){switch(c){case a.PLAY:b.playPauseIcon={pause:!0};break;case a.PAUSE:b.playPauseIcon={play:!0};break;case a.STOP:b.playPauseIcon={play:!0}}},b.onClickPlayPause=function(){e.playPause()},b.playPauseIcon={play:!0},b.$watch(function(){return e.currentState},function(a,c){b.setState(a)})}}}]),angular.module("com.2fdevs.videogular.plugins.controls").run(["$templateCache",function(a){a.put("vg-templates/vg-playback-button",'<button class="playbackValue iconButton" ng-click="onClickPlayback()">{{playback}}x</button>')}]).directive("vgPlaybackButton",[function(){return{restrict:"E",require:"^videogular",templateUrl:function(a,b){return b.vgTemplate||"vg-templates/vg-playback-button"},scope:{vgSpeeds:"=?"},link:function(a,b,c,d){a.playback="1",a.setPlayback=function(b){a.playback=b,d.setPlayback(parseFloat(b))},a.onClickPlayback=function(){var b=a.vgSpeeds||["0.5","1","1.5","2"],c=b.indexOf(a.playback.toString())+1;c>=b.length?a.playback=b[0]:a.playback=b[c],a.setPlayback(a.playback)},a.$watch(function(){return d.playback},function(b,c){b!=c&&a.setPlayback(b)})}}}]),angular.module("com.2fdevs.videogular.plugins.controls").directive("vgScrubBarBuffer",[function(){return{restrict:"E",require:"^videogular",link:function(a,b,c,d){var e=0;a.onUpdateBuffer=function(a){"number"==typeof a&&d.totalTime?(e=100*(a/d.totalTime),b.css("width",e+"%")):b.css("width",0)},a.$watch(function(){return d.bufferEnd},function(b,c){a.onUpdateBuffer(b)})}}}]),angular.module("com.2fdevs.videogular.plugins.controls").run(["$templateCache",function(a){a.put("vg-templates/vg-scrub-bar-cue-points",'<div class="cue-point-timeline"><div ng-repeat="cuePoint in vgCuePoints" class="cue-point" ng-style="cuePoint.$$style"></div></div>')}]).directive("vgScrubBarCuePoints",[function(){return{restrict:"E",require:"^videogular",templateUrl:function(a,b){return b.vgTemplate||"vg-templates/vg-scrub-bar-cue-points"},scope:{vgCuePoints:"="},link:function(a,b,c,d){a.onPlayerReady=function(){a.updateCuePoints(a.vgCuePoints)},a.updateCuePoints=function(a){var c;if(a){c=parseInt(b[0].clientWidth);for(var e=0,f=a.length;f>e;e++){var g=a[e].timeLapse.end>=0?a[e].timeLapse.end:a[e].timeLapse.start+1,h=1e3*(g-a[e].timeLapse.start),i=100*a[e].timeLapse.start/Math.round(d.totalTime/1e3)+"%",j=0;"number"==typeof h&&d.totalTime&&(j=100*h/d.totalTime+"%"),a[e].$$style={width:j,left:i}}}},a.$watch("vgCuePoints",a.updateCuePoints),a.$watch(function(){return d.totalTime},function(b,c){b>0&&a.onPlayerReady()})}}}]),angular.module("com.2fdevs.videogular.plugins.controls").directive("vgScrubBarCurrentTime",[function(){return{restrict:"E",require:"^videogular",link:function(a,b,c,d){var e=0;a.onUpdateTime=function(a){"number"==typeof a&&d.totalTime?(e=100*(a/d.totalTime),b.css("width",e+"%")):b.css("width",0)},a.$watch(function(){return d.currentTime},function(b,c){a.onUpdateTime(b)})}}}]),angular.module("com.2fdevs.videogular.plugins.controls").run(["$templateCache",function(a){a.put("vg-templates/vg-scrub-bar-thumbnails",'<div class="vg-thumbnails" ng-show="thumbnails" ng-style="thumbnailContainer"><div class="image-thumbnail" ng-style="thumbnails"></div></div><div class="background"></div>')}]).directive("vgScrubBarThumbnails",["VG_UTILS",function(a){return{restrict:"E",require:"^videogular",templateUrl:function(a,b){return b.vgTemplate||"vg-templates/vg-scrub-bar-thumbnails"},scope:{vgThumbnails:"="},link:function(b,c,d,e){var f=0,g=0,h=c[0].querySelector(".background"),i="string"==typeof b.vgThumbnails;b.thumbnails=!1,b.thumbnailContainer={},b.getOffset=function(a){for(var b=a.target,c=0;b&&!isNaN(b.offsetLeft);)c+=b.offsetLeft-b.scrollLeft,b=b.offsetParent;return a.clientX-c},b.onLoadThumbnails=function(a){f=a.currentTarget.naturalWidth,g=f/100},b.onLoadThumbnail=function(a){g=a.currentTarget.naturalWidth},b.updateThumbnails=function(a){var c=Math.round(100*a/(e.totalTime/1e3)),d=h.scrollWidth*c/100-g/2;if(i){var j=Math.round(f*c/100);b.thumbnailContainer={width:g+"px",left:d+"px"},b.thumbnails={"background-image":'url("'+b.vgThumbnails+'")',"background-position":-j+"px 0px"}}else{var k=e.totalTime/h.scrollWidth/1e3,l={start:Math.floor(a-k/2),end:Math.ceil(a)};if(l.start<0&&(l.start=0),l.end>e.totalTime&&(l.end=e.totalTime),b.thumbnailContainer={left:d+"px"},b.thumbnails={"background-image":"none"},b.vgThumbnails)for(var m=0,n=b.vgThumbnails.length;n>m;m++){var o=b.vgThumbnails[m];if(o.timeLapse.end>=0){if(l.start>=o.timeLapse.start&&(l.end<=o.timeLapse.end||l.end<=o.timeLapse.start)){b.thumbnails={"background-image":'url("'+o.params.thumbnail+'")'};break}}else if(o.timeLapse.start>=l.start&&o.timeLapse.start<=l.end){b.thumbnails={"background-image":'url("'+o.params.thumbnail+'")'};break}}}},b.onMouseMove=function(a){var c=Math.round(a.offsetX*e.mediaElement[0].duration/h.scrollWidth);b.updateThumbnails(c),b.$digest()},b.onTouchMove=function(a){var c=a.touches,d=b.getOffset(c[0]),f=Math.round(d*e.mediaElement[0].duration/h.scrollWidth);b.updateThumbnails(f),b.$digest()},b.onMouseLeave=function(a){b.thumbnails=!1,b.$digest()},b.onTouchLeave=function(a){b.thumbnails=!1,b.$digest()},b.onDestroy=function(){c.unbind("touchmove",b.onTouchMove),c.unbind("touchleave",b.onTouchLeave),c.unbind("touchend",b.onTouchLeave),c.unbind("mousemove",b.onMouseMove),c.unbind("mouseleave",b.onMouseLeave)};var j;i?(j=new Image,j.onload=b.onLoadThumbnails.bind(b),j.src=b.vgThumbnails):(j=new Image,j.onload=b.onLoadThumbnail.bind(b),j.src=b.vgThumbnails[0].params.thumbnail),a.isMobileDevice()?(c.bind("touchmove",b.onTouchMove),c.bind("touchleave",b.onTouchLeave),c.bind("touchend",b.onTouchLeave)):(c.bind("mousemove",b.onMouseMove),c.bind("mouseleave",b.onMouseLeave)),b.$on("destroy",b.onDestroy.bind(b))}}}]),angular.module("com.2fdevs.videogular.plugins.controls").run(["$templateCache",function(a){a.put("vg-templates/vg-scrub-bar",'<div role="slider" aria-valuemax="{{ariaTime(API.totalTime)}}" aria-valuenow="{{ariaTime(API.currentTime)}}" aria-valuemin="0" aria-label="Time scrub bar" tabindex="0" ng-keydown="onScrubBarKeyDown($event)"></div><div class="container" ng-transclude></div>')}]).directive("vgScrubBar",["VG_STATES","VG_UTILS",function(a,b){return{restrict:"E",require:"^videogular",transclude:!0,templateUrl:function(a,b){return b.vgTemplate||"vg-templates/vg-scrub-bar"},scope:{vgThumbnails:"="},link:function(c,d,e,f){var g=!1,h=!1,i=!1,j=37,k=39,l=5,m=0,n=0,o=d[0].querySelector("div[role=slider]");if(c.thumbnails=!1,c.thumbnailContainer={},c.API=f,c.onLoadThumbnails=function(a){m=a.path[0].naturalWidth,n=m/100},c.ariaTime=function(a){return Math.round(a/1e3)},c.getOffset=function(a){for(var b=a.target,c=0;b&&!isNaN(b.offsetLeft);)c+=b.offsetLeft-b.scrollLeft,b=b.offsetParent;return a.clientX-c},c.onScrubBarTouchStart=function(a){var b=a.originalEvent||a,d=b.touches,e=c.getOffset(d[0]);g=!0,h&&(i=!0),f.pause(),f.seekTime(e*f.mediaElement[0].duration/o.scrollWidth),c.$digest()},c.onScrubBarTouchEnd=function(a){a.originalEvent||a;i&&(i=!1,f.play()),g=!1,c.$digest()},c.onScrubBarTouchMove=function(a){var b=a.originalEvent||a,d=b.touches,e=c.getOffset(d[0]);if(c.vgThumbnails&&c.vgThumbnails.length){var h=Math.round(e*f.mediaElement[0].duration/o.scrollWidth),i=Math.round(100*h/(f.totalTime/1e3));c.updateThumbnails(i)}g&&f.seekTime(e*f.mediaElement[0].duration/o.scrollWidth),c.$digest()},c.onScrubBarTouchLeave=function(a){g=!1,c.thumbnails=!1,c.$digest()},c.onScrubBarMouseDown=function(a){a=b.fixEventOffset(a),g=!0,h&&(i=!0),f.pause(),f.seekTime(a.offsetX*f.mediaElement[0].duration/o.scrollWidth),c.$digest()},c.onScrubBarMouseUp=function(a){i&&(i=!1,f.play()),g=!1,c.$digest()},c.onScrubBarMouseMove=function(a){if(c.vgThumbnails&&c.vgThumbnails.length){var d=Math.round(a.offsetX*f.mediaElement[0].duration/o.scrollWidth),e=Math.round(100*d/(f.totalTime/1e3));c.updateThumbnails(e)}g&&(a=b.fixEventOffset(a),f.seekTime(a.offsetX*f.mediaElement[0].duration/o.scrollWidth)),c.$digest()},c.onScrubBarMouseLeave=function(a){g=!1,c.thumbnails=!1,c.$digest()},c.onScrubBarKeyDown=function(a){var b=f.currentTime/f.totalTime*100;a.which===j||a.keyCode===j?(f.seekTime(b-l,!0),a.preventDefault()):(a.which===k||a.keyCode===k)&&(f.seekTime(b+l,!0),a.preventDefault())},c.updateThumbnails=function(a){var b=Math.round(m*a/100),d=o.scrollWidth*a/100-n/2;c.thumbnailContainer={width:n+"px",left:d+"px"},c.thumbnails={"background-image":'url("'+c.vgThumbnails+'")',"background-position":-b+"px 0px"}},c.setState=function(b){if(!g)switch(b){case a.PLAY:h=!0;break;case a.PAUSE:h=!1;break;case a.STOP:h=!1}},c.onDestroy=function(){d.unbind("touchstart",c.onScrubBarTouchStart),d.unbind("touchend",c.onScrubBarTouchEnd),d.unbind("touchmove",c.onScrubBarTouchMove),d.unbind("touchleave",c.onScrubBarTouchLeave),d.unbind("mousedown",c.onScrubBarMouseDown),d.unbind("mouseup",c.onScrubBarMouseUp),d.unbind("mousemove",c.onScrubBarMouseMove),d.unbind("mouseleave",c.onScrubBarMouseLeave)},c.$watch(function(){return f.currentState},function(a,b){a!=b&&c.setState(a)}),c.vgThumbnails){var p=new Image;p.onload=c.onLoadThumbnails.bind(c),p.src=c.vgThumbnails}b.isMobileDevice()?(d.bind("touchstart",c.onScrubBarTouchStart),d.bind("touchend",c.onScrubBarTouchEnd),d.bind("touchmove",c.onScrubBarTouchMove),d.bind("touchleave",c.onScrubBarTouchLeave)):(d.bind("mousedown",c.onScrubBarMouseDown),d.bind("mouseup",c.onScrubBarMouseUp),d.bind("mousemove",c.onScrubBarMouseMove),d.bind("mouseleave",c.onScrubBarMouseLeave)),c.$on("destroy",c.onDestroy.bind(c))}}}]),angular.module("com.2fdevs.videogular.plugins.controls").directive("vgTimeDisplay",[function(){return{require:"^videogular",restrict:"E",link:function(a,b,c,d){a.currentTime=d.currentTime,a.timeLeft=d.timeLeft,a.totalTime=d.totalTime,a.isLive=d.isLive,a.$watch(function(){return d.currentTime},function(b,c){a.currentTime=b}),a.$watch(function(){return d.timeLeft},function(b,c){a.timeLeft=b}),a.$watch(function(){return d.totalTime},function(b,c){a.totalTime=b}),a.$watch(function(){return d.isLive},function(b,c){a.isLive=b})}}}]),angular.module("com.2fdevs.videogular.plugins.controls").run(["$templateCache",function(a){a.put("vg-templates/vg-mute-button",'<button type="button" class="iconButton" ng-class="muteIcon" ng-click="onClickMute()" ng-focus="onMuteButtonFocus()" ng-blur="onMuteButtonLoseFocus()" ng-mouseleave="onMuteButtonLeave()" ng-keydown="onMuteButtonKeyDown($event)" aria-label="Mute"></button>')}]).directive("vgMuteButton",[function(){return{restrict:"E",require:"^videogular",templateUrl:function(a,b){return b.vgTemplate||"vg-templates/vg-mute-button"},link:function(a,b,c,d){var e=!1,f=38,g=40,h=.05;a.onClickMute=function(){e?a.currentVolume=a.defaultVolume:(a.currentVolume=0,a.muteIcon={mute:!0}),e=!e,d.setVolume(a.currentVolume)},a.onMuteButtonFocus=function(){a.volumeVisibility="visible"},a.onMuteButtonLoseFocus=function(){a.volumeVisibility="hidden"},a.onMuteButtonLeave=function(){document.activeElement.blur()},a.onMuteButtonKeyDown=function(a){var b,c=null!=d.volume?d.volume:1;a.which===f||a.keyCode===f?(b=c+h,b>1&&(b=1),d.setVolume(b),a.preventDefault()):(a.which===g||a.keyCode===g)&&(b=c-h,0>b&&(b=0),d.setVolume(b),a.preventDefault())},a.onSetVolume=function(b){a.currentVolume=b,e=0===a.currentVolume,e?b>0&&(a.defaultVolume=b):a.defaultVolume=b;var c=Math.round(100*b);0==c?a.muteIcon={mute:!0}:c>0&&25>c?a.muteIcon={level0:!0}:c>=25&&50>c?a.muteIcon={level1:!0}:c>=50&&75>c?a.muteIcon={level2:!0}:c>=75&&(a.muteIcon={level3:!0})},a.defaultVolume=1,a.currentVolume=a.defaultVolume,a.muteIcon={level3:!0},a.onSetVolume(d.volume),a.$watch(function(){return d.volume},function(b,c){b!=c&&a.onSetVolume(b)})}}}]),angular.module("com.2fdevs.videogular.plugins.controls").run(["$templateCache",function(a){a.put("vg-templates/vg-volume-bar",'<div class="verticalVolumeBar"> <div class="volumeBackground" ng-click="onClickVolume($event)" ng-mousedown="onMouseDownVolume()" ng-mouseup="onMouseUpVolume()" ng-mousemove="onMouseMoveVolume($event)" ng-mouseleave="onMouseLeaveVolume()"> <div class="volumeValue"></div> <div class="volumeClickArea"></div> </div> </div>')}]).directive("vgVolumeBar",["VG_UTILS",function(a){return{restrict:"E",require:"^videogular",templateUrl:function(a,b){return b.vgTemplate||"vg-templates/vg-volume-bar"},link:function(b,c,d,e){var f=!1,g=angular.element(c[0].getElementsByClassName("volumeBackground")),h=angular.element(c[0].getElementsByClassName("volumeValue"));b.onClickVolume=function(b){b=a.fixEventOffset(b);var c=parseInt(g.prop("offsetHeight")),d=100*b.offsetY/c,f=1-d/100;e.setVolume(f)},b.onMouseDownVolume=function(){f=!0},b.onMouseUpVolume=function(){f=!1},b.onMouseLeaveVolume=function(){f=!1},b.onMouseMoveVolume=function(b){if(f){b=a.fixEventOffset(b);var c=parseInt(g.prop("offsetHeight")),d=100*b.offsetY/c,h=1-d/100;e.setVolume(h)}},b.updateVolumeView=function(a){a=100*a,h.css("height",a+"%"),h.css("top",100-a+"%")},b.onChangeVisibility=function(a){c.css("visibility",a)},c.css("visibility",b.volumeVisibility),b.$watch("volumeVisibility",b.onChangeVisibility),b.updateVolumeView(e.volume),b.$watch(function(){return e.volume},function(a,c){a!=c&&b.updateVolumeView(a)})}}}]),angular.module("com.2fdevs.videogular.plugins.controls").directive("vgVolume",["VG_UTILS",function(a){return{restrict:"E",link:function(b,c,d){b.onMouseOverVolume=function(){b.$evalAsync(function(){b.volumeVisibility="visible"})},b.onMouseLeaveVolume=function(){b.$evalAsync(function(){b.volumeVisibility="hidden"})},b.onDestroy=function(){c.unbind("mouseover",b.onScrubBarTouchStart),c.unbind("mouseleave",b.onScrubBarTouchEnd)},a.isMobileDevice()?c.css("display","none"):(b.volumeVisibility="hidden",c.bind("mouseover",b.onMouseOverVolume),c.bind("mouseleave",b.onMouseLeaveVolume)),b.$on("destroy",b.onDestroy.bind(b))}}}]);
\ No newline at end of file |
