pyc-website
main website for pyc inc.
git clone https://9o.is/git/pyc-website.git
videogular-controls.js
(14907B)
1 /**
2 * @license Videogular v0.4.0 http://videogular.com
3 * Two Fucking Developers http://twofuckingdevelopers.com
4 * License: MIT
5 */
6 "use strict";
7 angular.module("com.2fdevs.videogular.plugins.controls", [])
8 .directive(
9 "vgControls",
10 ["$timeout", "VG_STATES", "VG_EVENTS", function($timeout, VG_STATES, VG_EVENTS){
11 return {
12 restrict: "E",
13 require: "^videogular",
14 transclude: true,
15 template: '<div id="controls-container" ng-show="isReady" ng-class="animationClass" ng-transclude></div>',
16 scope: {
17 autoHide: "=vgAutohide",
18 autoHideTime: "=vgAutohideTime"
19 },
20 link: function(scope, elem, attr, API) {
21 var w = 0;
22 var h = 0;
23 var autoHideTime = 2000;
24 var controlBarHeight = elem[0].style.height;
25 var hideInterval;
26 var isReadyInterval;
27
28 scope.isReady = false;
29
30 function onUpdateSize(target, params) {
31 w = params[0];
32 h = params[1];
33
34 elem.css("top", (parseInt(h, 10) - parseInt(controlBarHeight, 10)) + "px");
35 }
36
37 function onMouseMove() {
38 showControls();
39 scope.$apply();
40 }
41
42 function hideControls() {
43 scope.animationClass = "hide-animation";
44 }
45
46 function showControls() {
47 scope.animationClass = "show-animation";
48 $timeout.cancel(hideInterval);
49 if (scope.autoHide) hideInterval = $timeout(hideControls, autoHideTime);
50 }
51
52 function onPlayerReady() {
53 var size = API.getSize();
54
55 elem.css("top", (parseInt(size.height, 10) - parseInt(controlBarHeight, 10)) + "px");
56 isReadyInterval = $timeout(showWhenIsReady, 500);
57 }
58
59 function showWhenIsReady() {
60 $timeout.cancel(isReadyInterval);
61 scope.isReady = true;
62 }
63
64 // If vg-autohide has been set
65 if (scope.autoHide != undefined) {
66 scope.$watch("autoHide", function(value) {
67 if (value) {
68 scope.animationClass = "hide-animation";
69 API.videogularElement.bind("mousemove", onMouseMove);
70 }
71 else {
72 scope.animationClass = "";
73 $timeout.cancel(hideInterval);
74 API.videogularElement.unbind("mousemove", onMouseMove);
75 showControls();
76 }
77 });
78 }
79
80 // If vg-autohide-time has been set
81 if (scope.autoHideTime != undefined) {
82 scope.$watch("autoHideTime", function(value) {
83 autoHideTime = value;
84 });
85 }
86
87 API.$on(VG_EVENTS.ON_UPDATE_SIZE, onUpdateSize);
88
89 if (API.isPlayerReady()) onPlayerReady();
90 else API.$on(VG_EVENTS.ON_PLAYER_READY, onPlayerReady);
91 }
92 }
93 }
94 ])
95 .directive(
96 "vgPlayPauseButton",
97 ["VG_STATES", "VG_EVENTS", function(VG_STATES, VG_EVENTS) {
98 return {
99 restrict: "E",
100 require: "^videogular",
101 template: "<i class='fa fa-play fa-2x text-white' ng-class='playPauseIcon'></i>",
102 link: function(scope, elem, attr, API) {
103 function onChangeState(target, params) {
104 switch (params[0]) {
105 case VG_STATES.PLAY:
106 scope.playPauseIcon = {pause: true};
107 break;
108
109 case VG_STATES.PAUSE:
110 scope.playPauseIcon = {play: true};
111 break;
112
113 case VG_STATES.STOP:
114 scope.playPauseIcon = {play: true};
115 break;
116 }
117 }
118
119 function onClickPlayPause() {
120 API.playPause();
121 scope.$apply();
122 }
123
124 scope.playPauseIcon = {play: true};
125
126 elem.bind("click", onClickPlayPause);
127 API.$on(VG_EVENTS.ON_SET_STATE, onChangeState);
128 }
129 }
130 }
131 ])
132 .directive(
133 "vgTimedisplay",
134 ["VG_EVENTS", function(VG_EVENTS){
135 return {
136 require: "^videogular",
137 restrict: "E",
138 link: function(scope, elem, attr, API) {
139 var showHours = false;
140 var totalTimeUnparsed = 0;
141
142 function parseTime(time) {
143 var hours = Math.floor(time / 3600);
144 var mins = Math.floor((time % 3600) / 60);
145 var secs = Math.floor(time % 60);
146
147 return {hours: hours, mins: mins, secs: secs};
148 }
149
150 function displayTime(h, m, s) {
151 var displayTime = '';
152
153 var hh = h < 10 ? "0" + h : h;
154 var mm = m < 10 ? "0" + m : m;
155 var ss = s < 10 ? "0" + s : s;
156
157 if (showHours || h > 0) {
158 displayTime += hh + ':';
159 }
160
161 return displayTime + mm + ':' + ss;
162 }
163
164 function onUpdateTime(target, params) {
165 var time = parseTime(params[0]);
166 var timeLeft = parseTime(totalTimeUnparsed - params[0]);
167
168 scope.currentTime = displayTime(time.hours, time.mins, time.secs);
169 scope.timeLeft = displayTime(timeLeft.hours, timeLeft.mins, timeLeft.secs);
170 }
171
172 function onComplete(target, params) {
173 scope.currentTime = "00:00";
174 }
175
176 function onStartPlaying(target, params) {
177 totalTimeUnparsed = params[0];
178
179 var time = parseTime(totalTimeUnparsed);
180
181 showHours = (time.hours > 0);
182
183 scope.totalTime = displayTime(time.hours, time.mins, time.secs);
184 }
185
186 scope.currentTime = "00:00";
187 scope.totalTime = "00:00";
188
189 API.$on(VG_EVENTS.ON_START_PLAYING, onStartPlaying);
190 API.$on(VG_EVENTS.ON_UPDATE_TIME, onUpdateTime);
191 API.$on(VG_EVENTS.ON_COMPLETE, onComplete);
192 }
193 }
194 }
195 ])
196 .directive(
197 "vgScrubbar",
198 ["VG_EVENTS", "VG_STATES", "VG_UTILS", function(VG_EVENTS, VG_STATES, VG_UTILS){
199 return {
200 restrict: "AE",
201 require: "^videogular",
202 replace: true,
203 link: function(scope, elem, attr, API) {
204 var isSeeking = false;
205 var isPlaying = false;
206 var isPlayingWhenSeeking = false;
207 var touchStartX = 0;
208
209 function onScrubBarTouchStart(event) {
210 var touches = event.originalEvent.touches;
211 var touchX;
212
213 if (VG_UTILS.isiOSDevice()) {
214 touchStartX = (touches[0].clientX - event.originalEvent.layerX) * -1;
215 }
216 else {
217 touchStartX = event.originalEvent.layerX;
218 }
219
220 touchX = touches[0].clientX + touchStartX - touches[0].target.offsetLeft;
221
222 isSeeking = true;
223 if (isPlaying) isPlayingWhenSeeking = true;
224 seekTime(touchX * API.videoElement[0].duration / elem[0].scrollWidth);
225 API.pause();
226 }
227 function onScrubBarTouchEnd(event) {
228 if (isPlayingWhenSeeking) {
229 isPlayingWhenSeeking = false;
230 API.play();
231 }
232 isSeeking = false;
233 }
234 function onScrubBarTouchMove(event) {
235 var touches = event.originalEvent.touches;
236 var touchX;
237
238 if (isSeeking) {
239 touchX = touches[0].clientX + touchStartX - touches[0].target.offsetLeft;
240 seekTime(touchX * API.videoElement[0].duration / elem[0].scrollWidth);
241 }
242 }
243 function onScrubBarTouchLeave(event) {
244 isSeeking = false;
245 }
246
247 function onScrubBarMouseDown(event) {
248 event = VG_UTILS.fixEventOffset(event);
249
250 isSeeking = true;
251 if (isPlaying) isPlayingWhenSeeking = true;
252 seekTime(event.offsetX * API.videoElement[0].duration / elem[0].scrollWidth);
253 API.pause();
254 }
255 function onScrubBarMouseUp(event) {
256 event = VG_UTILS.fixEventOffset(event);
257
258 if (isPlayingWhenSeeking) {
259 isPlayingWhenSeeking = false;
260 API.play();
261 }
262 isSeeking = false;
263 seekTime(event.offsetX * API.videoElement[0].duration / elem[0].scrollWidth);
264 }
265 function onScrubBarMouseMove(event) {
266 if (isSeeking) {
267 event = VG_UTILS.fixEventOffset(event);
268 seekTime(event.offsetX * API.videoElement[0].duration / elem[0].scrollWidth);
269 }
270 }
271 function onScrubBarMouseLeave(event) {
272 isSeeking = false;
273 }
274 function seekTime(time) {
275 API.seekTime(time, false);
276 }
277
278 function onChangeState(target, params) {
279 if (!isSeeking) {
280 switch (params[0]) {
281 case VG_STATES.PLAY:
282 isPlaying = true;
283 break;
284
285 case VG_STATES.PAUSE:
286 isPlaying = false;
287 break;
288
289 case VG_STATES.STOP:
290 isPlaying = false;
291 break;
292 }
293 }
294 }
295
296 API.$on(VG_EVENTS.ON_SET_STATE, onChangeState);
297
298 // Touch move is really buggy in Chrome for Android, maybe we could use mouse move that works ok
299 if (VG_UTILS.isMobileDevice()) {
300 elem.bind("touchstart", onScrubBarTouchStart);
301 elem.bind("touchend", onScrubBarTouchEnd);
302 elem.bind("touchmove", onScrubBarTouchMove);
303 elem.bind("touchleave", onScrubBarTouchLeave);
304 }
305 else {
306 elem.bind("mousedown", onScrubBarMouseDown);
307 elem.bind("mouseup", onScrubBarMouseUp);
308 elem.bind("mousemove", onScrubBarMouseMove);
309 elem.bind("mouseleave", onScrubBarMouseLeave);
310 }
311 }
312 }
313 }
314 ])
315 .directive(
316 "vgScrubbarcurrenttime",
317 ["VG_EVENTS", function(VG_EVENTS){
318 return {
319 restrict: "E",
320 require: "^videogular",
321 link: function(scope, elem, attr, API) {
322 var percentTime = 0;
323
324 function onUpdateTime(target, params){
325 percentTime = Math.round((params[0] / params[1]) * 100);
326 elem.css("width", percentTime + "%");
327 scope.$apply();
328 }
329
330 function onComplete(target, params){
331 percentTime = 0;
332 elem.css("width", percentTime + "%");
333 }
334
335 API.$on(VG_EVENTS.ON_UPDATE_TIME, onUpdateTime);
336 API.$on(VG_EVENTS.ON_COMPLETE, onComplete);
337 }
338 }
339 }
340 ])
341 .directive(
342 "vgVolume",
343 ["VG_UTILS", function(VG_UTILS) {
344 return {
345 restrict: "E",
346 link: function(scope, elem, attr) {
347 function onMouseOverVolume() {
348 scope.volumeVisibility = "visible";
349 scope.$apply();
350 }
351
352 function onMouseLeaveVolume() {
353 scope.volumeVisibility = "hidden";
354 scope.$apply();
355 }
356
357 // We hide volume controls on mobile devices
358 if (VG_UTILS.isMobileDevice()) {
359 elem.css("display", "none");
360 }
361 else {
362 scope.volumeVisibility = "hidden";
363
364 elem.bind("mouseover", onMouseOverVolume);
365 elem.bind("mouseleave", onMouseLeaveVolume);
366 }
367 }
368 }
369 }
370 ])
371 .directive(
372 "vgVolumebar",
373 ["VG_EVENTS", "VG_UTILS", function(VG_EVENTS, VG_UTILS) {
374 return {
375 restrict: "E",
376 require: "^videogular",
377 template:
378 "<div class='verticalVolumeBar'>"+
379 "<div class='volumeBackground'>"+
380 "<div class='volumeValue'></div>"+
381 "<div class='volumeClickArea'></div>"+
382 "</div>"+
383 "</div>",
384 link: function(scope, elem, attr, API) {
385 var isChangingVolume = false;
386 var volumeBackElem = angular.element(elem[0].getElementsByClassName("volumeBackground"));
387 var volumeValueElem = angular.element(elem[0].getElementsByClassName("volumeValue"));
388
389 function onClickVolume(event) {
390 event = VG_UTILS.fixEventOffset(event);
391 var volumeHeight = parseInt(volumeBackElem.prop("offsetHeight"));
392 var value = event.offsetY * 100 / volumeHeight;
393 var volValue = 1 - (value / 100);
394 updateVolumeView(value);
395
396 API.setVolume(volValue);
397
398 scope.$apply();
399 }
400
401 function onMouseDownVolume(event) {
402 isChangingVolume = true;
403 }
404
405 function onMouseUpVolume(event) {
406 isChangingVolume = false;
407 }
408
409 function onMouseLeaveVolume(event) {
410 isChangingVolume = false;
411 }
412
413 function onMouseMoveVolume(event) {
414 if (isChangingVolume) {
415 event = VG_UTILS.fixEventOffset(event);
416 var volumeHeight = parseInt(volumeBackElem.prop("offsetHeight"));
417 var value = event.offsetY * 100 / volumeHeight;
418 var volValue = 1 - (value / 100);
419 updateVolumeView(value);
420
421 API.setVolume(volValue);
422
423 scope.$apply();
424 }
425 }
426
427 function updateVolumeView(value) {
428 volumeValueElem.css("height", value + "%");
429 volumeValueElem.css("top", (100 - value) + "%");
430 }
431
432 function onSetVolume(target, params) {
433 updateVolumeView(params[0] * 100);
434 }
435
436 function onChangeVisibility(value) {
437 elem.css("visibility", value);
438 }
439
440 elem.css("visibility", scope.volumeVisibility);
441
442 scope.$watch("volumeVisibility", onChangeVisibility);
443
444 volumeBackElem.bind("click", onClickVolume);
445 volumeBackElem.bind("mousedown", onMouseDownVolume);
446 volumeBackElem.bind("mouseup", onMouseUpVolume);
447 volumeBackElem.bind("mousemove", onMouseMoveVolume);
448 volumeBackElem.bind("mouseleave", onMouseLeaveVolume);
449
450 API.$on(VG_EVENTS.ON_SET_VOLUME, onSetVolume);
451 }
452 }
453 }
454 ])
455 .directive(
456 "vgMutebutton",
457 ["VG_EVENTS", function(VG_EVENTS) {
458 return {
459 restrict: "E",
460 require: "^videogular",
461 template: "<i class='fa fa-volume-up fa-2x text-white' ng-class='muteIcon'></i>",
462 link: function(scope, elem, attr, API) {
463 var isMuted = false;
464
465 function onClickMute(event) {
466 if (isMuted) {
467 scope.currentVolume = scope.defaultVolume;
468 }
469 else {
470 scope.currentVolume = 0;
471 scope.muteIcon = {mute: true};
472 }
473
474 isMuted = !isMuted;
475
476 API.setVolume(scope.currentVolume);
477
478 scope.$apply();
479 }
480
481 function onSetVolume(target, params) {
482 scope.currentVolume = params[0];
483
484 // TODO: Save volume with LocalStorage
485 // if it's not muted we save the default volume
486 if (!isMuted) {
487 scope.defaultVolume = params[0];
488 }
489 else {
490 // if was muted but the user changed the volume
491 if (params[0] > 0) {
492 scope.defaultVolume = params[0];
493 }
494 }
495
496 var percentValue = Math.round(params[0] * 100);
497 if (percentValue == 0) {
498 scope.muteIcon = {mute: true};
499 }
500 else if (percentValue > 0 && percentValue < 25) {
501 scope.muteIcon = {level0: true};
502 }
503 else if (percentValue >= 25 && percentValue < 50) {
504 scope.muteIcon = {level1: true};
505 }
506 else if (percentValue >= 50 && percentValue < 75) {
507 scope.muteIcon = {level2: true};
508 }
509 else if (percentValue >= 75) {
510 scope.muteIcon = {level3: true};
511 }
512
513 //scope.$apply();
514 }
515
516 scope.defaultVolume = 1;
517 scope.currentVolume = scope.defaultVolume;
518 scope.muteIcon = {level3: true};
519
520 //TODO: get volume from localStorage
521 elem.bind("click", onClickMute);
522
523 API.$on(VG_EVENTS.ON_SET_VOLUME, onSetVolume);
524 }
525 }
526 }
527 ])
528 .directive(
529 "vgFullscreenbutton",
530 ["$window", "VG_EVENTS", function($window, VG_EVENTS){
531 return {
532 restrict: "AE",
533 require: "^videogular",
534 scope: {
535 vgEnterFullScreenIcon: "=",
536 vgExitFullScreenIcon: "="
537 },
538 template: "<i class='fa fa-hand-o-left fa-2x text-white' ng-class='fullscreenIcon'></i>",
539 link: function(scope, elem, attr, API) {
540 function onEnterFullScreen() {
541 scope.fullscreenIcon = {exit: true};
542 }
543 function onExitFullScreen() {
544 scope.fullscreenIcon = {enter: true};
545 }
546 function onClickFullScreen(event) {
547 API.toggleFullScreen();
548
549 scope.$apply();
550 }
551
552 elem.bind("click", onClickFullScreen);
553 scope.fullscreenIcon = {enter: true};
554
555 API.$on(VG_EVENTS.ON_ENTER_FULLSCREEN, onEnterFullScreen);
556 API.$on(VG_EVENTS.ON_EXIT_FULLSCREEN, onExitFullScreen);
557 }
558 }
559 }
560 ]);