summaryrefslogtreecommitdiff
path: root/www/lib/videogular-controls/vg-controls.js
diff options
context:
space:
mode:
Diffstat (limited to 'www/lib/videogular-controls/vg-controls.js')
-rw-r--r--www/lib/videogular-controls/vg-controls.js741
1 files changed, 536 insertions, 205 deletions
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));
}
}
}]