diff options
60 files changed, 4248 insertions, 135 deletions
diff --git a/www/css/style.css b/www/css/style.css index 7ca94150..ebfeb58c 100644 --- a/www/css/style.css +++ b/www/css/style.css @@ -513,6 +513,15 @@ input[type=range]::-webkit-slider-thumb { float: right; } + +.videogular-container { + height: 190px; + width:300px; + margin: auto; + overflow: hidden; + float:left; +} + /*.mySliderClass.jslider.sliderCSS div.jslider-pointer {top:-10px;left:15px;width:60px;height:60px;margin-left:-5px;background-color:silver;background-color:#615959;border-radius:50% }*/ diff --git a/www/index.html b/www/index.html index 2e3b3186..ffdc78d4 100644 --- a/www/index.html +++ b/www/index.html @@ -54,6 +54,12 @@ <script src="lib/angular-awesome-slider/dist/angular-awesome-slider.min.js"> </script> + + + <script src="lib/videogular/videogular.js"></script> +<script src="lib/videogular-controls/vg-controls.js"></script> + <script src="lib/videogular-overlay-play/vg-overlay-play.js"></script> + <script src="lib/videogular-buffering/vg-buffering.js"></script> <script src="js/app.js"></script> <!--<script src="js/ExceptionHandler.js"></script>--> diff --git a/www/js/EventCtrl.js b/www/js/EventCtrl.js index 483e3d55..c5aad8d5 100644 --- a/www/js/EventCtrl.js +++ b/www/js/EventCtrl.js @@ -7,7 +7,7 @@ // and whether the new API has a better mechanism angular.module('zmApp.controllers') - .controller('zmApp.EventCtrl', ['$scope', '$rootScope', 'zm', 'ZMDataModel', 'message', '$ionicSideMenuDelegate', '$timeout', '$interval', '$ionicModal', '$ionicLoading', '$http', '$state', '$stateParams', '$ionicHistory', '$ionicScrollDelegate', '$ionicPlatform', '$ionicSlideBoxDelegate', '$ionicPosition', '$ionicPopover', '$ionicPopup', 'EventServer', '$cordovaBadge', '$cordovaLocalNotification', function ($scope, $rootScope, zm, ZMDataModel, message, $ionicSideMenuDelegate, $timeout, $interval, $ionicModal, $ionicLoading, $http, $state, $stateParams, $ionicHistory, $ionicScrollDelegate, $ionicPlatform, $ionicSlideBoxDelegate, $ionicPosition, $ionicPopover, $ionicPopup, EventServer, $cordovaBadge, $cordovaLocalNotification) { + .controller('zmApp.EventCtrl', ['$scope', '$rootScope', 'zm', 'ZMDataModel', 'message', '$ionicSideMenuDelegate', '$timeout', '$interval', '$ionicModal', '$ionicLoading', '$http', '$state', '$stateParams', '$ionicHistory', '$ionicScrollDelegate', '$ionicPlatform', '$ionicSlideBoxDelegate', '$ionicPosition', '$ionicPopover', '$ionicPopup', 'EventServer', '$sce', '$cordovaBadge', '$cordovaLocalNotification', function ($scope, $rootScope, zm, ZMDataModel, message, $ionicSideMenuDelegate, $timeout, $interval, $ionicModal, $ionicLoading, $http, $state, $stateParams, $ionicHistory, $ionicScrollDelegate, $ionicPlatform, $ionicSlideBoxDelegate, $ionicPosition, $ionicPopover, $ionicPopup, EventServer, $sce, $cordovaBadge, $cordovaLocalNotification) { // events in last 5 minutes // TODO https://server/zm/api/events/consoleEvents/5%20minute.json @@ -15,6 +15,17 @@ angular.module('zmApp.controllers') //--------------------------------------------------- // Controller main //--------------------------------------------------- + + $scope.video={}; + $scope.video.config = { + sources: [ + {src: $sce.trustAsResourceUrl("http://173.228.105.6/zm/events/2/15/11/01/01/54/03/754-video.mp4"), type: "video/mp4"} + + ], + + theme: "lib/videogular-themes-default/videogular.css", + + }; var loginData = ZMDataModel.getLogin(); @@ -705,8 +716,30 @@ angular.module('zmApp.controllers') }); } + + + // now get event details to show alarm frames var loginData = ZMDataModel.getLogin(); + + + // grab video details + event.Event.video={}; + var videoURL = loginData.url+"/events/"+event.Event.relativePath+event.Event.DefaultVideo; + + console.log ("************** VIDEO IS " + videoURL); + event.Event.video.config = { + sources: [ + {src: + $sce.trustAsResourceUrl(videoURL), type: "video/mp4"} + + ], + + theme: "lib/videogular-themes-default/videogular.css", + + }; + + var myurl = loginData.apiurl + '/events/' + event.Event.Id + ".json"; ZMDataModel.zmLog("API for event details" + myurl); $http.get(myurl) diff --git a/www/js/app.js b/www/js/app.js index 5e0a8a65..982a995e 100644 --- a/www/js/app.js +++ b/www/js/app.js @@ -15,6 +15,9 @@ angular.module('zmApp', [ 'fileLogger', 'angular-carousel', 'angularAwesomeSlider', + 'com.2fdevs.videogular', + 'com.2fdevs.videogular.plugins.controls', + 'com.2fdevs.videogular.plugins.overlayplay' diff --git a/www/lib/videogular-buffering/.bower.json b/www/lib/videogular-buffering/.bower.json new file mode 100644 index 00000000..2bfe6f72 --- /dev/null +++ b/www/lib/videogular-buffering/.bower.json @@ -0,0 +1,19 @@ +{ + "name": "videogular-buffering", + "version": "1.3.2", + "main": "./vg-buffering.js", + "dependencies": { + "videogular": "~1.3.2" + }, + "homepage": "https://github.com/2fdevs/bower-videogular-buffering", + "_release": "1.3.2", + "_resolution": { + "type": "version", + "tag": "v1.3.2", + "commit": "c46fd7f63d446b048e9ffe5d5a3656f180478e16" + }, + "_source": "git://github.com/2fdevs/bower-videogular-buffering.git", + "_target": "~1.3.2", + "_originalSource": "videogular-buffering", + "_direct": true +}
\ No newline at end of file diff --git a/www/lib/videogular-buffering/.gitignore b/www/lib/videogular-buffering/.gitignore new file mode 100644 index 00000000..ac2c9712 --- /dev/null +++ b/www/lib/videogular-buffering/.gitignore @@ -0,0 +1,3 @@ +/node_modules/ +/bower_components/ +.idea
\ No newline at end of file diff --git a/www/lib/videogular-buffering/Gruntfile.js b/www/lib/videogular-buffering/Gruntfile.js new file mode 100644 index 00000000..e5b2f2f7 --- /dev/null +++ b/www/lib/videogular-buffering/Gruntfile.js @@ -0,0 +1,35 @@ +module.exports = function(grunt) { + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + release: { + options: { + //bump: false, //default: true + //file: 'bower.json', //default: package.json + //add: false, //default: true + //commit: false, //default: true + //tag: false, //default: true + //push: false, //default: true + //pushTags: false, //default: true + //npmtag: true, //default: no tag + //folder: 'folder/to/publish/to/npm', //default project root + //commitMessage: 'check out my release <%= version %>', //default: 'release <%= version %>' + //tagMessage: 'tagging version <%= version %>', //default: 'Version <%= version %>', + //tagName: 'v<%= version %>', //default: '<%= version %>' + + file: 'bower.json', //default: package.json + add: false, //default: true + commit: false, //default: true + tag: false, //default: true + push: false, //default: true + pushTags: false, //default: true + npm: false + } + } + }); + + grunt.loadNpmTasks('grunt-release'); + + grunt.registerTask('major', ['release:major']); + grunt.registerTask('minor', ['release:minor']); + grunt.registerTask('patch', ['release:patch']); +}; diff --git a/www/lib/videogular-buffering/LICENSE b/www/lib/videogular-buffering/LICENSE new file mode 100644 index 00000000..2a6b69f7 --- /dev/null +++ b/www/lib/videogular-buffering/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 2fdevs + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/www/lib/videogular-buffering/README.md b/www/lib/videogular-buffering/README.md new file mode 100644 index 00000000..d2c9e258 --- /dev/null +++ b/www/lib/videogular-buffering/README.md @@ -0,0 +1,59 @@ +bower-videogular-buffering +========================== + +Videogular `buffering` plugin repository for distribution on `bower`. + +## Install + +Install [Videogular](http://www.videogular.com/) `buffering` plugin with Bower: + +`bower install videogular-buffering` + +### Install Videogular + +Install [Videogular](http://www.videogular.com/) with Bower: + +`bower install videogular` + +### Install themes + +Install [Videogular](http://www.videogular.com/) themes with Bower: + +`bower install videogular-themes-default` + +### Install plugins + +Install [Videogular](http://www.videogular.com/) plugins with Bower: + +`bower install videogular-controls` + +`bower install videogular-overlay-play` + +`bower install videogular-poster` + +## Documentation + +It's available on [Videogular's project Wiki](https://github.com/2fdevs/videogular/wiki). + +## License + +The MIT License (MIT) + +Copyright (c) 2013 2fdevs + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/www/lib/videogular-buffering/bower.json b/www/lib/videogular-buffering/bower.json new file mode 100644 index 00000000..f445c8b0 --- /dev/null +++ b/www/lib/videogular-buffering/bower.json @@ -0,0 +1,8 @@ +{ + "name": "videogular-buffering", + "version": "1.3.2", + "main": "./vg-buffering.js", + "dependencies": { + "videogular": "~1.3.2" + } +} diff --git a/www/lib/videogular-buffering/index.js b/www/lib/videogular-buffering/index.js new file mode 100644 index 00000000..1ee16a8e --- /dev/null +++ b/www/lib/videogular-buffering/index.js @@ -0,0 +1,3 @@ +require('./vg-buffering'); + +module.exports = 'com.2fdevs.videogular.plugins.buffering'; diff --git a/www/lib/videogular-buffering/package.json b/www/lib/videogular-buffering/package.json new file mode 100644 index 00000000..7d92b0d7 --- /dev/null +++ b/www/lib/videogular-buffering/package.json @@ -0,0 +1,12 @@ +{ + "name": "videogular-buffering", + "version": "1.3.2", + "main": "index.js", + "devDependencies": { + "grunt": "~0.4.1", + "grunt-release": "~0.7.0" + }, + "engines": { + "node": ">=0.8.0" + } +} diff --git a/www/lib/videogular-buffering/vg-buffering.js b/www/lib/videogular-buffering/vg-buffering.js new file mode 100644 index 00000000..fde9e839 --- /dev/null +++ b/www/lib/videogular-buffering/vg-buffering.js @@ -0,0 +1,116 @@ +/** + * @license videogular v1.3.2 http://videogular.com + * Two Fucking Developers http://twofuckingdevelopers.com + * License: MIT + */ +/** + * @ngdoc directive + * @name com.2fdevs.videogular.plugins.buffering.directive:vgBuffering + * @restrict E + * @description + * Shows a spinner when Videogular is buffering or preparing the video player. + * + * <pre> + * <videogular vg-theme="config.theme.url" vg-autoplay="config.autoPlay"> + * <vg-media vg-src="sources"></vg-media> + * + * <vg-buffering></vg-buffering> + * </videogular> + * </pre> + * + */ +"use strict"; +angular.module("com.2fdevs.videogular.plugins.buffering", []) + .run( + ["$templateCache", function ($templateCache) { + $templateCache.put("vg-templates/vg-buffering", + '<div class="bufferingContainer">\ + <div ng-class="spinnerClass" class="loadingSpinner"></div>\ + </div>'); + }] +) + .directive( + "vgBuffering", + ["VG_STATES", "VG_UTILS", function (VG_STATES, VG_UTILS) { + return { + restrict: "E", + require: "^videogular", + templateUrl: function (elem, attrs) { + return attrs.vgTemplate || 'vg-templates/vg-buffering'; + }, + link: function (scope, elem, attr, API) { + scope.showSpinner = function showSpinner() { + scope.spinnerClass = {stop: API.isBuffering}; + elem.css("display", "block"); + }; + + scope.hideSpinner = function hideSpinner() { + scope.spinnerClass = {stop: API.isBuffering}; + elem.css("display", "none"); + }; + + scope.setState = function setState(isBuffering) { + if (isBuffering) { + scope.showSpinner(); + } + else { + scope.hideSpinner(); + } + }; + + scope.onStateChange = function onStateChange(state) { + if (state == VG_STATES.STOP) { + scope.hideSpinner(); + } + }; + + scope.onPlayerReady = function onPlayerReady(isReady) { + if (isReady) { + scope.hideSpinner(); + } + }; + + scope.showSpinner(); + + // Workaround for issue #16: https://github.com/2fdevs/videogular/issues/16 + if (VG_UTILS.isMobileDevice()) { + scope.hideSpinner(); + } + else { + scope.$watch( + function () { + return API.isReady; + }, + function (newVal, oldVal) { + if (API.isReady == true || newVal != oldVal) { + scope.onPlayerReady(newVal); + } + } + ); + } + + scope.$watch( + function () { + return API.currentState; + }, + function (newVal, oldVal) { + if (newVal != oldVal) { + scope.onStateChange(newVal); + } + } + ); + + scope.$watch( + function () { + return API.isBuffering; + }, + function (newVal, oldVal) { + if (newVal != oldVal) { + scope.setState(newVal); + } + } + ); + } + } + } + ]); diff --git a/www/lib/videogular-buffering/vg-buffering.min.js b/www/lib/videogular-buffering/vg-buffering.min.js new file mode 100644 index 00000000..b0bb1ff8 --- /dev/null +++ b/www/lib/videogular-buffering/vg-buffering.min.js @@ -0,0 +1 @@ +"use strict";angular.module("com.2fdevs.videogular.plugins.buffering",[]).run(["$templateCache",function(a){a.put("vg-templates/vg-buffering",'<div class="bufferingContainer"> <div ng-class="spinnerClass" class="loadingSpinner"></div> </div>')}]).directive("vgBuffering",["VG_STATES","VG_UTILS",function(a,b){return{restrict:"E",require:"^videogular",templateUrl:function(a,b){return b.vgTemplate||"vg-templates/vg-buffering"},link:function(c,d,e,f){c.showSpinner=function(){c.spinnerClass={stop:f.isBuffering},d.css("display","block")},c.hideSpinner=function(){c.spinnerClass={stop:f.isBuffering},d.css("display","none")},c.setState=function(a){a?c.showSpinner():c.hideSpinner()},c.onStateChange=function(b){b==a.STOP&&c.hideSpinner()},c.onPlayerReady=function(a){a&&c.hideSpinner()},c.showSpinner(),b.isMobileDevice()?c.hideSpinner():c.$watch(function(){return f.isReady},function(a,b){(1==f.isReady||a!=b)&&c.onPlayerReady(a)}),c.$watch(function(){return f.currentState},function(a,b){a!=b&&c.onStateChange(a)}),c.$watch(function(){return f.isBuffering},function(a,b){a!=b&&c.setState(a)})}}}]);
\ No newline at end of file diff --git a/www/lib/videogular-controls/.bower.json b/www/lib/videogular-controls/.bower.json new file mode 100644 index 00000000..363047f2 --- /dev/null +++ b/www/lib/videogular-controls/.bower.json @@ -0,0 +1,19 @@ +{ + "name": "videogular-controls", + "version": "1.3.2", + "main": "./vg-controls.js", + "dependencies": { + "videogular": "~1.3.2" + }, + "homepage": "https://github.com/2fdevs/bower-videogular-controls", + "_release": "1.3.2", + "_resolution": { + "type": "version", + "tag": "v1.3.2", + "commit": "6fa5a2cb079b995cca749573576eed82bddc3eb6" + }, + "_source": "git://github.com/2fdevs/bower-videogular-controls.git", + "_target": "~1.3.2", + "_originalSource": "videogular-controls", + "_direct": true +}
\ No newline at end of file diff --git a/www/lib/videogular-controls/.gitignore b/www/lib/videogular-controls/.gitignore new file mode 100644 index 00000000..ac2c9712 --- /dev/null +++ b/www/lib/videogular-controls/.gitignore @@ -0,0 +1,3 @@ +/node_modules/ +/bower_components/ +.idea
\ No newline at end of file diff --git a/www/lib/videogular-controls/Gruntfile.js b/www/lib/videogular-controls/Gruntfile.js new file mode 100644 index 00000000..e5b2f2f7 --- /dev/null +++ b/www/lib/videogular-controls/Gruntfile.js @@ -0,0 +1,35 @@ +module.exports = function(grunt) { + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + release: { + options: { + //bump: false, //default: true + //file: 'bower.json', //default: package.json + //add: false, //default: true + //commit: false, //default: true + //tag: false, //default: true + //push: false, //default: true + //pushTags: false, //default: true + //npmtag: true, //default: no tag + //folder: 'folder/to/publish/to/npm', //default project root + //commitMessage: 'check out my release <%= version %>', //default: 'release <%= version %>' + //tagMessage: 'tagging version <%= version %>', //default: 'Version <%= version %>', + //tagName: 'v<%= version %>', //default: '<%= version %>' + + file: 'bower.json', //default: package.json + add: false, //default: true + commit: false, //default: true + tag: false, //default: true + push: false, //default: true + pushTags: false, //default: true + npm: false + } + } + }); + + grunt.loadNpmTasks('grunt-release'); + + grunt.registerTask('major', ['release:major']); + grunt.registerTask('minor', ['release:minor']); + grunt.registerTask('patch', ['release:patch']); +}; diff --git a/www/lib/videogular-controls/LICENSE b/www/lib/videogular-controls/LICENSE new file mode 100644 index 00000000..2a6b69f7 --- /dev/null +++ b/www/lib/videogular-controls/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 2fdevs + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/www/lib/videogular-controls/README.md b/www/lib/videogular-controls/README.md new file mode 100644 index 00000000..706b94ea --- /dev/null +++ b/www/lib/videogular-controls/README.md @@ -0,0 +1,59 @@ +bower-videogular-controls +========================= + +Videogular `controls` plugin repository for distribution on `bower`. + +## Install + +Install [Videogular](http://www.videogular.com/) `controls` plugin with Bower: + +`bower install videogular-controls` + +### Install Videogular + +Install [Videogular](http://www.videogular.com/) with Bower: + +`bower install videogular` + +### Install themes + +Install [Videogular](http://www.videogular.com/) themes with Bower: + +`bower install videogular-themes-default` + +### Install plugins + +Install [Videogular](http://www.videogular.com/) plugins with Bower: + +`bower install videogular-buffering` + +`bower install videogular-overlay-play` + +`bower install videogular-poster` + +## Documentation + +It's available on [Videogular's project Wiki](https://github.com/2fdevs/videogular/wiki). + +## License + +The MIT License (MIT) + +Copyright (c) 2013 2fdevs + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/www/lib/videogular-controls/bower.json b/www/lib/videogular-controls/bower.json new file mode 100644 index 00000000..4cd2b307 --- /dev/null +++ b/www/lib/videogular-controls/bower.json @@ -0,0 +1,8 @@ +{ + "name": "videogular-controls", + "version": "1.3.2", + "main": "./vg-controls.js", + "dependencies": { + "videogular": "~1.3.2" + } +} diff --git a/www/lib/videogular-controls/index.js b/www/lib/videogular-controls/index.js new file mode 100644 index 00000000..346eb418 --- /dev/null +++ b/www/lib/videogular-controls/index.js @@ -0,0 +1,3 @@ +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 new file mode 100644 index 00000000..195fa399 --- /dev/null +++ b/www/lib/videogular-controls/package.json @@ -0,0 +1,12 @@ +{ + "name": "videogular-controls", + "version": "1.3.2", + "main": "index.js", + "devDependencies": { + "grunt": "~0.4.1", + "grunt-release": "~0.7.0" + }, + "engines": { + "node": ">=0.8.0" + } +} diff --git a/www/lib/videogular-controls/vg-controls.js b/www/lib/videogular-controls/vg-controls.js new file mode 100644 index 00000000..ef0efd9a --- /dev/null +++ b/www/lib/videogular-controls/vg-controls.js @@ -0,0 +1,1077 @@ +/** + * @license videogular v1.3.2 http://videogular.com + * Two Fucking Developers http://twofuckingdevelopers.com + * License: MIT + */ +/** + * @ngdoc directive + * @name com.2fdevs.videogular.plugins.controls.directive:vgControls + * @restrict E + * @description + * This directive acts as a container and you will need other directives to control the media. + * Inside this directive you can add other directives like vg-play-pause-button and vg-scrub-bar. + * + * <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-controls> + * </videogular> + * </pre> + * + * @param {boolean=false} vgAutohide Boolean variable or value to activate autohide. + * @param {number=2000} vgAutohideTime Number variable or value that represents the time in milliseconds that will wait vgControls until it hides. + * + * + */ +"use strict"; +angular.module("com.2fdevs.videogular.plugins.controls", []) + .run( + ["$templateCache", function ($templateCache) { + $templateCache.put("vg-templates/vg-controls", + '<div class="controls-container" ng-mousemove="onMouseMove()" ng-class="animationClass" ng-transclude></div>'); + }] +) + .directive("vgControls", + ["$timeout", "VG_STATES", function ($timeout, VG_STATES) { + return { + restrict: "E", + require: "^videogular", + transclude: true, + templateUrl: function (elem, attrs) { + return attrs.vgTemplate || 'vg-templates/vg-controls'; + }, + scope: { + vgAutohide: "=?", + vgAutohideTime: "=?" + }, + link: function (scope, elem, attr, API) { + var w = 0; + var h = 0; + var autoHideTime = 2000; + var hideInterval; + + scope.API = API; + + scope.onMouseMove = function onMouseMove() { + if (scope.vgAutohide) scope.showControls(); + }; + + scope.setAutohide = function setAutohide(value) { + if (value && API.currentState == VG_STATES.PLAY) { + hideInterval = $timeout(scope.hideControls, autoHideTime); + } + else { + scope.animationClass = ""; + $timeout.cancel(hideInterval); + scope.showControls(); + } + }; + + scope.setAutohideTime = function setAutohideTime(value) { + autoHideTime = value; + }; + + scope.hideControls = function hideControls() { + scope.animationClass = "hide-animation"; + }; + + scope.showControls = function showControls() { + scope.animationClass = "show-animation"; + $timeout.cancel(hideInterval); + if (scope.vgAutohide && API.currentState == VG_STATES.PLAY) hideInterval = $timeout(scope.hideControls, autoHideTime); + }; + + if (API.isConfig) { + scope.$watch("API.config", + function () { + if (scope.API.config) { + var ahValue = scope.API.config.plugins.controls.autohide || false; + var ahtValue = scope.API.config.plugins.controls.autohideTime || 2000; + scope.vgAutohide = ahValue; + scope.vgAutohideTime = ahtValue; + scope.setAutohideTime(ahtValue); + scope.setAutohide(ahValue); + } + } + ); + } + else { + // If vg-autohide has been set + if (scope.vgAutohide != undefined) { + scope.$watch("vgAutohide", scope.setAutohide); + } + + // If vg-autohide-time has been set + if (scope.vgAutohideTime != undefined) { + scope.$watch("vgAutohideTime", scope.setAutohideTime); + } + } + + + } + } + }] +); + +/** + * @ngdoc directive + * @name com.2fdevs.videogular.plugins.controls.directive:vgFullscreenButton + * @restrict E + * @description + * Directive to switch between fullscreen and normal mode. + * + * <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-fullscreen-button></vg-fullscreen-button> + * </vg-controls> + * </videogular> + * </pre> + * + */ +angular.module("com.2fdevs.videogular.plugins.controls") + .run( + ["$templateCache", function ($templateCache) { + $templateCache.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 (elem, attrs) { + return attrs.vgTemplate || 'vg-templates/vg-fullscreen-button'; + }, + link: function (scope, elem, attr, API) { + scope.onChangeFullScreen = function onChangeFullScreen(isFullScreen) { + scope.fullscreenIcon = {enter: !isFullScreen, exit: isFullScreen}; + }; + + scope.onClickFullScreen = function onClickFullScreen() { + API.toggleFullScreen(); + }; + + scope.fullscreenIcon = {enter: true}; + + scope.$watch( + function () { + return API.isFullScreen; + }, + function (newVal, oldVal) { + if (newVal != oldVal) { + scope.onChangeFullScreen(newVal); + } + } + ); + } + } + }] +); + +/** + * @ngdoc directive + * @name com.2fdevs.videogular.plugins.controls.directive:vgPlayPauseButton + * @restrict E + * @description + * Adds a button inside vg-controls to play and pause media. + * + * <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-play-pause-button></vg-play-pause-button> + * </vg-controls> + * </videogular> + * </pre> + * + */ +angular.module("com.2fdevs.videogular.plugins.controls") + .run( + ["$templateCache", function ($templateCache) { + $templateCache.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 (VG_STATES) { + return { + restrict: "E", + require: "^videogular", + scope: {}, + templateUrl: function (elem, attrs) { + return attrs.vgTemplate || 'vg-templates/vg-play-pause-button'; + }, + link: function (scope, elem, attr, API) { + scope.setState = function setState(newState) { + switch (newState) { + case VG_STATES.PLAY: + scope.playPauseIcon = {pause: true}; + break; + + case VG_STATES.PAUSE: + scope.playPauseIcon = {play: true}; + break; + + case VG_STATES.STOP: + scope.playPauseIcon = {play: true}; + break; + } + }; + + scope.onClickPlayPause = function onClickPlayPause() { + API.playPause(); + }; + + scope.playPauseIcon = {play: true}; + + scope.$watch( + function () { + return API.currentState; + }, + function (newVal, oldVal) { + scope.setState(newVal); + } + ); + } + } + }] +); + +/** + * @ngdoc directive + * @name com.2fdevs.videogular.plugins.controls.directive:ngPlaybackButton + * @restrict E + * @description + * Directive to display a playback buttom to control the playback rate. + * + * <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-controls> + * </videogular> + * </pre> + * + */ +angular.module("com.2fdevs.videogular.plugins.controls") + .run( + ["$templateCache", function ($templateCache) { + $templateCache.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 (elem, attrs) { + return attrs.vgTemplate || 'vg-templates/vg-playback-button'; + }, + link: function (scope, elem, attr, API) { + scope.playback = '1'; + + scope.setPlayback = function(playback) { + scope.playback = playback; + API.setPlayback(parseFloat(playback)); + }; + + scope.onClickPlayback = function onClickPlayback() { + var playbackOptions = ['0.5', '1', '1.5', '2']; + var nextPlaybackRate = playbackOptions.indexOf(scope.playback.toString()) + 1; + + if (nextPlaybackRate >= playbackOptions.length) { + scope.playback = playbackOptions[0]; + } + else { + scope.playback = playbackOptions[nextPlaybackRate]; + } + + scope.setPlayback(scope.playback); + }; + + scope.$watch( + function () { + return API.playback; + }, + function(newVal, oldVal) { + if (newVal != oldVal) { + scope.setPlayback(newVal); + } + } + ); + } + } + }] +); +/** + * @ngdoc directive + * @name com.2fdevs.videogular.plugins.controls.directive:vgScrubBarBuffer + * @restrict E + * @description + * Layer inside vg-scrub-bar to display the buffer. + * + * <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-scrub-bar> + * <vg-scrub-bar-buffer></vg-scrub-bar-buffer> + * </vg-scrub-bar> + * </vg-controls> + * </videogular> + * </pre> + * + */ +angular.module("com.2fdevs.videogular.plugins.controls") + .directive("vgScrubBarBuffer", + [function () { + return { + restrict: "E", + require: "^videogular", + link: function (scope, elem, attr, API) { + var percentTime = 0; + + scope.onUpdateBuffer = function onUpdateBuffer(newBuffer) { + if (typeof newBuffer === 'number' && API.totalTime) { + percentTime = 100 * (newBuffer / API.totalTime); + elem.css("width", percentTime + "%"); + } else { + elem.css("width", 0); + } + }; + + scope.$watch( + function () { + return API.bufferEnd; + }, + function (newVal, oldVal) { + scope.onUpdateBuffer(newVal); + } + ); + } + } + }] +); + +/** + * @ngdoc directive + * @name com.2fdevs.videogular.plugins.controls.directive:vgScrubBarCuePoints + * @restrict E + * @description + * Layer inside vg-scrub-bar to display a cue point timeline. + * + * <pre> + * <videogular vg-theme="config.theme.url"> + * <vg-media vg-src="sources"></vg-media> + * + * <vg-controls> + * <vg-scrub-bar> + * <vg-scrub-bar-cue-points vg-cue-points='config.cuePoints[0]'></vg-scrub-bar-cue-points> + * </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-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) + "%"; + } + + cuePoints[i].$$style = { + width: percentWidth, + left: position + }; + } + } + }; + + scope.$watch("vgCuePoints", scope.updateCuePoints); + + scope.$watch( + function () { + return API.totalTime; + }, + function (newVal, oldVal) { + if (newVal > 0) scope.onPlayerReady(); + } + ); + } + } + }] +); + +/** + * @ngdoc directive + * @name com.2fdevs.videogular.plugins.controls.directive:vgScrubBarCurrentTime + * @restrict E + * @description + * Layer inside vg-scrub-bar to display the current time. + * + * <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-scrub-bar> + * <vg-scrub-bar-current-time></vg-scrub-bar-current-time> + * </vg-scrub-bar> + * </vg-controls> + * </videogular> + * </pre> + * + */ +angular.module("com.2fdevs.videogular.plugins.controls") + .directive("vgScrubBarCurrentTime", + [function () { + return { + restrict: "E", + require: "^videogular", + link: function (scope, elem, attr, API) { + var percentTime = 0; + + scope.onUpdateTime = function onUpdateTime(newCurrentTime) { + if (typeof newCurrentTime === 'number' && API.totalTime) { + percentTime = 100 * (newCurrentTime / API.totalTime); + elem.css("width", percentTime + "%"); + } else { + elem.css("width", 0); + } + }; + + scope.$watch( + function () { + return API.currentTime; + }, + function (newVal, oldVal) { + scope.onUpdateTime(newVal); + } + ); + } + } + }] +); + +/** + * @ngdoc directive + * @name com.2fdevs.videogular.plugins.controls.directive:vgScrubBar + * @restrict E + * @description + * Directive to control the time and display other information layers about the progress of the media. + * This directive acts as a container and you can add more layers to display current time, cuepoints, buffer or whatever you need. + * + * <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-scrub-bar></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", + '<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; + + scope.API = API; + 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; + } + + return event.clientX - x; + }; + + scope.onScrubBarTouchStart = function onScrubBarTouchStart($event) { + var event = $event.originalEvent || $event; + var touches = event.touches; + var touchX = scope.getOffset(touches[0]); + + isSeeking = true; + if (isPlaying) isPlayingWhenSeeking = true; + API.pause(); + API.seekTime(touchX * API.mediaElement[0].duration / elem[0].scrollWidth); + + scope.$apply(); + }; + + scope.onScrubBarTouchEnd = function onScrubBarTouchEnd($event) { + var event = $event.originalEvent || $event; + if (isPlayingWhenSeeking) { + isPlayingWhenSeeking = false; + API.play(); + } + isSeeking = false; + + scope.$apply(); + }; + + 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 / elem[0].scrollWidth); + } + + scope.$apply(); + }; + + scope.onScrubBarTouchLeave = function onScrubBarTouchLeave(event) { + isSeeking = false; + + scope.$apply(); + }; + + scope.onScrubBarMouseDown = function onScrubBarMouseDown(event) { + event = VG_UTILS.fixEventOffset(event); + + isSeeking = true; + if (isPlaying) isPlayingWhenSeeking = true; + API.pause(); + + API.seekTime(event.offsetX * API.mediaElement[0].duration / elem[0].scrollWidth); + + scope.$apply(); + }; + + 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 / elem[0].scrollWidth); + + scope.$apply(); + }; + + scope.onScrubBarMouseMove = function onScrubBarMouseMove(event) { + if (isSeeking) { + event = VG_UTILS.fixEventOffset(event); + API.seekTime(event.offsetX * API.mediaElement[0].duration / elem[0].scrollWidth); + } + + scope.$apply(); + }; + + scope.onScrubBarMouseLeave = function onScrubBarMouseLeave(event) { + isSeeking = false; + + scope.$apply(); + }; + + scope.onScrubBarKeyDown = function onScrubBarKeyDown(event) { + var currentPercent = (API.currentTime / API.totalTime) * 100; + + 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.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.$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); + } + } + } + }] +); + +/** + * @ngdoc directive + * @name com.2fdevs.videogular.plugins.controls.directive:vgTimeDisplay + * @restrict E + * @description + * Adds a time display inside vg-controls to play and pause media. + * You have three scope variables to show current time, time left and total time. + * + * Those scope variables are in milliseconds, you can add a date filter to show the time as you wish. + * + * <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-time-display>{{currentTime | date:'hh:mm'}}</vg-time-display> + * <vg-time-display>{{timeLeft | date:'mm:ss'}}</vg-time-display> + * <vg-time-display>{{totalTime | date:'hh:mm:ss'}}</vg-time-display> + * </vg-controls> + * </videogular> + * </pre> + * + */ +angular.module("com.2fdevs.videogular.plugins.controls") + .directive("vgTimeDisplay", + [function () { + return { + require: "^videogular", + restrict: "E", + link: function (scope, elem, attr, API) { + scope.currentTime = API.currentTime; + scope.timeLeft = API.timeLeft; + scope.totalTime = API.totalTime; + scope.isLive = API.isLive; + + scope.$watch( + function () { + return API.currentTime; + }, + function (newVal, oldVal) { + scope.currentTime = newVal; + } + ); + + scope.$watch( + function () { + return API.timeLeft; + }, + function (newVal, oldVal) { + scope.timeLeft = newVal; + } + ); + + scope.$watch( + function () { + return API.totalTime; + }, + function (newVal, oldVal) { + scope.totalTime = newVal; + } + ); + + scope.$watch( + function () { + return API.isLive; + }, + function (newVal, oldVal) { + scope.isLive = newVal; + } + ); + } + } + }] +); + +/** + * @ngdoc directive + * @name com.2fdevs.videogular.plugins.controls.directive:vgMuteButton + * @restrict E + * @description + * Directive to display a button to mute volume. + * + * <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-volume> + * <vg-mute-button><vg-mute-button> + * </vg-volume> + * </vg-controls> + * </videogular> + * </pre> + * + */ +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>'); + }] +) + .directive("vgMuteButton", + [function () { + return { + restrict: "E", + require: "^videogular", + templateUrl: function (elem, attrs) { + return attrs.vgTemplate || 'vg-templates/vg-mute-button'; + }, + link: function (scope, elem, attr, API) { + var isMuted = false; + var UP = 38; + var DOWN = 40; + var CHANGE_PER_PRESS = 0.05; + + scope.onClickMute = function onClickMute() { + if (isMuted) { + scope.currentVolume = scope.defaultVolume; + } + else { + scope.currentVolume = 0; + scope.muteIcon = {mute: true}; + } + + isMuted = !isMuted; + + API.setVolume(scope.currentVolume); + }; + + scope.onMuteButtonFocus = function onMuteButtonFocus() { + scope.volumeVisibility = "visible"; + }; + + scope.onMuteButtonLoseFocus = function onMuteButtonLoseFocus() { + scope.volumeVisibility = "hidden"; + }; + + scope.onMuteButtonKeyDown = function onMuteButtonKeyDown(event) { + var currentVolume = (API.volume != null) ? API.volume : 1; + var newVolume; + + if (event.which === UP || event.keyCode === UP) { + newVolume = currentVolume + CHANGE_PER_PRESS; + if (newVolume > 1) newVolume = 1; + + API.setVolume(newVolume); + event.preventDefault(); + } + else if (event.which === DOWN || event.keyCode === DOWN) { + newVolume = currentVolume - CHANGE_PER_PRESS; + if (newVolume < 0) newVolume = 0; + + API.setVolume(newVolume); + event.preventDefault(); + } + }; + + scope.onSetVolume = function onSetVolume(newVolume) { + scope.currentVolume = newVolume; + + isMuted = (scope.currentVolume === 0); + + // if it's not muted we save the default volume + if (!isMuted) { + scope.defaultVolume = newVolume; + } + else { + // if was muted but the user changed the volume + if (newVolume > 0) { + scope.defaultVolume = newVolume; + } + } + + var percentValue = Math.round(newVolume * 100); + if (percentValue == 0) { + scope.muteIcon = {mute: true}; + } + else if (percentValue > 0 && percentValue < 25) { + scope.muteIcon = {level0: true}; + } + else if (percentValue >= 25 && percentValue < 50) { + scope.muteIcon = {level1: true}; + } + else if (percentValue >= 50 && percentValue < 75) { + scope.muteIcon = {level2: true}; + } + else if (percentValue >= 75) { + scope.muteIcon = {level3: true}; + } + }; + + scope.defaultVolume = 1; + scope.currentVolume = scope.defaultVolume; + scope.muteIcon = {level3: true}; + + //Update the mute button on initialization, then watch for changes + scope.onSetVolume(API.volume); + scope.$watch( + function () { + return API.volume; + }, + function (newVal, oldVal) { + if (newVal != oldVal) { + scope.onSetVolume(newVal); + } + } + ); + } + } + }] +); + +/** + * @ngdoc directive + * @name com.2fdevs.videogular.plugins.controls.directive:vgVolumeBar + * @restrict E + * @description + * Directive to display a vertical volume bar to control the volume. + * This directive must be inside vg-volume directive and requires vg-mute-button to be displayed. + * + * <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-volume> + * <vg-mute-button><vg-mute-button> + * <vg-volume-bar><vg-volume-bar> + * </vg-volume> + * </vg-controls> + * </videogular> + * </pre> + * + */ +angular.module("com.2fdevs.videogular.plugins.controls") + .run( + ["$templateCache", function ($templateCache) { + $templateCache.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 (VG_UTILS) { + return { + restrict: "E", + require: "^videogular", + templateUrl: function (elem, attrs) { + return attrs.vgTemplate || 'vg-templates/vg-volume-bar'; + }, + link: function (scope, elem, attr, API) { + var isChangingVolume = false; + var volumeBackElem = angular.element(elem[0].getElementsByClassName("volumeBackground")); + var volumeValueElem = angular.element(elem[0].getElementsByClassName("volumeValue")); + + scope.onClickVolume = function onClickVolume(event) { + event = VG_UTILS.fixEventOffset(event); + var volumeHeight = parseInt(volumeBackElem.prop("offsetHeight")); + var value = event.offsetY * 100 / volumeHeight; + var volValue = 1 - (value / 100); + + API.setVolume(volValue); + }; + + scope.onMouseDownVolume = function onMouseDownVolume() { + isChangingVolume = true; + }; + + scope.onMouseUpVolume = function onMouseUpVolume() { + isChangingVolume = false; + }; + + scope.onMouseLeaveVolume = function onMouseLeaveVolume() { + isChangingVolume = false; + }; + + scope.onMouseMoveVolume = function onMouseMoveVolume(event) { + if (isChangingVolume) { + event = VG_UTILS.fixEventOffset(event); + var volumeHeight = parseInt(volumeBackElem.prop("offsetHeight")); + var value = event.offsetY * 100 / volumeHeight; + var volValue = 1 - (value / 100); + + API.setVolume(volValue); + } + }; + + scope.updateVolumeView = function updateVolumeView(value) { + value = value * 100; + volumeValueElem.css("height", value + "%"); + volumeValueElem.css("top", (100 - value) + "%"); + }; + + scope.onChangeVisibility = function onChangeVisibility(value) { + elem.css("visibility", value); + }; + + elem.css("visibility", scope.volumeVisibility); + + scope.$watch("volumeVisibility", scope.onChangeVisibility); + + //Update the volume bar on initialization, then watch for changes + scope.updateVolumeView(API.volume); + scope.$watch( + function () { + return API.volume; + }, + function (newVal, oldVal) { + if (newVal != oldVal) { + scope.updateVolumeView(newVal); + } + } + ); + } + } + }] +); + +/** + * @ngdoc directive + * @name com.2fdevs.videogular.plugins.controls.directive:vgVolume + * @restrict E + * @description + * Directive to control the volume. + * This directive acts as a container and you will need other directives like vg-mutebutton and vg-volumebar to control the volume. + * In mobile will be hided since volume API is disabled for mobile devices. + * + * <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-volume></vg-volume> + * </vg-controls> + * </videogular> + * </pre> + * + */ +angular.module("com.2fdevs.videogular.plugins.controls") + .directive("vgVolume", + ["VG_UTILS", function (VG_UTILS) { + return { + restrict: "E", + link: function (scope, elem, attr) { + scope.onMouseOverVolume = function onMouseOverVolume() { + scope.$evalAsync(function () { + scope.volumeVisibility = "visible"; + }); + }; + + scope.onMouseLeaveVolume = function onMouseLeaveVolume() { + scope.$evalAsync(function () { + scope.volumeVisibility = "hidden"; + }); + }; + + // We hide volume controls on mobile devices + if (VG_UTILS.isMobileDevice()) { + elem.css("display", "none"); + } + else { + scope.volumeVisibility = "hidden"; + + elem.bind("mouseover", scope.onMouseOverVolume); + elem.bind("mouseleave", scope.onMouseLeaveVolume); + } + } + } + }] +); diff --git a/www/lib/videogular-controls/vg-controls.min.js b/www/lib/videogular-controls/vg-controls.min.js new file mode 100644 index 00000000..07fa4c65 --- /dev/null +++ b/www/lib/videogular-controls/vg-controls.min.js @@ -0,0 +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 diff --git a/www/lib/videogular-overlay-play/.bower.json b/www/lib/videogular-overlay-play/.bower.json new file mode 100644 index 00000000..22c499fd --- /dev/null +++ b/www/lib/videogular-overlay-play/.bower.json @@ -0,0 +1,19 @@ +{ + "name": "videogular-overlay-play", + "version": "1.3.2", + "main": "./vg-overlay-play.js", + "dependencies": { + "videogular": "~1.3.2" + }, + "homepage": "https://github.com/2fdevs/bower-videogular-overlay-play", + "_release": "1.3.2", + "_resolution": { + "type": "version", + "tag": "v1.3.2", + "commit": "8c68babdf2ad165be19983656a6dae4c4c0d9b21" + }, + "_source": "git://github.com/2fdevs/bower-videogular-overlay-play.git", + "_target": "~1.3.2", + "_originalSource": "videogular-overlay-play", + "_direct": true +}
\ No newline at end of file diff --git a/www/lib/videogular-overlay-play/.gitignore b/www/lib/videogular-overlay-play/.gitignore new file mode 100644 index 00000000..ac2c9712 --- /dev/null +++ b/www/lib/videogular-overlay-play/.gitignore @@ -0,0 +1,3 @@ +/node_modules/ +/bower_components/ +.idea
\ No newline at end of file diff --git a/www/lib/videogular-overlay-play/Gruntfile.js b/www/lib/videogular-overlay-play/Gruntfile.js new file mode 100644 index 00000000..e5b2f2f7 --- /dev/null +++ b/www/lib/videogular-overlay-play/Gruntfile.js @@ -0,0 +1,35 @@ +module.exports = function(grunt) { + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + release: { + options: { + //bump: false, //default: true + //file: 'bower.json', //default: package.json + //add: false, //default: true + //commit: false, //default: true + //tag: false, //default: true + //push: false, //default: true + //pushTags: false, //default: true + //npmtag: true, //default: no tag + //folder: 'folder/to/publish/to/npm', //default project root + //commitMessage: 'check out my release <%= version %>', //default: 'release <%= version %>' + //tagMessage: 'tagging version <%= version %>', //default: 'Version <%= version %>', + //tagName: 'v<%= version %>', //default: '<%= version %>' + + file: 'bower.json', //default: package.json + add: false, //default: true + commit: false, //default: true + tag: false, //default: true + push: false, //default: true + pushTags: false, //default: true + npm: false + } + } + }); + + grunt.loadNpmTasks('grunt-release'); + + grunt.registerTask('major', ['release:major']); + grunt.registerTask('minor', ['release:minor']); + grunt.registerTask('patch', ['release:patch']); +}; diff --git a/www/lib/videogular-overlay-play/LICENSE b/www/lib/videogular-overlay-play/LICENSE new file mode 100644 index 00000000..2a6b69f7 --- /dev/null +++ b/www/lib/videogular-overlay-play/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 2fdevs + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/www/lib/videogular-overlay-play/README.md b/www/lib/videogular-overlay-play/README.md new file mode 100644 index 00000000..80ce6c68 --- /dev/null +++ b/www/lib/videogular-overlay-play/README.md @@ -0,0 +1,59 @@ +bower-videogular-overlay-play +============================= + +Videogular `overlay-play` plugin repository for distribution on `bower`. + +## Install + +Install [Videogular](http://www.videogular.com/) `overlay-play` plugin with Bower: + +`bower install videogular-overlay-play` + +### Install Videogular + +Install [Videogular](http://www.videogular.com/) with Bower: + +`bower install videogular` + +### Install themes + +Install [Videogular](http://www.videogular.com/) themes with Bower: + +`bower install videogular-themes-default` + +### Install plugins + +Install [Videogular](http://www.videogular.com/) plugins with Bower: + +`bower install videogular-buffering` + +`bower install videogular-controls` + +`bower install videogular-poster` + +## Documentation + +It's available on [Videogular's project Wiki](https://github.com/2fdevs/videogular/wiki). + +## License + +The MIT License (MIT) + +Copyright (c) 2013 2fdevs + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/www/lib/videogular-overlay-play/bower.json b/www/lib/videogular-overlay-play/bower.json new file mode 100644 index 00000000..32166c2f --- /dev/null +++ b/www/lib/videogular-overlay-play/bower.json @@ -0,0 +1,8 @@ +{ + "name": "videogular-overlay-play", + "version": "1.3.2", + "main": "./vg-overlay-play.js", + "dependencies": { + "videogular": "~1.3.2" + } +} diff --git a/www/lib/videogular-overlay-play/index.js b/www/lib/videogular-overlay-play/index.js new file mode 100644 index 00000000..fe6e0b39 --- /dev/null +++ b/www/lib/videogular-overlay-play/index.js @@ -0,0 +1,3 @@ +require('./vg-overlay-play'); + +module.exports = 'com.2fdevs.videogular.plugins.overlayplay'; diff --git a/www/lib/videogular-overlay-play/package.json b/www/lib/videogular-overlay-play/package.json new file mode 100644 index 00000000..8a0202b5 --- /dev/null +++ b/www/lib/videogular-overlay-play/package.json @@ -0,0 +1,12 @@ +{ + "name": "videogular-overlay-play", + "version": "1.3.2", + "main": "index.js", + "devDependencies": { + "grunt": "~0.4.1", + "grunt-release": "~0.7.0" + }, + "engines": { + "node": ">=0.8.0" + } +} diff --git a/www/lib/videogular-overlay-play/vg-overlay-play.js b/www/lib/videogular-overlay-play/vg-overlay-play.js new file mode 100644 index 00000000..a5142f07 --- /dev/null +++ b/www/lib/videogular-overlay-play/vg-overlay-play.js @@ -0,0 +1,77 @@ +/** + * @license videogular v1.3.2 http://videogular.com + * Two Fucking Developers http://twofuckingdevelopers.com + * License: MIT + */ +/** + * @ngdoc directive + * @name com.2fdevs.videogular.plugins.overlayplay.directive:vgOverlayPlay + * @restrict E + * @description + * Shows a big play button centered when player is paused or stopped. + * + * <pre> + * <videogular vg-theme="config.theme.url" vg-autoplay="config.autoPlay"> + * <vg-media vg-src="sources"></vg-media> + * + * <vg-overlay-play></vg-overlay-play> + * </videogular> + * </pre> + * + */ +"use strict"; +angular.module("com.2fdevs.videogular.plugins.overlayplay", []) + .run( + ["$templateCache", function ($templateCache) { + $templateCache.put("vg-templates/vg-overlay-play", + '<div class="overlayPlayContainer" ng-click="onClickOverlayPlay()">\ + <div class="iconButton" ng-class="overlayPlayIcon"></div>\ + </div>'); + }] +) + .directive( + "vgOverlayPlay", + ["VG_STATES", function (VG_STATES) { + return { + restrict: "E", + require: "^videogular", + scope: {}, + templateUrl: function (elem, attrs) { + return attrs.vgTemplate || 'vg-templates/vg-overlay-play'; + }, + link: function (scope, elem, attr, API) { + scope.onChangeState = function onChangeState(newState) { + switch (newState) { + case VG_STATES.PLAY: + scope.overlayPlayIcon = {}; + break; + + case VG_STATES.PAUSE: + scope.overlayPlayIcon = {play: true}; + break; + + case VG_STATES.STOP: + scope.overlayPlayIcon = {play: true}; + break; + } + }; + + scope.onClickOverlayPlay = function onClickOverlayPlay(event) { + API.playPause(); + }; + + scope.overlayPlayIcon = {play: true}; + + scope.$watch( + function () { + return API.currentState; + }, + function (newVal, oldVal) { + scope.onChangeState(newVal); + } + ); + } + } + } + ]); + diff --git a/www/lib/videogular-overlay-play/vg-overlay-play.min.js b/www/lib/videogular-overlay-play/vg-overlay-play.min.js new file mode 100644 index 00000000..31a59c8a --- /dev/null +++ b/www/lib/videogular-overlay-play/vg-overlay-play.min.js @@ -0,0 +1 @@ +"use strict";angular.module("com.2fdevs.videogular.plugins.overlayplay",[]).run(["$templateCache",function(a){a.put("vg-templates/vg-overlay-play",'<div class="overlayPlayContainer" ng-click="onClickOverlayPlay()"> <div class="iconButton" ng-class="overlayPlayIcon"></div> </div>')}]).directive("vgOverlayPlay",["VG_STATES",function(a){return{restrict:"E",require:"^videogular",scope:{},templateUrl:function(a,b){return b.vgTemplate||"vg-templates/vg-overlay-play"},link:function(b,c,d,e){b.onChangeState=function(c){switch(c){case a.PLAY:b.overlayPlayIcon={};break;case a.PAUSE:b.overlayPlayIcon={play:!0};break;case a.STOP:b.overlayPlayIcon={play:!0}}},b.onClickOverlayPlay=function(a){e.playPause()},b.overlayPlayIcon={play:!0},b.$watch(function(){return e.currentState},function(a,c){b.onChangeState(a)})}}}]);
\ No newline at end of file diff --git a/www/lib/videogular-themes-default/.bower.json b/www/lib/videogular-themes-default/.bower.json new file mode 100644 index 00000000..fe245097 --- /dev/null +++ b/www/lib/videogular-themes-default/.bower.json @@ -0,0 +1,22 @@ +{ + "name": "videogular-themes-default", + "version": "1.3.2", + "main": [ + "./videogular.css", + "./fonts/*" + ], + "dependencies": { + "videogular": "~1.3.2" + }, + "homepage": "https://github.com/2fdevs/bower-videogular-themes-default", + "_release": "1.3.2", + "_resolution": { + "type": "version", + "tag": "v1.3.2", + "commit": "08233954c31e0b45b9f918de6dce117e14d951f8" + }, + "_source": "git://github.com/2fdevs/bower-videogular-themes-default.git", + "_target": "~1.3.2", + "_originalSource": "videogular-themes-default", + "_direct": true +}
\ No newline at end of file diff --git a/www/lib/videogular-themes-default/.gitignore b/www/lib/videogular-themes-default/.gitignore new file mode 100644 index 00000000..ac2c9712 --- /dev/null +++ b/www/lib/videogular-themes-default/.gitignore @@ -0,0 +1,3 @@ +/node_modules/ +/bower_components/ +.idea
\ No newline at end of file diff --git a/www/lib/videogular-themes-default/Gruntfile.js b/www/lib/videogular-themes-default/Gruntfile.js new file mode 100644 index 00000000..e5b2f2f7 --- /dev/null +++ b/www/lib/videogular-themes-default/Gruntfile.js @@ -0,0 +1,35 @@ +module.exports = function(grunt) { + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + release: { + options: { + //bump: false, //default: true + //file: 'bower.json', //default: package.json + //add: false, //default: true + //commit: false, //default: true + //tag: false, //default: true + //push: false, //default: true + //pushTags: false, //default: true + //npmtag: true, //default: no tag + //folder: 'folder/to/publish/to/npm', //default project root + //commitMessage: 'check out my release <%= version %>', //default: 'release <%= version %>' + //tagMessage: 'tagging version <%= version %>', //default: 'Version <%= version %>', + //tagName: 'v<%= version %>', //default: '<%= version %>' + + file: 'bower.json', //default: package.json + add: false, //default: true + commit: false, //default: true + tag: false, //default: true + push: false, //default: true + pushTags: false, //default: true + npm: false + } + } + }); + + grunt.loadNpmTasks('grunt-release'); + + grunt.registerTask('major', ['release:major']); + grunt.registerTask('minor', ['release:minor']); + grunt.registerTask('patch', ['release:patch']); +}; diff --git a/www/lib/videogular-themes-default/LICENSE b/www/lib/videogular-themes-default/LICENSE new file mode 100644 index 00000000..2a6b69f7 --- /dev/null +++ b/www/lib/videogular-themes-default/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 2fdevs + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/www/lib/videogular-themes-default/README.md b/www/lib/videogular-themes-default/README.md new file mode 100644 index 00000000..4627c8f1 --- /dev/null +++ b/www/lib/videogular-themes-default/README.md @@ -0,0 +1,55 @@ +bower-videogular-themes-default +=============================== + +Default Videogular's theme for distribution on `bower`. + +## Install theme + +Install [Videogular](http://www.videogular.com/) theme with Bower: + +`bower install videogular-themes-default` + +### Install Videogular + +Install [Videogular](http://www.videogular.com/) with Bower: + +`bower install videogular` + +### Install plugins + +Install [Videogular](http://www.videogular.com/) plugins with Bower: + +`bower install videogular-controls` + +`bower install videogular-buffering` + +`bower install videogular-overlay-play` + +`bower install videogular-poster` + +## Documentation + +It's available on [Videogular's project Wiki](https://github.com/2fdevs/videogular/wiki). + +## License + +The MIT License (MIT) + +Copyright (c) 2013 2fdevs + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/www/lib/videogular-themes-default/bower.json b/www/lib/videogular-themes-default/bower.json new file mode 100644 index 00000000..38f5332c --- /dev/null +++ b/www/lib/videogular-themes-default/bower.json @@ -0,0 +1,11 @@ +{ + "name": "videogular-themes-default", + "version": "1.3.2", + "main": [ + "./videogular.css", + "./fonts/*" + ], + "dependencies": { + "videogular": "~1.3.2" + } +} diff --git a/www/lib/videogular-themes-default/fonts/videogular.dev.svg b/www/lib/videogular-themes-default/fonts/videogular.dev.svg new file mode 100644 index 00000000..7d6b86f8 --- /dev/null +++ b/www/lib/videogular-themes-default/fonts/videogular.dev.svg @@ -0,0 +1,37 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > +<svg xmlns="http://www.w3.org/2000/svg"> +<metadata> +This is a custom SVG font generated by IcoMoon. +<iconset grid="16"></iconset> +</metadata> +<defs> +<font id="icomoon" horiz-adv-x="512" > +<font-face units-per-em="512" ascent="480" descent="-32" /> +<missing-glyph horiz-adv-x="512" /> +<glyph class="hidden" unicode="" d="M0,480L 512 -32L0 -32 z" horiz-adv-x="0" /> +<glyph unicode="" d="M 96,416L 416,224L 96,32 z" data-tags="play, media control, audio" /> +<glyph unicode="" d="M 64,416L 224,416L 224,32L 64,32zM 288,416L 448,416L 448,32L 288,32z" data-tags="pause, media control, audio" /> +<glyph unicode="" d="M 445.020,18.98c-6.143,0-12.284,2.343-16.971,7.029c-9.372,9.373-9.372,24.568,0,33.941 + C 471.868,103.771, 496.001,162.030, 496.001,224c0,61.969-24.133,120.229-67.952,164.049c-9.372,9.373-9.372,24.569,0,33.941 + c 9.372,9.372, 24.569,9.372, 33.941,0c 52.885-52.886, 82.011-123.2, 82.011-197.99c0-74.791-29.126-145.104-82.011-197.99 + C 457.304,21.323, 451.162,18.98, 445.020,18.98zM 359.765,64.235c-6.143,0-12.284,2.343-16.971,7.029c-9.372,9.372-9.372,24.568,0,33.941 + c 65.503,65.503, 65.503,172.085,0,237.588c-9.372,9.373-9.372,24.569,0,33.941c 9.372,9.371, 24.569,9.372, 33.941,0 + C 417.532,335.938, 440,281.696, 440,224c0-57.695-22.468-111.938-63.265-152.735C 372.049,66.578, 365.907,64.235, 359.765,64.235zM 274.51,109.49c-6.143,0-12.284,2.343-16.971,7.029c-9.373,9.373-9.373,24.568,0,33.941 + c 40.55,40.55, 40.55,106.529,0,147.078c-9.373,9.373-9.373,24.569,0,33.941c 9.373,9.372, 24.568,9.372, 33.941,0 + c 59.265-59.265, 59.265-155.696,0-214.961C 286.794,111.833, 280.652,109.49, 274.51,109.49zM 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" horiz-adv-x="544" data-tags="volume-high, speaker, media control, audio" /> +<glyph unicode="" d="M 359.765,64.235c-6.143,0-12.284,2.343-16.971,7.029c-9.372,9.372-9.372,24.568,0,33.941 + c 65.503,65.503, 65.503,172.085,0,237.588c-9.372,9.373-9.372,24.569,0,33.941c 9.372,9.371, 24.569,9.372, 33.941,0 + C 417.532,335.938, 440,281.696, 440,224c0-57.695-22.468-111.938-63.265-152.735C 372.049,66.578, 365.907,64.235, 359.765,64.235zM 274.51,109.49c-6.143,0-12.284,2.343-16.971,7.029c-9.373,9.373-9.373,24.568,0,33.941 + c 40.55,40.55, 40.55,106.529,0,147.078c-9.373,9.373-9.373,24.569,0,33.941c 9.373,9.372, 24.568,9.372, 33.941,0 + c 59.265-59.265, 59.265-155.696,0-214.961C 286.794,111.833, 280.652,109.49, 274.51,109.49zM 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" data-tags="volume-medium, speaker, media control, audio" /> +<glyph unicode="" d="M 274.51,109.49c-6.143,0-12.284,2.343-16.971,7.029c-9.373,9.373-9.373,24.568,0,33.941 + c 40.55,40.55, 40.55,106.529,0,147.078c-9.373,9.373-9.373,24.569,0,33.941c 9.373,9.372, 24.568,9.372, 33.941,0 + c 59.265-59.265, 59.265-155.696,0-214.961C 286.794,111.833, 280.652,109.49, 274.51,109.49zM 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" data-tags="volume-low, speaker, media control, audio" /> +<glyph unicode="" d="M 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" data-tags="volume-mute, speaker, media control, audio, mute" /> +<glyph unicode="" d="M 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 ZM 480,170.426 L 480,128 L 437.574,128 L 384,181.574 L 330.426,128 L 288,128 L 288,170.426 L 341.574,224 L 288,277.574 L 288,320 L 330.426,320 L 384,266.426 L 437.574,320 L 480,320 L 480,277.574 L 426.426,224 Z" data-tags="volume-mute, speaker, media control, audio, mute" /> +<glyph unicode="" d="M 512,480 L 512,288 L 442.87,357.13 L 336.87,251.13 L 283.13,304.87 L 389.13,410.87 L 320,480 ZM 122.87,410.87 L 228.87,304.87 L 175.13,251.13 L 69.13,357.13 L 0,288 L 0,480 L 192,480 ZM 442.87,90.87 L 512,160 L 512-32 L 320-32 L 389.13,37.13 L 283.13,143.13 L 336.87,196.87 ZM 228.87,143.13 L 122.87,37.13 L 192-32 L 0-32 L 0,160 L 69.13,90.87 L 175.13,196.87 Z" data-tags="expand, enlarge, maximize, fullscreen" /> +<glyph unicode="" d="M 32,192 L 224,192 L 224,0 L 154.87,69.13 L 53.87-31.87 L 0.13,21.87 L 101.13,122.87 ZM 410.87,122.87 L 511.87,21.87 L 458.13-31.87 L 357.13,69.13 L 288,0 L 288,192 L 480,192 ZM 480,256 L 288,256 L 288,448 L 357.13,378.87 L 458.13,479.87 L 511.87,426.13 L 410.87,325.13 ZM 154.87,378.87 L 224,448 L 224,256 L 32,256 L 101.13,325.13 L 0.13,426.13 L 53.87,479.87 Z" data-tags="contract, minimize, shrink, collapse" /> +<glyph unicode="" d="M 512,288 L 320,288 L 391.765,359.765 C 355.5,396.028 307.285,416 256,416 C 204.715,416 156.5,396.028 120.235,359.765 C 83.972,323.5 64,275.285 64,224 C 64,172.715 83.972,124.5 120.235,88.235 C 156.5,51.972 204.715,32 256,32 C 307.285,32 355.5,51.972 391.764,88.236 C 394.792,91.263 397.694,94.382 400.492,97.57 L 448.652,55.429 C 401.729,1.846 332.82-32 256-32 C 114.615-32 0,82.615 0,224 C 0,365.385 114.615,480 256,480 C 326.693,480 390.684,451.337 437.008,405.008 L 512,480 L 512,288 Z" data-tags="spinner, loading, busy, wait, wheel, repeat" /> +<glyph unicode=" " horiz-adv-x="256" /> +</font></defs></svg>
\ No newline at end of file diff --git a/www/lib/videogular-themes-default/fonts/videogular.eot b/www/lib/videogular-themes-default/fonts/videogular.eot Binary files differnew file mode 100644 index 00000000..cf6b47e2 --- /dev/null +++ b/www/lib/videogular-themes-default/fonts/videogular.eot diff --git a/www/lib/videogular-themes-default/fonts/videogular.svg b/www/lib/videogular-themes-default/fonts/videogular.svg new file mode 100644 index 00000000..96d7b5cf --- /dev/null +++ b/www/lib/videogular-themes-default/fonts/videogular.svg @@ -0,0 +1,37 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > +<svg xmlns="http://www.w3.org/2000/svg"> +<metadata> +This is a custom SVG font generated by IcoMoon. +<iconset grid="16"></iconset> +</metadata> +<defs> +<font id="icomoon" horiz-adv-x="512" > +<font-face units-per-em="512" ascent="480" descent="-32" /> +<missing-glyph horiz-adv-x="512" /> +<glyph class="hidden" unicode="" d="M0,480L 512 -32L0 -32 z" horiz-adv-x="0" /> +<glyph unicode="" d="M 96,416L 416,224L 96,32 z" /> +<glyph unicode="" d="M 64,416L 224,416L 224,32L 64,32zM 288,416L 448,416L 448,32L 288,32z" /> +<glyph unicode="" d="M 445.020,18.98c-6.143,0-12.284,2.343-16.971,7.029c-9.372,9.373-9.372,24.568,0,33.941 + C 471.868,103.771, 496.001,162.030, 496.001,224c0,61.969-24.133,120.229-67.952,164.049c-9.372,9.373-9.372,24.569,0,33.941 + c 9.372,9.372, 24.569,9.372, 33.941,0c 52.885-52.886, 82.011-123.2, 82.011-197.99c0-74.791-29.126-145.104-82.011-197.99 + C 457.304,21.323, 451.162,18.98, 445.020,18.98zM 359.765,64.235c-6.143,0-12.284,2.343-16.971,7.029c-9.372,9.372-9.372,24.568,0,33.941 + c 65.503,65.503, 65.503,172.085,0,237.588c-9.372,9.373-9.372,24.569,0,33.941c 9.372,9.371, 24.569,9.372, 33.941,0 + C 417.532,335.938, 440,281.696, 440,224c0-57.695-22.468-111.938-63.265-152.735C 372.049,66.578, 365.907,64.235, 359.765,64.235zM 274.51,109.49c-6.143,0-12.284,2.343-16.971,7.029c-9.373,9.373-9.373,24.568,0,33.941 + c 40.55,40.55, 40.55,106.529,0,147.078c-9.373,9.373-9.373,24.569,0,33.941c 9.373,9.372, 24.568,9.372, 33.941,0 + c 59.265-59.265, 59.265-155.696,0-214.961C 286.794,111.833, 280.652,109.49, 274.51,109.49zM 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" horiz-adv-x="544" /> +<glyph unicode="" d="M 359.765,64.235c-6.143,0-12.284,2.343-16.971,7.029c-9.372,9.372-9.372,24.568,0,33.941 + c 65.503,65.503, 65.503,172.085,0,237.588c-9.372,9.373-9.372,24.569,0,33.941c 9.372,9.371, 24.569,9.372, 33.941,0 + C 417.532,335.938, 440,281.696, 440,224c0-57.695-22.468-111.938-63.265-152.735C 372.049,66.578, 365.907,64.235, 359.765,64.235zM 274.51,109.49c-6.143,0-12.284,2.343-16.971,7.029c-9.373,9.373-9.373,24.568,0,33.941 + c 40.55,40.55, 40.55,106.529,0,147.078c-9.373,9.373-9.373,24.569,0,33.941c 9.373,9.372, 24.568,9.372, 33.941,0 + c 59.265-59.265, 59.265-155.696,0-214.961C 286.794,111.833, 280.652,109.49, 274.51,109.49zM 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" /> +<glyph unicode="" d="M 274.51,109.49c-6.143,0-12.284,2.343-16.971,7.029c-9.373,9.373-9.373,24.568,0,33.941 + c 40.55,40.55, 40.55,106.529,0,147.078c-9.373,9.373-9.373,24.569,0,33.941c 9.373,9.372, 24.568,9.372, 33.941,0 + c 59.265-59.265, 59.265-155.696,0-214.961C 286.794,111.833, 280.652,109.49, 274.51,109.49zM 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" /> +<glyph unicode="" d="M 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" /> +<glyph unicode="" d="M 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 ZM 480,170.426 L 480,128 L 437.574,128 L 384,181.574 L 330.426,128 L 288,128 L 288,170.426 L 341.574,224 L 288,277.574 L 288,320 L 330.426,320 L 384,266.426 L 437.574,320 L 480,320 L 480,277.574 L 426.426,224 Z" /> +<glyph unicode="" d="M 512,480 L 512,288 L 442.87,357.13 L 336.87,251.13 L 283.13,304.87 L 389.13,410.87 L 320,480 ZM 122.87,410.87 L 228.87,304.87 L 175.13,251.13 L 69.13,357.13 L 0,288 L 0,480 L 192,480 ZM 442.87,90.87 L 512,160 L 512-32 L 320-32 L 389.13,37.13 L 283.13,143.13 L 336.87,196.87 ZM 228.87,143.13 L 122.87,37.13 L 192-32 L 0-32 L 0,160 L 69.13,90.87 L 175.13,196.87 Z" /> +<glyph unicode="" d="M 32,192 L 224,192 L 224,0 L 154.87,69.13 L 53.87-31.87 L 0.13,21.87 L 101.13,122.87 ZM 410.87,122.87 L 511.87,21.87 L 458.13-31.87 L 357.13,69.13 L 288,0 L 288,192 L 480,192 ZM 480,256 L 288,256 L 288,448 L 357.13,378.87 L 458.13,479.87 L 511.87,426.13 L 410.87,325.13 ZM 154.87,378.87 L 224,448 L 224,256 L 32,256 L 101.13,325.13 L 0.13,426.13 L 53.87,479.87 Z" /> +<glyph unicode="" d="M 512,288 L 320,288 L 391.765,359.765 C 355.5,396.028 307.285,416 256,416 C 204.715,416 156.5,396.028 120.235,359.765 C 83.972,323.5 64,275.285 64,224 C 64,172.715 83.972,124.5 120.235,88.235 C 156.5,51.972 204.715,32 256,32 C 307.285,32 355.5,51.972 391.764,88.236 C 394.792,91.263 397.694,94.382 400.492,97.57 L 448.652,55.429 C 401.729,1.846 332.82-32 256-32 C 114.615-32 0,82.615 0,224 C 0,365.385 114.615,480 256,480 C 326.693,480 390.684,451.337 437.008,405.008 L 512,480 L 512,288 Z" /> +<glyph unicode=" " horiz-adv-x="256" /> +</font></defs></svg>
\ No newline at end of file diff --git a/www/lib/videogular-themes-default/fonts/videogular.ttf b/www/lib/videogular-themes-default/fonts/videogular.ttf Binary files differnew file mode 100644 index 00000000..3837d8ec --- /dev/null +++ b/www/lib/videogular-themes-default/fonts/videogular.ttf diff --git a/www/lib/videogular-themes-default/fonts/videogular.woff b/www/lib/videogular-themes-default/fonts/videogular.woff Binary files differnew file mode 100644 index 00000000..0e08bdbb --- /dev/null +++ b/www/lib/videogular-themes-default/fonts/videogular.woff diff --git a/www/lib/videogular-themes-default/package.json b/www/lib/videogular-themes-default/package.json new file mode 100644 index 00000000..b8bcec92 --- /dev/null +++ b/www/lib/videogular-themes-default/package.json @@ -0,0 +1,12 @@ +{ + "name": "videogular-themes-default", + "version": "1.3.2", + "main": "videogular.css", + "devDependencies": { + "grunt": "~0.4.1", + "grunt-release": "~0.7.0" + }, + "engines": { + "node": ">=0.8.0" + } +} diff --git a/www/lib/videogular-themes-default/videogular.css b/www/lib/videogular-themes-default/videogular.css new file mode 100644 index 00000000..de4a7acb --- /dev/null +++ b/www/lib/videogular-themes-default/videogular.css @@ -0,0 +1,430 @@ +/** + * @license videogular v1.2.7 http://videogular.com + * Two Fucking Developers http://twofuckingdevelopers.com + * License: MIT + */ +@font-face { + font-family: 'videogular'; + src: url("fonts/videogular.eot"); + src: url("fonts/videogular.eot?#iefix") format("embedded-opentype"), url("fonts/videogular.woff") format("woff"), url("fonts/videogular.ttf") format("truetype"), url("fonts/videogular.svg#videogular") format("svg"); + font-weight: normal; + font-style: normal; } +videogular, [videogular] { + width: 100%; + height: 100%; + position: relative; + background-color: #000000; + display: block; + flex-direction: column; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: moz-none; + -ms-user-select: none; + user-select: none; + /*****************/ + /* Poster plugin */ + /*****************/ + /**********************/ + /* OverlayPlay plugin */ + /**********************/ + /*********************/ + /* Controlbar plugin */ + /*********************/ + /* IE10 hack */ + /* Controlbar icons */ + /********************/ + /* Buffering plugin */ + /********************/ + /* Loading Spinner + * http://www.alessioatzeni.com/blog/css3-loading-animation-loop/ + */ + /**********************/ + /* IMA ads plugin */ + /**********************/ } + videogular button, [videogular] button { + cursor: pointer; } + videogular.fullscreen, [videogular].fullscreen { + position: fixed; + left: 0; + top: 0; } + videogular vg-media, [videogular] vg-media { + width: 100%; + height: 100%; + max-width: 100%; + max-height: 100%; + display: block; } + videogular vg-media video, [videogular] vg-media video { + width: 100%; + height: 100%; + max-width: 100%; + max-height: 100%; } + videogular .iconButton, [videogular] .iconButton { + color: #FFFFFF; + font-family: 'videogular'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + background: none; + padding: 6px; + border: none; } + videogular .iconButton:focus, [videogular] .iconButton:focus { + border: 1px solid white; } + videogular vg-poster, [videogular] vg-poster { + width: 100%; + height: 100%; + max-width: 100%; + max-height: 100%; + position: absolute; + display: block; + z-index: 1; + top: 0; + pointer-events: none; } + videogular vg-poster img, [videogular] vg-poster img { + width: auto; + height: auto; + max-width: 100%; + max-height: 100%; + top: 0; + bottom: 0; + right: 0; + left: 0; + margin: auto; + position: absolute; } + videogular vg-poster img.pause, + videogular vg-poster img.play, [videogular] vg-poster img.pause, + [videogular] vg-poster img.play { + display: none; } + videogular vg-poster img.stop, [videogular] vg-poster img.stop { + display: block; } + videogular vg-overlay-play, [videogular] vg-overlay-play { + width: 100%; + height: 100%; + max-width: 100%; + max-height: 100%; + position: absolute; + z-index: 2; + top: 0; } + videogular vg-overlay-play .play:before, [videogular] vg-overlay-play .play:before { + content: "\e000"; } + videogular vg-overlay-play .overlayPlayContainer, [videogular] vg-overlay-play .overlayPlayContainer { + font-size: 100px; + width: 100%; + height: 100%; + max-width: 100%; + max-height: 100%; + position: absolute; + display: table; + cursor: pointer; + zoom: 1; + filter: alpha(opacity=60); + opacity: 0.6; } + videogular vg-overlay-play .overlayPlayContainer div, [videogular] vg-overlay-play .overlayPlayContainer div { + vertical-align: middle; + text-align: center; + display: table-cell; } + videogular vg-controls, [videogular] vg-controls { + width: 100%; + height: 50px; + display: block; + position: absolute; + z-index: 3; + bottom: 0; } + videogular vg-controls .controls-container, [videogular] vg-controls .controls-container { + width: 100%; + height: 50px; + background-color: rgba(0, 0, 0, 0.5); + position: absolute; + display: table; + zoom: 1; } + videogular vg-play-pause-button, [videogular] vg-play-pause-button { + display: table-cell; + width: 50px; + vertical-align: middle; + text-align: center; + cursor: pointer; } + videogular vg-time-display, [videogular] vg-time-display { + color: #FFFFFF; + display: table-cell; + font-family: Arial; + font-size: 18px; + width: 75px; + vertical-align: middle; + text-align: center; + cursor: default; } + videogular .vgTimeDisplay, [videogular] .vgTimeDisplay { + display: table-cell; + font-family: Arial; + font-size: 18px; + width: auto; } + videogular vg-scrub-bar, [videogular] vg-scrub-bar { + width: auto; + display: table-cell; + cursor: pointer; + vertical-align: middle; } + videogular vg-scrub-bar [role=slider], [videogular] vg-scrub-bar [role=slider] { + margin-top: 24px; + margin-bottom: 24px; + height: 2px; + background-color: black; + position: relative; } + videogular vg-scrub-bar :focus vg-scrub-bar-current-time, [videogular] vg-scrub-bar :focus vg-scrub-bar-current-time { + border-right: 6px black groove; } + videogular vg-scrub-bar-current-time, [videogular] vg-scrub-bar-current-time { + background-color: #FFFFFF; + width: 100%; + height: 100%; + display: block; + cursor: pointer; } + videogular vg-scrub-bar-buffer, [videogular] vg-scrub-bar-buffer { + position: absolute; + background-color: #FFFFFF; + width: 100%; + height: 100%; + display: block; + cursor: pointer; + zoom: 1; + filter: alpha(opacity=50); + opacity: 0.5; } + videogular vg-scrub-bar-cue-points, [videogular] vg-scrub-bar-cue-points { + width: 100%; + height: 100%; + display: block; + position: relative; } + videogular vg-scrub-bar-cue-points .cue-point-timeline, [videogular] vg-scrub-bar-cue-points .cue-point-timeline { + color: #FFFFFF; + padding-top: 3px; } + videogular vg-scrub-bar-cue-points .cue-point-timeline .cue-point, [videogular] vg-scrub-bar-cue-points .cue-point-timeline .cue-point { + position: absolute; + height: 3px; + background-color: #FFFFFF; } + videogular vg-playback-button, [videogular] vg-playback-button { + display: table-cell; + width: 50px; + vertical-align: middle; + text-align: center; + cursor: pointer; } + videogular vg-volume, [videogular] vg-volume { + display: table-cell; + width: 50px; + vertical-align: middle; + text-align: center; + cursor: pointer; } + videogular vg-volume-bar, [videogular] vg-volume-bar { + width: 50px; + height: 100px; + top: -100px; + margin-left: -25px; + vertical-align: middle; + text-align: center; + position: absolute; + cursor: pointer; } + @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { + videogular vg-volume-bar, [videogular] vg-volume-bar { + zoom: 1; + filter: alpha(opacity=50); + opacity: 0.5; } } + videogular vg-fullscreen-button, [videogular] vg-fullscreen-button { + display: table-cell; + width: 50px; + vertical-align: middle; + text-align: center; + cursor: pointer; } + videogular vg-volume-bar .verticalVolumeBar, [videogular] vg-volume-bar .verticalVolumeBar { + width: 50px; + height: 100px; + background-color: #000000; + position: absolute; } + videogular vg-volume-bar .volumeBackground, [videogular] vg-volume-bar .volumeBackground { + width: 20px; + height: 70px; + left: 15px; + top: 15px; + background-color: #222222; + position: absolute; } + videogular vg-volume-bar .volumeValue, [videogular] vg-volume-bar .volumeValue { + width: 20px; + height: 100%; + background-color: #FFFFFF; + position: absolute; } + videogular vg-volume-bar .volumeClickArea, [videogular] vg-volume-bar .volumeClickArea { + width: 20px; + height: 100%; + position: absolute; } + videogular vg-controls .hide-animation, [videogular] vg-controls .hide-animation { + animation: hideControlsAnimationFrames ease-out 0.5s; + animation-iteration-count: 1; + animation-fill-mode: forwards; + /*when the spec is finished*/ + -webkit-animation: hideControlsAnimationFrames ease-out 0.5s; + -webkit-animation-iteration-count: 1; + -webkit-animation-fill-mode: forwards; + /*Chrome 16+, Safari 4+*/ + -moz-animation: hideControlsAnimationFrames ease-out 0.5s; + -moz-animation-iteration-count: 1; + -moz-animation-fill-mode: forwards; + /*FF 5+*/ + -o-animation: hideControlsAnimationFrames ease-out 0.5s; + -o-animation-iteration-count: 1; + -o-animation-fill-mode: forwards; + /*Not implemented yet*/ + -ms-animation: hideControlsAnimationFrames ease-out 0.5s; + -ms-animation-iteration-count: 1; + -ms-animation-fill-mode: forwards; + /*IE 10+*/ } +@keyframes hideControlsAnimationFrames { + 0% { + opacity: 0.5; } + 100% { + opacity: 0; } } +@-moz-keyframes hideControlsAnimationFrames { + 0% { + opacity: 0.5; } + 100% { + opacity: 0; } } +@-webkit-keyframes hideControlsAnimationFrames { + 0% { + opacity: 0.5; } + 100% { + opacity: 0; } } +@-o-keyframes hideControlsAnimationFrames { + 0% { + opacity: 0.5; } + 100% { + opacity: 0; } } +@-ms-keyframes hideControlsAnimationFrames { + 0% { + opacity: 0.5; } + 100% { + opacity: 0; } } + videogular vg-controls .show-animation, [videogular] vg-controls .show-animation { + animation: showControlsAnimationFrames ease-out 0.5s; + animation-iteration-count: 1; + animation-fill-mode: forwards; + /*when the spec is finished*/ + -webkit-animation: showControlsAnimationFrames ease-out 0.5s; + -webkit-animation-iteration-count: 1; + -webkit-animation-fill-mode: forwards; + /*Chrome 16+, Safari 4+*/ + -moz-animation: showControlsAnimationFrames ease-out 0.5s; + -moz-animation-iteration-count: 1; + -moz-animation-fill-mode: forwards; + /*FF 5+*/ + -o-animation: showControlsAnimationFrames ease-out 0.5s; + -o-animation-iteration-count: 1; + -o-animation-fill-mode: forwards; + /*Not implemented yet*/ + -ms-animation: showControlsAnimationFrames ease-out 0.5s; + -ms-animation-iteration-count: 1; + -ms-animation-fill-mode: forwards; + /*IE 10+*/ } +@keyframes showControlsAnimationFrames { + 0% { + background-color: transparent; } + 100% { + background-color: rgba(0, 0, 0, 0.5); } } +@-moz-keyframes showControlsAnimationFrames { + 0% { + background-color: transparent; } + 100% { + background-color: rgba(0, 0, 0, 0.5); } } +@-webkit-keyframes showControlsAnimationFrames { + 0% { + background-color: transparent; } + 100% { + background-color: rgba(0, 0, 0, 0.5); } } +@-o-keyframes showControlsAnimationFrames { + 0% { + background-color: transparent; } + 100% { + background-color: rgba(0, 0, 0, 0.5); } } +@-ms-keyframes showControlsAnimationFrames { + 0% { + background-color: transparent; } + 100% { + background-color: rgba(0, 0, 0, 0.5); } } + videogular vg-play-pause-button .play:before, [videogular] vg-play-pause-button .play:before { + content: "\e000"; } + videogular vg-play-pause-button .pause:before, [videogular] vg-play-pause-button .pause:before { + content: "\e001"; } + videogular vg-mute-button, [videogular] vg-mute-button { + width: 50px; + display: block; } + videogular vg-mute-button .level3:before, [videogular] vg-mute-button .level3:before { + content: "\e002"; } + videogular vg-mute-button .level2:before, [videogular] vg-mute-button .level2:before { + content: "\e003"; } + videogular vg-mute-button .level1:before, [videogular] vg-mute-button .level1:before { + content: "\e004"; } + videogular vg-mute-button .level0:before, [videogular] vg-mute-button .level0:before { + content: "\e005"; } + videogular vg-mute-button .mute:before, [videogular] vg-mute-button .mute:before { + content: "\e006"; } + videogular vg-fullscreen-button .enter:before, [videogular] vg-fullscreen-button .enter:before { + content: "\e007"; } + videogular vg-fullscreen-button .exit:before, [videogular] vg-fullscreen-button .exit:before { + content: "\e008"; } + videogular vg-buffering, [videogular] vg-buffering { + width: 100%; + height: 100%; + position: absolute; + z-index: 4; + top: 0; } + videogular vg-buffering .bufferingContainer, [videogular] vg-buffering .bufferingContainer { + width: 100%; + position: absolute; + cursor: pointer; + top: 50%; + margin-top: -50px; + zoom: 1; + filter: alpha(opacity=60); + opacity: 0.6; } + videogular vg-buffering .loadingSpinner, [videogular] vg-buffering .loadingSpinner { + background-color: transparent; + border: 5px solid white; + opacity: .9; + border-top: 5px solid transparent; + border-left: 5px solid transparent; + border-radius: 50px; + box-shadow: 0 0 35px #FFFFFF; + width: 50px; + height: 50px; + margin: 0 auto; + -moz-animation: spin .5s infinite linear; + -webkit-animation: spin .5s infinite linear; } + videogular vg-buffering .loadingSpinner .stop, [videogular] vg-buffering .loadingSpinner .stop { + -webkit-animation-play-state: paused; + -moz-animation-play-state: paused; } +@-moz-keyframes spin { + 0% { + -moz-transform: rotate(0deg); } + 100% { + -moz-transform: rotate(360deg); } } +@-moz-keyframes spinoff { + 0% { + -moz-transform: rotate(0deg); } + 100% { + -moz-transform: rotate(-360deg); } } +@-webkit-keyframes spin { + 0% { + -webkit-transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(360deg); } } +@-webkit-keyframes spinoff { + 0% { + -webkit-transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(-360deg); } } + videogular vg-ima-ads, [videogular] vg-ima-ads { + width: 100%; + height: 100%; + position: absolute; + z-index: 5; + top: 0; + display: none; } + +/*# sourceMappingURL=videogular.css.map */ diff --git a/www/lib/videogular-themes-default/videogular.css.map b/www/lib/videogular-themes-default/videogular.css.map new file mode 100644 index 00000000..139cd09c --- /dev/null +++ b/www/lib/videogular-themes-default/videogular.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": ";;;;;AAKA,UASC;EARG,WAAW,EAAE,YAAY;EACzB,GAAG,EAAE,2BAA2B;EAChC,GAAG,EAAE,iNAA8D;EAInE,WAAW,EAAE,MAAM;EACnB,UAAU,EAAE,MAAM;AAGtB,wBAAyB;EACrB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,QAAQ,EAAE,QAAQ;EAClB,gBAAgB,EAAE,OAAO;EACzB,OAAO,EAAE,KAAK;EACd,cAAc,EAAE,MAAM;EAEtB,qBAAqB,EAAE,IAAI;EAC3B,mBAAmB,EAAE,IAAI;EACzB,kBAAkB,EAAE,IAAI;EACxB,gBAAgB,EAAE,QAAQ;EAC1B,eAAe,EAAE,IAAI;EACrB,WAAW,EAAE,IAAI;;;;;;;;;;;;;;;;;;;;;EAEjB,sCAAO;IACH,MAAM,EAAE,OAAO;EAGnB,8CAAa;IACT,QAAQ,EAAE,KAAK;IACf,IAAI,EAAE,CAAC;IACP,GAAG,EAAE,CAAC;EAGV,0CAAS;IACL,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,IAAI;IAEhB,OAAO,EAAE,KAAK;IAEd,sDAAM;MACF,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,IAAI;MACZ,SAAS,EAAE,IAAI;MACf,UAAU,EAAE,IAAI;EAIxB,gDAAY;IACR,KAAK,EAAE,OAAO;IACd,WAAW,EAAE,YAAY;IACzB,KAAK,EAAE,IAAI;IACX,UAAU,EAAE,MAAM;IAClB,WAAW,EAAE,MAAM;IACnB,YAAY,EAAE,MAAM;IACpB,cAAc,EAAE,IAAI;IACpB,WAAW,EAAE,CAAC;IACd,sBAAsB,EAAE,WAAW;IAEnC,UAAU,EAAE,IAAI;IAChB,OAAO,EAAE,GAAG;IACZ,MAAM,EAAE,IAAI;EAGhB,4DAAkB;IACd,MAAM,EAAE,eAAe;EAM3B,4CAAU;IACN,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,IAAI;IAChB,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,KAAK;IACd,OAAO,EAAE,CAAC;IACV,GAAG,EAAE,CAAC;IACN,cAAc,EAAE,IAAI;EAGxB,oDAAc;IACV,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,IAAI;IAEhB,GAAG,EAAE,CAAC;IACN,MAAM,EAAE,CAAC;IACT,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,IAAI;IACZ,QAAQ,EAAE,QAAQ;EAGtB;;iCACmB;IACf,OAAO,EAAE,IAAI;EAGjB,8DAAmB;IACf,OAAO,EAAE,KAAK;EAMlB,wDAAgB;IACZ,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,IAAI;IAChB,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,CAAC;IACV,GAAG,EAAE,CAAC;EAGV,kFAA6B;IACzB,OAAO,EAAE,OAAO;EAGpB,oGAAsC;IAClC,SAAS,EAAE,KAAK;IAChB,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,IAAI;IAChB,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,KAAK;IACd,MAAM,EAAE,OAAO;IAEf,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,iBAAiB;IACzB,OAAO,EAAE,GAAG;EAGhB,4GAA0C;IACtC,cAAc,EAAE,MAAM;IACtB,UAAU,EAAE,MAAM;IAClB,OAAO,EAAE,UAAU;EAMvB,gDAAY;IACR,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,OAAO,EAAE,KAAK;IACd,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,CAAC;IACV,MAAM,EAAE,CAAC;EAGb,wFAAgC;IAC5B,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,gBAAgB,EAAE,kBAAkB;IACpC,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,KAAK;IAEd,IAAI,EAAE,CAAC;EAGX,kEAAqB;IACjB,OAAO,EAAE,UAAU;IACnB,KAAK,EAAE,IAAI;IACX,cAAc,EAAE,MAAM;IACtB,UAAU,EAAE,MAAM;IAClB,MAAM,EAAE,OAAO;EAGnB,wDAAgB;IACZ,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,UAAU;IACnB,WAAW,EAAE,KAAK;IAClB,SAAS,EAAE,IAAI;IACf,KAAK,EAAE,IAAI;IACX,cAAc,EAAE,MAAM;IACtB,UAAU,EAAE,MAAM;IAClB,MAAM,EAAE,OAAO;EAGnB,sDAAe;IACX,OAAO,EAAE,UAAU;IACnB,WAAW,EAAE,KAAK;IAClB,SAAS,EAAE,IAAI;IACf,KAAK,EAAE,IAAI;EAGf,kDAAa;IACT,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,UAAU;IACnB,MAAM,EAAE,OAAO;IACf,cAAc,EAAE,MAAM;EAG1B,8EAA2B;IACvB,UAAU,EAAE,IAAI;IAChB,aAAa,EAAE,IAAI;IACnB,MAAM,EAAE,GAAG;IACX,gBAAgB,EAAE,KAAK;IACvB,QAAQ,EAAE,QAAQ;EAGtB,oHAA8C;IAC1C,YAAY,EAAE,gBAAgB;EAGlC,4EAA0B;IACtB,gBAAgB,EAAE,OAAO;IACzB,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,OAAO,EAAE,KAAK;IACd,MAAM,EAAE,OAAO;EAGnB,gEAAoB;IAChB,QAAQ,EAAE,QAAQ;IAClB,gBAAgB,EAAE,OAAO;IACzB,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,OAAO,EAAE,KAAK;IACd,MAAM,EAAE,OAAO;IAEf,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,iBAAiB;IACzB,OAAO,EAAE,GAAG;EAGhB,wEAAwB;IACpB,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,OAAO,EAAE,KAAK;IACd,QAAQ,EAAE,QAAQ;IAElB,gHAAoB;MAChB,KAAK,EAAE,OAAO;MACd,WAAW,EAAE,GAAG;MAEhB,sIAAW;QACP,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,GAAG;QACX,gBAAgB,EAAE,OAAO;EAKrC,8DAAmB;IACf,OAAO,EAAE,UAAU;IACnB,KAAK,EAAE,IAAI;IACX,cAAc,EAAE,MAAM;IACtB,UAAU,EAAE,MAAM;IAClB,MAAM,EAAE,OAAO;EAGnB,4CAAU;IACN,OAAO,EAAE,UAAU;IACnB,KAAK,EAAE,IAAI;IACX,cAAc,EAAE,MAAM;IACtB,UAAU,EAAE,MAAM;IAClB,MAAM,EAAE,OAAO;EAGnB,oDAAc;IACV,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,KAAK;IACb,GAAG,EAAE,MAAM;IACX,WAAW,EAAE,KAAK;IAClB,cAAc,EAAE,MAAM;IACtB,UAAU,EAAE,MAAM;IAClB,QAAQ,EAAE,QAAQ;IAClB,MAAM,EAAE,OAAO;EAInB,wEAAyE;IACrE,oDAAc;MACV,IAAI,EAAE,CAAC;MACP,MAAM,EAAE,iBAAiB;MACzB,OAAO,EAAE,GAAG;EAIpB,kEAAqB;IACjB,OAAO,EAAE,UAAU;IACnB,KAAK,EAAE,IAAI;IACX,cAAc,EAAE,MAAM;IACtB,UAAU,EAAE,MAAM;IAClB,MAAM,EAAE,OAAO;EAGnB,0FAAiC;IAC7B,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,KAAK;IACb,gBAAgB,EAAE,OAAO;IACzB,QAAQ,EAAE,QAAQ;EAGtB,wFAAgC;IAC5B,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,IAAI,EAAE,IAAI;IACV,GAAG,EAAE,IAAI;IACT,gBAAgB,EAAE,OAAO;IACzB,QAAQ,EAAE,QAAQ;EAGtB,8EAA2B;IACvB,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,gBAAgB,EAAE,OAAO;IACzB,QAAQ,EAAE,QAAQ;EAGtB,sFAA+B;IAC3B,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,QAAQ,EAAE,QAAQ;EAGtB,gFAA4B;IACxB,SAAS,EAAE,yCAAyC;IACpD,yBAAyB,EAAE,CAAC;IAC5B,mBAAmB,EAAE,QAAQ;;IAC7B,iBAAiB,EAAE,yCAAyC;IAC5D,iCAAiC,EAAE,CAAC;IACpC,2BAA2B,EAAE,QAAQ;;IACrC,cAAc,EAAE,yCAAyC;IACzD,8BAA8B,EAAE,CAAC;IACjC,wBAAwB,EAAE,QAAQ;;IAClC,YAAY,EAAE,yCAAyC;IACvD,4BAA4B,EAAE,CAAC;IAC/B,sBAAsB,EAAE,QAAQ;;IAChC,aAAa,EAAE,yCAAyC;IACxD,6BAA6B,EAAE,CAAC;IAChC,uBAAuB,EAAE,QAAQ;;AAGrC,sCAOC;EANG,EAAG;IACC,OAAO,EAAE,GAAG;EAEhB,IAAK;IACD,OAAO,EAAE,CAAC;AAIlB,2CAOC;EANG,EAAG;IACC,OAAO,EAAE,GAAG;EAEhB,IAAK;IACD,OAAO,EAAE,CAAC;AAIlB,8CAOC;EANG,EAAG;IACC,OAAO,EAAE,GAAG;EAEhB,IAAK;IACD,OAAO,EAAE,CAAC;AAIlB,yCAOC;EANG,EAAG;IACC,OAAO,EAAE,GAAG;EAEhB,IAAK;IACD,OAAO,EAAE,CAAC;AAIlB,0CAOC;EANG,EAAG;IACC,OAAO,EAAE,GAAG;EAEhB,IAAK;IACD,OAAO,EAAE,CAAC;EAIlB,gFAA4B;IACxB,SAAS,EAAE,yCAAyC;IACpD,yBAAyB,EAAE,CAAC;IAC5B,mBAAmB,EAAE,QAAQ;;IAC7B,iBAAiB,EAAE,yCAAyC;IAC5D,iCAAiC,EAAE,CAAC;IACpC,2BAA2B,EAAE,QAAQ;;IACrC,cAAc,EAAE,yCAAyC;IACzD,8BAA8B,EAAE,CAAC;IACjC,wBAAwB,EAAE,QAAQ;;IAClC,YAAY,EAAE,yCAAyC;IACvD,4BAA4B,EAAE,CAAC;IAC/B,sBAAsB,EAAE,QAAQ;;IAChC,aAAa,EAAE,yCAAyC;IACxD,6BAA6B,EAAE,CAAC;IAChC,uBAAuB,EAAE,QAAQ;;AAGrC,sCAOC;EANG,EAAG;IACC,gBAAgB,EAAE,WAAgB;EAEtC,IAAK;IACD,gBAAgB,EAAE,kBAAkB;AAI5C,2CAOC;EANG,EAAG;IACC,gBAAgB,EAAE,WAAgB;EAEtC,IAAK;IACD,gBAAgB,EAAE,kBAAkB;AAI5C,8CAOC;EANG,EAAG;IACC,gBAAgB,EAAE,WAAgB;EAEtC,IAAK;IACD,gBAAgB,EAAE,kBAAkB;AAI5C,yCAOC;EANG,EAAG;IACC,gBAAgB,EAAE,WAAgB;EAEtC,IAAK;IACD,gBAAgB,EAAE,kBAAkB;AAI5C,0CAOC;EANG,EAAG;IACC,gBAAgB,EAAE,WAAgB;EAEtC,IAAK;IACD,gBAAgB,EAAE,kBAAkB;EAK5C,4FAAkC;IAC9B,OAAO,EAAE,OAAO;EAGpB,8FAAmC;IAC/B,OAAO,EAAE,OAAO;EAGpB,sDAAe;IACX,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,KAAK;EAGlB,oFAA8B;IAC1B,OAAO,EAAE,OAAO;EAGpB,oFAA8B;IAC1B,OAAO,EAAE,OAAO;EAGpB,oFAA8B;IAC1B,OAAO,EAAE,OAAO;EAGpB,oFAA8B;IAC1B,OAAO,EAAE,OAAO;EAGpB,gFAA4B;IACxB,OAAO,EAAE,OAAO;EAGpB,8FAAmC;IAC/B,OAAO,EAAE,OAAO;EAGpB,4FAAkC;IAC9B,OAAO,EAAE,OAAO;EAMpB,kDAAa;IACT,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,CAAC;IACV,GAAG,EAAE,CAAC;EAGV,0FAAiC;IAC7B,KAAK,EAAE,IAAI;IACX,QAAQ,EAAE,QAAQ;IAClB,MAAM,EAAE,OAAO;IACf,GAAG,EAAE,GAAG;IACR,UAAU,EAAE,KAAK;IAEjB,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,iBAAiB;IACzB,OAAO,EAAE,GAAG;EAMhB,kFAA6B;IACzB,gBAAgB,EAAE,WAAgB;IAClC,MAAM,EAAE,eAAgC;IACxC,OAAO,EAAE,EAAE;IACX,UAAU,EAAE,qBAA0B;IACtC,WAAW,EAAE,qBAA0B;IACvC,aAAa,EAAE,IAAI;IACnB,UAAU,EAAE,gBAAgB;IAC5B,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,MAAM,EAAE,MAAM;IACd,cAAc,EAAE,wBAAwB;IACxC,iBAAiB,EAAE,wBAAwB;EAG/C,8FAAmC;IAC/B,4BAA4B,EAAE,MAAM;IACpC,yBAAyB,EAAE,MAAM;AAGrC,oBAOC;EANG,EAAG;IACC,cAAc,EAAE,YAAY;EAEhC,IAAK;IACD,cAAc,EAAE,cAAc;AAItC,uBAOC;EANG,EAAG;IACC,cAAc,EAAE,YAAY;EAEhC,IAAK;IACD,cAAc,EAAE,eAAe;AAIvC,uBAOC;EANG,EAAG;IACC,iBAAiB,EAAE,YAAY;EAEnC,IAAK;IACD,iBAAiB,EAAE,cAAc;AAIzC,0BAOC;EANG,EAAG;IACC,iBAAiB,EAAE,YAAY;EAEnC,IAAK;IACD,iBAAiB,EAAE,eAAe;EAO1C,8CAAW;IACP,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,CAAC;IACV,GAAG,EAAE,CAAC;IACN,OAAO,EAAE,IAAI", +"sources": ["videogular.scss"], +"names": [], +"file": "videogular.css" +}
\ No newline at end of file diff --git a/www/lib/videogular-themes-default/videogular.min.css b/www/lib/videogular-themes-default/videogular.min.css new file mode 100644 index 00000000..78465e69 --- /dev/null +++ b/www/lib/videogular-themes-default/videogular.min.css @@ -0,0 +1 @@ +@font-face{font-family:videogular;src:url(fonts/videogular.eot);src:url(fonts/videogular.eot?#iefix) format("embedded-opentype"),url(fonts/videogular.woff) format("woff"),url(fonts/videogular.ttf) format("truetype"),url(fonts/videogular.svg#videogular) format("svg");font-weight:400;font-style:normal}videogular,[videogular]{width:100%;height:100%;position:relative;background-color:#000;display:block;flex-direction:column;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:moz-none;-ms-user-select:none;user-select:none}videogular button,[videogular] button{cursor:pointer}videogular.fullscreen,[videogular].fullscreen{position:fixed;left:0;top:0}videogular vg-media,[videogular] vg-media{width:100%;height:100%;max-width:100%;max-height:100%;display:block}videogular vg-media video,[videogular] vg-media video{width:100%;height:100%;max-width:100%;max-height:100%}videogular .iconButton,[videogular] .iconButton{color:#FFF;font-family:videogular;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;background:0 0;padding:6px;border:0}videogular .iconButton:focus,[videogular] .iconButton:focus{border:1px solid #fff}videogular vg-poster,[videogular] vg-poster{width:100%;height:100%;max-width:100%;max-height:100%;position:absolute;display:block;z-index:1;top:0;pointer-events:none}videogular vg-poster img,[videogular] vg-poster img{width:auto;height:auto;max-width:100%;max-height:100%;top:0;bottom:0;right:0;left:0;margin:auto;position:absolute}videogular vg-poster img.pause,videogular vg-poster img.play,[videogular] vg-poster img.pause,[videogular] vg-poster img.play{display:none}videogular vg-poster img.stop,[videogular] vg-poster img.stop{display:block}videogular vg-overlay-play,[videogular] vg-overlay-play{width:100%;height:100%;max-width:100%;max-height:100%;position:absolute;z-index:2;top:0}videogular vg-overlay-play .play:before,[videogular] vg-overlay-play .play:before{content:"\e000"}videogular vg-overlay-play .overlayPlayContainer,[videogular] vg-overlay-play .overlayPlayContainer{font-size:100px;width:100%;height:100%;max-width:100%;max-height:100%;position:absolute;display:table;cursor:pointer;zoom:1;filter:alpha(opacity=60);opacity:.6}videogular vg-overlay-play .overlayPlayContainer div,[videogular] vg-overlay-play .overlayPlayContainer div{vertical-align:middle;text-align:center;display:table-cell}videogular vg-controls,[videogular] vg-controls{width:100%;height:50px;display:block;position:absolute;z-index:3;bottom:0}videogular vg-controls .controls-container,[videogular] vg-controls .controls-container{width:100%;height:50px;background-color:rgba(0,0,0,.5);position:absolute;display:table;zoom:1}videogular vg-play-pause-button,[videogular] vg-play-pause-button{display:table-cell;width:50px;vertical-align:middle;text-align:center;cursor:pointer}videogular vg-time-display,[videogular] vg-time-display{color:#FFF;display:table-cell;font-family:Arial;font-size:18px;width:75px;vertical-align:middle;text-align:center;cursor:default}videogular .vgTimeDisplay,[videogular] .vgTimeDisplay{display:table-cell;font-family:Arial;font-size:18px;width:auto}videogular vg-scrub-bar,[videogular] vg-scrub-bar{width:auto;display:table-cell;cursor:pointer;vertical-align:middle}videogular vg-scrub-bar [role=slider],[videogular] vg-scrub-bar [role=slider]{margin-top:24px;margin-bottom:24px;height:2px;background-color:#000;position:relative}videogular vg-scrub-bar :focus vg-scrub-bar-current-time,[videogular] vg-scrub-bar :focus vg-scrub-bar-current-time{border-right:6px #000 groove}videogular vg-scrub-bar-current-time,[videogular] vg-scrub-bar-current-time{background-color:#FFF;width:100%;height:100%;display:block;cursor:pointer}videogular vg-scrub-bar-buffer,[videogular] vg-scrub-bar-buffer{position:absolute;background-color:#FFF;width:100%;height:100%;display:block;cursor:pointer;zoom:1;filter:alpha(opacity=50);opacity:.5}videogular vg-scrub-bar-cue-points,[videogular] vg-scrub-bar-cue-points{width:100%;height:100%;display:block;position:relative}videogular vg-scrub-bar-cue-points .cue-point-timeline,[videogular] vg-scrub-bar-cue-points .cue-point-timeline{color:#FFF;padding-top:3px}videogular vg-scrub-bar-cue-points .cue-point-timeline .cue-point,[videogular] vg-scrub-bar-cue-points .cue-point-timeline .cue-point{position:absolute;height:3px;background-color:#FFF}videogular vg-playback-button,[videogular] vg-playback-button{display:table-cell;width:50px;vertical-align:middle;text-align:center;cursor:pointer}videogular vg-volume,[videogular] vg-volume{display:table-cell;width:50px;vertical-align:middle;text-align:center;cursor:pointer}videogular vg-volume-bar,[videogular] vg-volume-bar{width:50px;height:100px;top:-100px;margin-left:-25px;vertical-align:middle;text-align:center;position:absolute;cursor:pointer}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){videogular vg-volume-bar,[videogular] vg-volume-bar{zoom:1;filter:alpha(opacity=50);opacity:.5}}videogular vg-fullscreen-button,[videogular] vg-fullscreen-button{display:table-cell;width:50px;vertical-align:middle;text-align:center;cursor:pointer}videogular vg-volume-bar .verticalVolumeBar,[videogular] vg-volume-bar .verticalVolumeBar{width:50px;height:100px;background-color:#000;position:absolute}videogular vg-volume-bar .volumeBackground,[videogular] vg-volume-bar .volumeBackground{width:20px;height:70px;left:15px;top:15px;background-color:#222;position:absolute}videogular vg-volume-bar .volumeValue,[videogular] vg-volume-bar .volumeValue{width:20px;height:100%;background-color:#FFF;position:absolute}videogular vg-volume-bar .volumeClickArea,[videogular] vg-volume-bar .volumeClickArea{width:20px;height:100%;position:absolute}videogular vg-controls .hide-animation,[videogular] vg-controls .hide-animation{animation:hideControlsAnimationFrames ease-out .5s;animation-iteration-count:1;animation-fill-mode:forwards;-webkit-animation:hideControlsAnimationFrames ease-out .5s;-webkit-animation-iteration-count:1;-webkit-animation-fill-mode:forwards;-moz-animation:hideControlsAnimationFrames ease-out .5s;-moz-animation-iteration-count:1;-moz-animation-fill-mode:forwards;-o-animation:hideControlsAnimationFrames ease-out .5s;-o-animation-iteration-count:1;-o-animation-fill-mode:forwards;-ms-animation:hideControlsAnimationFrames ease-out .5s;-ms-animation-iteration-count:1;-ms-animation-fill-mode:forwards}@keyframes hideControlsAnimationFrames{0%{opacity:.5}100%{opacity:0}}@-moz-keyframes hideControlsAnimationFrames{0%{opacity:.5}100%{opacity:0}}@-webkit-keyframes hideControlsAnimationFrames{0%{opacity:.5}100%{opacity:0}}@-o-keyframes hideControlsAnimationFrames{0%{opacity:.5}100%{opacity:0}}@-ms-keyframes hideControlsAnimationFrames{0%{opacity:.5}100%{opacity:0}}videogular vg-controls .show-animation,[videogular] vg-controls .show-animation{animation:showControlsAnimationFrames ease-out .5s;animation-iteration-count:1;animation-fill-mode:forwards;-webkit-animation:showControlsAnimationFrames ease-out .5s;-webkit-animation-iteration-count:1;-webkit-animation-fill-mode:forwards;-moz-animation:showControlsAnimationFrames ease-out .5s;-moz-animation-iteration-count:1;-moz-animation-fill-mode:forwards;-o-animation:showControlsAnimationFrames ease-out .5s;-o-animation-iteration-count:1;-o-animation-fill-mode:forwards;-ms-animation:showControlsAnimationFrames ease-out .5s;-ms-animation-iteration-count:1;-ms-animation-fill-mode:forwards}@keyframes showControlsAnimationFrames{0%{background-color:transparent}100%{background-color:rgba(0,0,0,.5)}}@-moz-keyframes showControlsAnimationFrames{0%{background-color:transparent}100%{background-color:rgba(0,0,0,.5)}}@-webkit-keyframes showControlsAnimationFrames{0%{background-color:transparent}100%{background-color:rgba(0,0,0,.5)}}@-o-keyframes showControlsAnimationFrames{0%{background-color:transparent}100%{background-color:rgba(0,0,0,.5)}}@-ms-keyframes showControlsAnimationFrames{0%{background-color:transparent}100%{background-color:rgba(0,0,0,.5)}}videogular vg-play-pause-button .play:before,[videogular] vg-play-pause-button .play:before{content:"\e000"}videogular vg-play-pause-button .pause:before,[videogular] vg-play-pause-button .pause:before{content:"\e001"}videogular vg-mute-button,[videogular] vg-mute-button{width:50px;display:block}videogular vg-mute-button .level3:before,[videogular] vg-mute-button .level3:before{content:"\e002"}videogular vg-mute-button .level2:before,[videogular] vg-mute-button .level2:before{content:"\e003"}videogular vg-mute-button .level1:before,[videogular] vg-mute-button .level1:before{content:"\e004"}videogular vg-mute-button .level0:before,[videogular] vg-mute-button .level0:before{content:"\e005"}videogular vg-mute-button .mute:before,[videogular] vg-mute-button .mute:before{content:"\e006"}videogular vg-fullscreen-button .enter:before,[videogular] vg-fullscreen-button .enter:before{content:"\e007"}videogular vg-fullscreen-button .exit:before,[videogular] vg-fullscreen-button .exit:before{content:"\e008"}videogular vg-buffering,[videogular] vg-buffering{width:100%;height:100%;position:absolute;z-index:4;top:0}videogular vg-buffering .bufferingContainer,[videogular] vg-buffering .bufferingContainer{width:100%;position:absolute;cursor:pointer;top:50%;margin-top:-50px;zoom:1;filter:alpha(opacity=60);opacity:.6}videogular vg-buffering .loadingSpinner,[videogular] vg-buffering .loadingSpinner{background-color:transparent;border:5px solid #fff;opacity:.9;border-top:5px solid transparent;border-left:5px solid transparent;border-radius:50px;box-shadow:0 0 35px #FFF;width:50px;height:50px;margin:0 auto;-moz-animation:spin .5s infinite linear;-webkit-animation:spin .5s infinite linear}videogular vg-buffering .loadingSpinner .stop,[videogular] vg-buffering .loadingSpinner .stop{-webkit-animation-play-state:paused;-moz-animation-play-state:paused}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(360deg)}}@-moz-keyframes spinoff{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(-360deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg)}}@-webkit-keyframes spinoff{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(-360deg)}}videogular vg-ima-ads,[videogular] vg-ima-ads{width:100%;height:100%;position:absolute;z-index:5;top:0;display:none}
\ No newline at end of file diff --git a/www/lib/videogular/.bower.json b/www/lib/videogular/.bower.json new file mode 100644 index 00000000..f105cfd7 --- /dev/null +++ b/www/lib/videogular/.bower.json @@ -0,0 +1,20 @@ +{ + "name": "videogular", + "version": "1.3.2", + "main": "./videogular.js", + "dependencies": { + "angular": "^1.3.x", + "angular-sanitize": "^1.3.x" + }, + "homepage": "https://github.com/2fdevs/bower-videogular", + "_release": "1.3.2", + "_resolution": { + "type": "version", + "tag": "v1.3.2", + "commit": "b0c01c91bd5277797d3a02e5546a5b31423cfeaa" + }, + "_source": "git://github.com/2fdevs/bower-videogular.git", + "_target": "~1.3.2", + "_originalSource": "videogular", + "_direct": true +}
\ No newline at end of file diff --git a/www/lib/videogular/.gitignore b/www/lib/videogular/.gitignore new file mode 100644 index 00000000..ac2c9712 --- /dev/null +++ b/www/lib/videogular/.gitignore @@ -0,0 +1,3 @@ +/node_modules/ +/bower_components/ +.idea
\ No newline at end of file diff --git a/www/lib/videogular/Gruntfile.js b/www/lib/videogular/Gruntfile.js new file mode 100644 index 00000000..e5b2f2f7 --- /dev/null +++ b/www/lib/videogular/Gruntfile.js @@ -0,0 +1,35 @@ +module.exports = function(grunt) { + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + release: { + options: { + //bump: false, //default: true + //file: 'bower.json', //default: package.json + //add: false, //default: true + //commit: false, //default: true + //tag: false, //default: true + //push: false, //default: true + //pushTags: false, //default: true + //npmtag: true, //default: no tag + //folder: 'folder/to/publish/to/npm', //default project root + //commitMessage: 'check out my release <%= version %>', //default: 'release <%= version %>' + //tagMessage: 'tagging version <%= version %>', //default: 'Version <%= version %>', + //tagName: 'v<%= version %>', //default: '<%= version %>' + + file: 'bower.json', //default: package.json + add: false, //default: true + commit: false, //default: true + tag: false, //default: true + push: false, //default: true + pushTags: false, //default: true + npm: false + } + } + }); + + grunt.loadNpmTasks('grunt-release'); + + grunt.registerTask('major', ['release:major']); + grunt.registerTask('minor', ['release:minor']); + grunt.registerTask('patch', ['release:patch']); +}; diff --git a/www/lib/videogular/LICENSE b/www/lib/videogular/LICENSE new file mode 100644 index 00000000..2a6b69f7 --- /dev/null +++ b/www/lib/videogular/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 2fdevs + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/www/lib/videogular/README.md b/www/lib/videogular/README.md new file mode 100644 index 00000000..770ed70e --- /dev/null +++ b/www/lib/videogular/README.md @@ -0,0 +1,55 @@ +bower-videogular +================ + +Videogular repository for distribution on `bower`. + +## Install + +Install [Videogular](http://www.videogular.com/) with Bower: + +`bower install videogular` + +### Install themes + +Install [Videogular](http://www.videogular.com/) themes with Bower: + +`bower install videogular-themes-default` + +### Install plugins + +Install [Videogular](http://www.videogular.com/) plugins with Bower: + +`bower install videogular-controls` + +`bower install videogular-buffering` + +`bower install videogular-overlay-play` + +`bower install videogular-poster` + +## Documentation + +It's available on [Videogular's project Wiki](https://github.com/2fdevs/videogular/wiki). + +## License + +The MIT License (MIT) + +Copyright (c) 2013 2fdevs + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/www/lib/videogular/bower.json b/www/lib/videogular/bower.json new file mode 100644 index 00000000..c593e6c9 --- /dev/null +++ b/www/lib/videogular/bower.json @@ -0,0 +1,9 @@ +{ + "name": "videogular", + "version": "1.3.2", + "main": "./videogular.js", + "dependencies": { + "angular": "^1.3.x", + "angular-sanitize": "^1.3.x" + } +} diff --git a/www/lib/videogular/index.js b/www/lib/videogular/index.js new file mode 100644 index 00000000..51945645 --- /dev/null +++ b/www/lib/videogular/index.js @@ -0,0 +1,5 @@ +require('angular'); +require('angular-sanitize'); +require('./videogular'); + +module.exports = 'com.2fdevs.videogular'; diff --git a/www/lib/videogular/package.json b/www/lib/videogular/package.json new file mode 100644 index 00000000..ee4603b7 --- /dev/null +++ b/www/lib/videogular/package.json @@ -0,0 +1,12 @@ +{ + "name": "videogular", + "version": "1.3.2", + "main": "index.js", + "devDependencies": { + "grunt": "~0.4.1", + "grunt-release": "~0.7.0" + }, + "engines": { + "node": ">=0.8.0" + } +} diff --git a/www/lib/videogular/videogular.js b/www/lib/videogular/videogular.js new file mode 100644 index 00000000..5685b076 --- /dev/null +++ b/www/lib/videogular/videogular.js @@ -0,0 +1,1473 @@ +/** + * @license videogular v1.3.2 http://videogular.com + * Two Fucking Developers http://twofuckingdevelopers.com + * License: MIT + */ +"use strict"; +angular.module("com.2fdevs.videogular", ["ngSanitize"]) + .run( + ["$templateCache", function ($templateCache) { + $templateCache.put("vg-templates/vg-media-video", "<video></video>"); + $templateCache.put("vg-templates/vg-media-audio", "<audio></audio>"); + + // Support for browsers that doesn't have .bind() + if (!Function.prototype.bind) { + Function.prototype.bind = function (oThis) { + if (typeof this !== 'function') { + // closest thing possible to the ECMAScript 5 + // internal IsCallable function + throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); + } + + var aArgs = Array.prototype.slice.call(arguments, 1), + fToBind = this, + fNOP = function () { + }, + fBound = function () { + return fToBind.apply(this instanceof fNOP + ? this + : oThis, + aArgs.concat(Array.prototype.slice.call(arguments))); + }; + + fNOP.prototype = this.prototype; + fBound.prototype = new fNOP(); + + return fBound; + }; + } + }] +); + +/** + * @ngdoc service + * @name com.2fdevs.videogular.constant:VG_STATES + * + * @description + * Possible video states: + * - VG_STATES.PLAY: "play" + * - VG_STATES.PAUSE: "pause" + * - VG_STATES.STOP: "stop" + **/ +/** + * @ngdoc service + * @name com.2fdevs.videogular.constant:VG_VOLUME_KEY + * + * @description localStorage key name for persistent video play volume on a domain. + **/ +"use strict"; +angular.module("com.2fdevs.videogular") + .constant("VG_STATES", { + PLAY: "play", + PAUSE: "pause", + STOP: "stop" + }) + .constant("VG_VOLUME_KEY", "videogularVolume"); + +"use strict"; +/** + * @ngdoc controller + * @name com.2fdevs.videogular.controller:vgController + * @description + * Videogular controller. + * This controller offers a public API: + * + * Methods + * - play(): Plays media. + * - pause(): Pause media. + * - stop(): Stops media. + * - playPause(): Toggles play and pause. + * - seekTime(value, byPercent): Seeks to a specified time position. Param value must be an integer representing the target position in seconds or a percentage. By default seekTime seeks by seconds, if you want to seek by percentage just pass byPercent to true. + * - setVolume(volume): Sets volume. Param volume must be an integer with a value between 0 and 1. + * - setPlayback(playback): Sets playback. Param plaback must be an integer with a value between 0 and 2. + * - setState(state): Sets a new state. Param state mus be an string with 'play', 'pause' or 'stop'. This method only changes the state of the player, but doesn't plays, pauses or stops the media file. + * - toggleFullScreen(): Toggles between fullscreen and normal mode. + * - updateTheme(css-url): Removes previous CSS theme and sets a new one. + * - clearMedia(): Cleans the current media file. + * - changeSource(array): Updates current media source. Param `array` must be an array of media source objects. + * A media source is an object with two properties `src` and `type`. The `src` property must contains a trustful url resource. + * <pre>{src: $sce.trustAsResourceUrl("http://static.videogular.com/assets/videos/videogular.mp4"), type: "video/mp4"}</pre> + * + * Properties + * - config: String with a url to JSON config file. + * - isReady: Boolean value with current player initialization state. + * - isBuffering: Boolean value to know if player is buffering media. + * - isCompleted: Boolean value to know if current media file has been completed. + * - isLive: Boolean value to know if current media file is a Live Streaming. + * - playsInline: Boolean value to know if Videogular is using inline playing or not. + * - nativeFullscreen: Boolean value to know if Videogular if fullscreen mode will use native mode or emulated mode. + * - mediaElement: Reference to video/audio object. + * - videogularElement: Reference to videogular tag. + * - sources: Array with current sources. + * - tracks: Array with current tracks. + * - cuePoints: Object containing a list of timelines with cue points. Each property in the object represents a timeline, which is an Array of objects with the next definition: + * <pre>{ + * timeLapse:{ + * start: 0, + * end: 10 + * }, + * onEnter: callback(currentTime, timeLapse, params), + * onLeave: callback(currentTime, timeLapse, params), + * onUpdate: callback(currentTime, timeLapse, params), + * onComplete: callback(currentTime, timeLapse, params), + * params: { + * // Custom object with desired structure and data + * } + * }</pre> + * + * * **timeLapse:** Object with start and end properties to define in seconds when this timeline is active.\n + * * **onEnter:** Callback function that will be called when progress reaches a cue point or being outside a cue point user seeks to a cue point manually. + * * **onLeave:** Callback function that will be called when user seeks and the new time doesn't reach to the timeLapse.start property. + * * **onUpdate:** Callback function that will be called when the progress is in the middle of timeLapse.start and timeLapse.end. + * * **onComplete:** Callback function that will be called when the progress is bigger than timeLapse.end. + * * **params:** Custom object with data to pass to the callbacks. + * + * - isFullScreen: Boolean value to know if we’re in fullscreen mode. + * - currentState: String value with “play”, “pause” or “stop”. + * - currentTime: Number value with current media time progress. + * - totalTime: Number value with total media time. + * - timeLeft: Number value with current media time left. + * - volume: Number value with current volume between 0 and 1. + * - playback: Number value with current playback between 0 and 2. + * - bufferEnd: Number value with latest buffer point in milliseconds. + * - buffered: Array of TimeRanges objects that represents current buffer state. + * + */ +angular.module("com.2fdevs.videogular") + .controller("vgController", + ['$scope', '$window', 'vgConfigLoader', 'vgFullscreen', 'VG_UTILS', 'VG_STATES', 'VG_VOLUME_KEY', function ($scope, $window, vgConfigLoader, vgFullscreen, VG_UTILS, VG_STATES, VG_VOLUME_KEY) { + var currentTheme = null; + var isFullScreenPressed = false; + var isMetaDataLoaded = false; + + // PUBLIC $API + this.videogularElement = null; + + this.clearMedia = function () { + this.mediaElement[0].src = ''; + }; + + this.onRouteChange = function() { + if (this.clearMediaOnNavigate === undefined || this.clearMediaOnNavigate === true) { + this.clearMedia(); + } + }; + + this.onCanPlay = function (evt) { + this.isBuffering = false; + $scope.$apply($scope.vgCanPlay({$event: evt})); + }; + + this.onVideoReady = function () { + this.isReady = true; + this.autoPlay = $scope.vgAutoPlay; + this.playsInline = $scope.vgPlaysInline; + this.nativeFullscreen = $scope.vgNativeFullscreen || true; + this.cuePoints = $scope.vgCuePoints; + this.clearMediaOnNavigate = $scope.vgClearMediaOnNavigate || true; + this.currentState = VG_STATES.STOP; + + isMetaDataLoaded = true; + + //Set media volume from localStorage if available + if (VG_UTILS.supportsLocalStorage()) { + //Default to 100% volume if local storage setting does not exist. + this.setVolume(parseFloat($window.localStorage.getItem(VG_VOLUME_KEY) || '1')); + } + + if ($scope.vgConfig) { + vgConfigLoader.loadConfig($scope.vgConfig).then( + this.onLoadConfig.bind(this) + ); + } + else { + $scope.vgPlayerReady({$API: this}); + } + }; + + this.onLoadConfig = function (config) { + this.config = config; + + $scope.vgTheme = this.config.theme; + $scope.vgAutoPlay = this.config.autoPlay; + $scope.vgPlaysInline = this.config.playsInline; + $scope.vgNativeFullscreen = this.config.nativeFullscreen; + $scope.vgCuePoints = this.config.cuePoints; + $scope.vgClearMediaOnNavigate = this.config.clearMediaOnNavigate; + + $scope.vgPlayerReady({$API: this}); + }; + + this.onLoadMetaData = function (evt) { + this.isBuffering = false; + this.onUpdateTime(evt); + }; + + this.onProgress = function (event) { + if (event.target.buffered.length) { + this.buffered = event.target.buffered; + this.bufferEnd = 1000 * event.target.buffered.end(event.target.buffered.length - 1); + } + + $scope.$apply(); + }; + + this.onUpdateTime = function (event) { + this.currentTime = 1000 * event.target.currentTime; + + if (event.target.buffered.length) { + this.buffered = event.target.buffered; + this.bufferEnd = 1000 * event.target.buffered.end(event.target.buffered.length - 1); + } + + if (event.target.duration != Infinity) { + this.totalTime = 1000 * event.target.duration; + this.timeLeft = 1000 * (event.target.duration - event.target.currentTime); + this.isLive = false; + } + else { + // It's a live streaming without and end + this.isLive = true; + } + + if (this.cuePoints) { + this.checkCuePoints(event.target.currentTime); + } + + $scope.vgUpdateTime({$currentTime: event.target.currentTime, $duration: event.target.duration}); + + $scope.$apply(); + }; + + this.checkCuePoints = function checkCuePoints(currentTime) { + for (var tl in this.cuePoints) { + for (var i = 0, l = this.cuePoints[tl].length; i < l; i++) { + var cp = this.cuePoints[tl][i]; + var currentSecond = parseInt(currentTime, 10); + var start = parseInt(cp.timeLapse.start, 10); + + // If timeLapse.end is not defined we set it as 1 second length + if (!cp.timeLapse.end) cp.timeLapse.end = cp.timeLapse.start + 1; + + if (currentTime < cp.timeLapse.end) cp.$$isCompleted = false; + + // Fire the onEnter event once reach to the cue point + if(!cp.$$isDirty && currentSecond === start && (typeof cp.onEnter == 'function')) { + cp.onEnter(currentTime, cp.timeLapse, cp.params); + cp.$$isDirty = true; + } + + // Check if we've been reached to the cue point + if (currentTime > cp.timeLapse.start) { + // We're in the timelapse + if (currentTime < cp.timeLapse.end) { + // Trigger onUpdate each time we enter here + if (cp.onUpdate) cp.onUpdate(currentTime, cp.timeLapse, cp.params); + + // Trigger onEnter if we enter on the cue point by manually seeking + if (!cp.$$isDirty && (typeof cp.onEnter === 'function')) { + cp.onEnter(currentTime, cp.timeLapse, cp.params); + } + } + + // We've been passed the cue point + if (currentTime >= cp.timeLapse.end) { + if (cp.onComplete && !cp.$$isCompleted) { + cp.$$isCompleted = true; + cp.onComplete(currentTime, cp.timeLapse, cp.params); + } + } + + cp.$$isDirty = true; + } + else { + if (cp.onLeave && cp.$$isDirty) { + cp.onLeave(currentTime, cp.timeLapse, cp.params); + } + + cp.$$isDirty = false; + } + } + } + }; + + this.onPlay = function () { + this.setState(VG_STATES.PLAY); + $scope.$apply(); + }; + + this.onPause = function () { + if (this.mediaElement[0].currentTime == 0) { + this.setState(VG_STATES.STOP); + } + else { + this.setState(VG_STATES.PAUSE); + } + + $scope.$apply(); + }; + + this.onVolumeChange = function () { + this.volume = this.mediaElement[0].volume; + $scope.$apply(); + }; + + this.onPlaybackChange = function () { + this.playback = this.mediaElement[0].playbackRate; + $scope.$apply(); + }; + + this.onSeeking = function (event) { + $scope.vgSeeking({$currentTime: event.target.currentTime, $duration: event.target.duration}); + }; + + this.onSeeked = function (event) { + $scope.vgSeeked({$currentTime: event.target.currentTime, $duration: event.target.duration}); + }; + + this.seekTime = function (value, byPercent) { + var second; + if (byPercent) { + second = value * this.mediaElement[0].duration / 100; + this.mediaElement[0].currentTime = second; + } + else { + second = value; + this.mediaElement[0].currentTime = second; + } + + this.currentTime = 1000 * second; + }; + + this.playPause = function () { + if (this.mediaElement[0].paused) { + this.play(); + } + else { + this.pause(); + } + }; + + this.setState = function (newState) { + if (newState && newState != this.currentState) { + $scope.vgUpdateState({$state: newState}); + + this.currentState = newState; + } + + return this.currentState; + }; + + this.play = function () { + this.mediaElement[0].play(); + this.setState(VG_STATES.PLAY); + }; + + this.pause = function () { + this.mediaElement[0].pause(); + this.setState(VG_STATES.PAUSE); + }; + + this.stop = function () { + try { + this.mediaElement[0].pause(); + this.mediaElement[0].currentTime = 0; + + this.currentTime = 0; + this.buffered = []; + this.bufferEnd = 0; + this.setState(VG_STATES.STOP); + } + catch (e) { + return e; + } + }; + + this.toggleFullScreen = function () { + // There is no native full screen support or we want to play inline + if (!vgFullscreen.isAvailable || !this.nativeFullscreen) { + if (this.isFullScreen) { + this.videogularElement.removeClass("fullscreen"); + this.videogularElement.css("z-index", "auto"); + } + else { + this.videogularElement.addClass("fullscreen"); + this.videogularElement.css("z-index", VG_UTILS.getZIndex()); + } + + this.isFullScreen = !this.isFullScreen; + } + // Perform native full screen support + else { + if (this.isFullScreen) { + if (!VG_UTILS.isMobileDevice()) { + vgFullscreen.exit(); + } + } + else { + // On mobile devices we should make fullscreen only the video object + if (VG_UTILS.isMobileDevice()) { + // On iOS we should check if user pressed before fullscreen button + // and also if metadata is loaded + if (VG_UTILS.isiOSDevice()) { + if (isMetaDataLoaded) { + this.enterElementInFullScreen(this.mediaElement[0]); + } + else { + isFullScreenPressed = true; + this.play(); + } + } + else { + this.enterElementInFullScreen(this.mediaElement[0]); + } + } + else { + this.enterElementInFullScreen(this.videogularElement[0]); + } + } + } + }; + + this.enterElementInFullScreen = function (element) { + vgFullscreen.request(element); + }; + + this.changeSource = function (newValue) { + $scope.vgChangeSource({$source: newValue}); + }; + + this.setVolume = function (newVolume) { + newVolume = Math.max(Math.min(newVolume, 1), 0); + $scope.vgUpdateVolume({$volume: newVolume}); + + this.mediaElement[0].volume = newVolume; + this.volume = newVolume; + + //Push volume updates to localStorage so that future instances resume volume + if (VG_UTILS.supportsLocalStorage()) { + //TODO: Improvement: concat key with current page or "video player id" to create separate stored volumes. + $window.localStorage.setItem(VG_VOLUME_KEY, newVolume.toString()); + } + }; + + this.setPlayback = function (newPlayback) { + $scope.vgUpdatePlayback({$playBack: newPlayback}); + + this.mediaElement[0].playbackRate = newPlayback; + this.playback = newPlayback; + }; + + this.updateTheme = function (value) { + var links = document.getElementsByTagName("link"); + var i; + var l; + + // Remove previous theme + if (currentTheme) { + for (i = 0, l = links.length; i < l; i++) { + if (links[i].outerHTML.indexOf(currentTheme) >= 0) { + + links[i].parentNode.removeChild(links[i]); + break; + } + } + } + + if (value) { + var headElem = angular.element(document).find("head"); + var exists = false; + + // Look if theme already exists + for (i = 0, l = links.length; i < l; i++) { + exists = (links[i].outerHTML.indexOf(value) >= 0); + if (exists) break; + } + + if (!exists) { + headElem.append("<link rel='stylesheet' href='" + value + "'>"); + } + + currentTheme = value; + } + }; + + this.onStartBuffering = function (event) { + this.isBuffering = true; + $scope.$apply(); + }; + + this.onStartPlaying = function (event) { + this.isBuffering = false; + $scope.$apply(); + }; + + this.onComplete = function (event) { + $scope.vgComplete(); + + this.setState(VG_STATES.STOP); + this.isCompleted = true; + $scope.$apply(); + }; + + this.onVideoError = function (event) { + $scope.vgError({$event: event}); + }; + + this.addListeners = function () { + this.mediaElement[0].addEventListener("canplay", this.onCanPlay.bind(this), false); + this.mediaElement[0].addEventListener("loadedmetadata", this.onLoadMetaData.bind(this), false); + this.mediaElement[0].addEventListener("waiting", this.onStartBuffering.bind(this), false); + this.mediaElement[0].addEventListener("ended", this.onComplete.bind(this), false); + this.mediaElement[0].addEventListener("playing", this.onStartPlaying.bind(this), false); + this.mediaElement[0].addEventListener("play", this.onPlay.bind(this), false); + this.mediaElement[0].addEventListener("pause", this.onPause.bind(this), false); + this.mediaElement[0].addEventListener("volumechange", this.onVolumeChange.bind(this), false); + this.mediaElement[0].addEventListener("playbackchange", this.onPlaybackChange.bind(this), false); + this.mediaElement[0].addEventListener("timeupdate", this.onUpdateTime.bind(this), false); + this.mediaElement[0].addEventListener("progress", this.onProgress.bind(this), false); + this.mediaElement[0].addEventListener("seeking", this.onSeeking.bind(this), false); + this.mediaElement[0].addEventListener("seeked", this.onSeeked.bind(this), false); + this.mediaElement[0].addEventListener("error", this.onVideoError.bind(this), false); + }; + + this.init = function () { + this.isReady = false; + this.isCompleted = false; + this.buffered = []; + this.bufferEnd = 0; + this.currentTime = 0; + this.totalTime = 0; + this.timeLeft = 0; + this.isLive = false; + this.isFullScreen = false; + this.playback = 1; + this.isConfig = ($scope.vgConfig != undefined); + + if (vgFullscreen.isAvailable) { + this.isFullScreen = vgFullscreen.isFullScreen(); + } + + this.updateTheme($scope.vgTheme); + this.addBindings(); + + if (vgFullscreen.isAvailable) { + document.addEventListener(vgFullscreen.onchange, this.onFullScreenChange.bind(this)); + } + }; + + this.onUpdateTheme = function onUpdateTheme(newValue) { + this.updateTheme(newValue); + }; + + this.onUpdateAutoPlay = function onUpdateAutoPlay(newValue) { + if (newValue && !this.autoPlay) { + this.autoPlay = newValue; + this.play(this); + } + }; + + this.onUpdatePlaysInline = function onUpdatePlaysInline(newValue) { + this.playsInline = newValue; + }; + + this.onUpdateNativeFullscreen = function onUpdateNativeFullscreen(newValue) { + if (newValue == undefined) newValue = true; + + this.nativeFullscreen = newValue; + }; + + this.onUpdateCuePoints = function onUpdateCuePoints(newValue) { + this.cuePoints = newValue; + this.checkCuePoints(this.currentTime); + }; + + this.onUpdateClearMediaOnNavigate = function onUpdateClearMediaOnNavigate(newValue) { + this.clearMediaOnNavigate = newValue; + }; + + this.addBindings = function () { + $scope.$watch("vgTheme", this.onUpdateTheme.bind(this)); + + $scope.$watch("vgAutoPlay", this.onUpdateAutoPlay.bind(this)); + + $scope.$watch("vgPlaysInline", this.onUpdatePlaysInline.bind(this)); + + $scope.$watch("vgNativeFullscreen", this.onUpdateNativeFullscreen.bind(this)); + + $scope.$watch("vgCuePoints", this.onUpdateCuePoints.bind(this)); + + $scope.$watch("vgClearMediaOnNavigate", this.onUpdateClearMediaOnNavigate.bind(this)); + }; + + this.onFullScreenChange = function (event) { + this.isFullScreen = vgFullscreen.isFullScreen(); + $scope.$apply(); + }; + + // Empty mediaElement on destroy to avoid that Chrome downloads video even when it's not present + $scope.$on('$destroy', this.clearMedia.bind(this)); + + // Empty mediaElement when router changes + $scope.$on('$routeChangeStart', this.onRouteChange.bind(this)); + + this.init(); + }] +); + +/** + * @ngdoc directive + * @name com.2fdevs.videogular.directive:vgCrossorigin + * @restrict A + * @description + * Optional directive for `vg-media` to add or remove a crossorigin policy to the video object. Possible values are: "anonymous" and "use-credentials". + * This feature should be enabled if you want to have your subtitles or video files on a different domain than the video player. Additionally you need + * to add CORS policies to your video and track files to your server to make it work. + * + */ +"use strict"; +angular.module("com.2fdevs.videogular") + .directive("vgCrossorigin", + [function () { + return { + restrict: "A", + require: "^videogular", + link: { + pre: function (scope, elem, attr, API) { + var crossorigin; + + scope.setCrossorigin = function setCrossorigin(value) { + if (value) { + API.mediaElement.attr("crossorigin", value); + } + else { + API.mediaElement.removeAttr("crossorigin"); + } + }; + + if (API.isConfig) { + scope.$watch( + function () { + return API.config; + }, + function () { + if (API.config) { + scope.setCrossorigin(API.config.crossorigin); + } + } + ); + } + else { + scope.$watch(attr.vgCrossorigin, function (newValue, oldValue) { + if ((!crossorigin || newValue != oldValue) && newValue) { + crossorigin = newValue; + scope.setCrossorigin(crossorigin); + } + else { + scope.setCrossorigin(); + } + }); + } + } + } + } + } + ]); + +/** + * @ngdoc directive + * @name com.2fdevs.videogular.directive:vgLoop + * @restrict A + * @description + * Optional directive for `vg-media` to add or remove loop in media files. Possible values are: "true" and "false" + * + */ +"use strict"; +angular.module("com.2fdevs.videogular") + .directive("vgLoop", + [function () { + return { + restrict: "A", + require: "^videogular", + link: { + pre: function (scope, elem, attr, API) { + var loop; + + scope.setLoop = function setLoop(value) { + if (value) { + API.mediaElement.attr("loop", value); + } + else { + API.mediaElement.removeAttr("loop"); + } + }; + + if (API.isConfig) { + scope.$watch( + function () { + return API.config; + }, + function () { + if (API.config) { + scope.setLoop(API.config.loop); + } + } + ); + } + else { + scope.$watch(attr.vgLoop, function (newValue, oldValue) { + if ((!loop || newValue != oldValue) && newValue) { + loop = newValue; + scope.setLoop(loop); + } + else { + scope.setLoop(); + } + }); + } + } + } + } + } + ]); + +/** + * @ngdoc directive + * @name com.2fdevs.videogular.direcitve:vgMedia + * @restrict E + * @description + * Directive to add a source of videos or audios. This directive will create a <video> or <audio> tag and usually will be above plugin tags. + * + * @param {array} vgSrc Bindable array with a list of media sources. A media source is an object with two properties `src` and `type`. The `src` property must contains a trustful url resource. + * @param {string} vgType String with "video" or "audio" values to set a <video> or <audio> tag inside <vg-media>. + * <pre> + * { + * src: $sce.trustAsResourceUrl("path/to/video/videogular.mp4"), + * type: "video/mp4" + * } + * </pre> + * + */ +"use strict"; +angular.module("com.2fdevs.videogular") + .directive("vgMedia", + ["$timeout", "VG_UTILS", "VG_STATES", function ($timeout, VG_UTILS, VG_STATES) { + return { + restrict: "E", + require: "^videogular", + templateUrl: function (elem, attrs) { + var vgType = attrs.vgType || "video"; + return attrs.vgTemplate || "vg-templates/vg-media-" + vgType; + }, + scope: { + vgSrc: "=?", + vgType: "=?" + }, + link: function (scope, elem, attrs, API) { + var sources; + + // what type of media do we want? defaults to 'video' + if (!attrs.vgType || attrs.vgType === "video") { + attrs.vgType = "video"; + } + else { + attrs.vgType = "audio"; + } + + // FUNCTIONS + scope.onChangeSource = function onChangeSource(newValue, oldValue) { + if ((!sources || newValue != oldValue) && newValue) { + sources = newValue; + + if (API.currentState !== VG_STATES.PLAY) { + API.currentState = VG_STATES.STOP; + } + + API.sources = sources; + scope.changeSource(); + } + }; + + scope.changeSource = function changeSource() { + var canPlay = ""; + + // It's a cool browser + if (API.mediaElement[0].canPlayType) { + for (var i = 0, l = sources.length; i < l; i++) { + canPlay = API.mediaElement[0].canPlayType(sources[i].type); + + if (canPlay == "maybe" || canPlay == "probably") { + API.mediaElement.attr("src", sources[i].src); + API.mediaElement.attr("type", sources[i].type); + //Trigger vgChangeSource($source) API callback in vgController + API.changeSource(sources[i]); + break; + } + } + } + // It's a crappy browser and it doesn't deserve any respect + else { + // Get H264 or the first one + API.mediaElement.attr("src", sources[0].src); + API.mediaElement.attr("type", sources[0].type); + //Trigger vgChangeSource($source) API callback in vgController + API.changeSource(sources[0]); + } + + // Android 2.3 support: https://github.com/2fdevs/videogular/issues/187 + if (VG_UTILS.isMobileDevice()) API.mediaElement[0].load(); + + $timeout(function () { + if (API.autoPlay && !VG_UTILS.isMobileDevice()) { + API.play(); + } + }); + + if (canPlay == "") { + API.onVideoError(); + } + }; + + // INIT + API.mediaElement = elem.find(attrs.vgType); + API.sources = scope.vgSrc; + + API.addListeners(); + API.onVideoReady(); + + scope.$watch("vgSrc", scope.onChangeSource); + scope.$watch( + function() { + return API.sources; + }, + scope.onChangeSource + ); + + scope.$watch( + function() { + return API.playsInline; + }, + function (newValue, oldValue) { + if (newValue) API.mediaElement.attr("webkit-playsinline", ""); + else API.mediaElement.removeAttr("webkit-playsinline"); + } + ); + + + if (API.isConfig) { + scope.$watch( + function () { + return API.config; + }, + function () { + if (API.config) { + scope.vgSrc = API.config.sources; + } + } + ); + } + } + } + } + ]); + +/** + * @ngdoc directive + * @name com.2fdevs.videogular.directive:vgNativeControls + * @restrict A + * @description + * Optional directive for `vg-media` to add or remove the native controls. Possible values are: "true" and "false" + * + */ +"use strict"; +angular.module("com.2fdevs.videogular") + .directive("vgNativeControls", + [function () { + return { + restrict: "A", + require: "^videogular", + link: { + pre: function (scope, elem, attr, API) { + var controls; + + scope.setControls = function setControls(value) { + if (value) { + API.mediaElement.attr("controls", value); + } + else { + API.mediaElement.removeAttr("controls"); + } + }; + + if (API.isConfig) { + scope.$watch( + function () { + return API.config; + }, + function () { + if (API.config) { + scope.setControls(API.config.controls); + } + } + ); + } + else { + scope.$watch(attr.vgNativeControls, function (newValue, oldValue) { + if ((!controls || newValue != oldValue) && newValue) { + controls = newValue; + scope.setControls(controls); + } + else { + scope.setControls(); + } + }); + } + } + } + } + } + ]); + +/** + * @ngdoc directive + * @name com.2fdevs.videogular.directive:vgPreload + * @restrict A + * @description + * Optional directive for `vg-media` to preload media files. Possible values are: "auto", "none" and "preload" + * + */ +"use strict"; +angular.module("com.2fdevs.videogular") + .directive("vgPreload", + [function () { + return { + restrict: "A", + require: "^videogular", + link: { + pre: function (scope, elem, attr, API) { + var preload; + + scope.setPreload = function setPreload(value) { + if (value) { + API.mediaElement.attr("preload", value); + } + else { + API.mediaElement.removeAttr("preload"); + } + }; + + if (API.isConfig) { + scope.$watch( + function () { + return API.config; + }, + function () { + if (API.config) { + scope.setPreload(API.config.preload); + } + } + ); + } + else { + scope.$watch(attr.vgPreload, function (newValue, oldValue) { + if ((!preload || newValue != oldValue) && newValue) { + preload = newValue; + scope.setPreload(preload); + } + else { + scope.setPreload(); + } + }); + } + } + } + } + } + ]); + +/** + * @ngdoc directive + * @name com.2fdevs.videogular.directive:vgTracks + * @restrict A + * @description + * Optional directive for `vg-media` to add a list of tracks. + * + * vgTracks Bindable array with a list of subtitles sources. A track source is an object with five properties: src, kind, srclang, label and default. + * <pre> + * { + * src: "assets/subs/pale-blue-dot.vtt", + * kind: "subtitles", + * srclang: "en", + * label: "English", + * default: "true/false" + * } + * </pre> + */ +"use strict"; +angular.module("com.2fdevs.videogular") + .directive("vgTracks", + [function () { + return { + restrict: "A", + require: "^videogular", + link: { + pre: function (scope, elem, attr, API) { + var isMetaDataLoaded = false; + var tracks; + var i; + var l; + + scope.onLoadMetaData = function() { + isMetaDataLoaded = true; + scope.updateTracks(); + }; + + scope.updateTracks = function() { + // Remove previous tracks + var oldTracks = API.mediaElement.children(); + + for (i = 0, l = oldTracks.length; i < l; i++) { + if (oldTracks[i].remove) { + oldTracks[i].remove(); + } + } + + // Add new tracks + if (tracks) { + for (i = 0, l = tracks.length; i < l; i++) { + var track = document.createElement('track'); + for (var prop in tracks[i]) { + track[prop] = tracks[i][prop]; + } + + track.addEventListener('load', scope.onLoadTrack.bind(scope, track)); + + API.mediaElement[0].appendChild(track); + } + } + }; + + scope.onLoadTrack = function(track) { + if (track.default) track.mode = 'showing'; + else track.mode = 'hidden'; + + for (var i=0, l=API.mediaElement[0].textTracks.length; i<l; i++) { + if (track.label == API.mediaElement[0].textTracks[i].label) { + if (track.default) { + API.mediaElement[0].textTracks[i].mode = 'showing'; + } + else { + API.mediaElement[0].textTracks[i].mode = 'disabled'; + } + } + + } + + track.removeEventListener('load', scope.onLoadTrack.bind(scope, track)); + }; + + scope.setTracks = function setTracks(value) { + // Add tracks to the API to have it available for other plugins (like controls) + tracks = value; + API.tracks = value; + + if (isMetaDataLoaded) { + scope.updateTracks(); + } + else { + API.mediaElement[0].addEventListener("loadedmetadata", scope.onLoadMetaData.bind(scope), false); + } + }; + + if (API.isConfig) { + scope.$watch( + function () { + return API.config; + }, + function () { + if (API.config) { + scope.setTracks(API.config.tracks); + } + } + ); + } + else { + scope.$watch(attr.vgTracks, function (newValue, oldValue) { + if ((!tracks || newValue != oldValue)) { + scope.setTracks(newValue); + } + }, true); + } + } + } + } + } + ]); + +/** + * @ngdoc directive + * @name com.2fdevs.videogular.directive:videogular + * @restrict E + * @description + * Main directive that must wrap a <vg-media> tag and all plugins. + * + * <video> tag usually will be above plugin tags, that's because plugins should be in a layer over the <video>. + * + * @param {string} vgTheme String with a scope name variable. This directive will inject a CSS link in the header of your page. + * **This parameter is required.** + * + * @param {boolean} [vgPlaysInline=false] vgPlaysInline Boolean value or a String with a scope name variable to use native fullscreen (default) or set fullscreen inside browser (true). + * + * @param {boolean} [vgClearMediaOnNavigate=true] vgClearMediaOnNavigate Boolean value or a String with a scope name variable to reset the video player when user navigates. + * + * This is useful to allow continuous playback between different routes. + * + * @param {boolean} [vgAutoPlay=false] vgAutoPlay Boolean value or a String with a scope name variable to auto start playing video when it is initialized. + * + * **This parameter is disabled in mobile devices** because user must click on content to prevent consuming mobile data plans. + * + * @param {object} vgCuePoints Bindable object containing a list of timelines with cue points objects. A timeline is an array of objects with the following properties: + * - `timeLapse` is an object with two properties `start` and `end` representing in seconds the period for this cue points. + * - `onEnter` callback called when user enters on a cue point. callback(currentTime, timeLapse, params) + * - `onLeave` callback called when user seeks backwards and leave the current cue point or a completed cue point. callback(currentTime, timeLapse, params) + * - `onUpdate` callback called when the current time is between timeLapse.start and timeLapse.end. callback(currentTime, timeLapse, params) + * - `onComplete` callback called when the user seek forward or the current time passes timeLapse.end property. callback(currentTime, timeLapse, params) + * - `params` an object with values available to receive in the callback.. + * + * @param {function} vgConfig String with a url to a config file. Config file's must be a JSON file object with the following structure: + * <pre> + { + "controls": false, + "loop": false, + "autoplay": false, + "preload": "auto", + "theme": "path/to/videogular.css", + "sources": [ + { + "src": "path/to/videogular.mp4", + "type": "video/mp4" + }, + { + "src": "path/to/videogular.webm", + "type": "video/webm" + }, + { + "src": "path/to/videogular.ogg", + "type": "video/ogg" + } + ], + "tracks": [ + { + "src": "path/to/pale-blue-dot.vtt", + "kind": "subtitles", + "srclang": "en", + "label": "English", + "default": "" + } + ], + "plugins": { + "controls": { + "autohide": true, + "autohideTime": 3000 + }, + "poster": { + "url": "path/to/earth.png" + }, + "ima-ads": { + "companion": "companionAd", + "companionSize": [728, 90], + "network": "6062", + "unitPath": "iab_vast_samples", + "adTagUrl": "http://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=%2F3510761%2FadRulesSampleTags&ciu_szs=160x600%2C300x250%2C728x90&cust_params=adrule%3Dpremidpostpodandbumpers&impl=s&gdfp_req=1&env=vp&ad_rule=1&vid=47570401&cmsid=481&output=xml_vast2&unviewed_position_start=1&url=[referrer_url]&correlator=[timestamp]", + "skipButton": "<div class='skipButton'>skip ad</div>" + }, + "analytics": { + "category": "Videogular", + "label": "Main", + "events": { + "ready": true, + "play": true, + "pause": true, + "stop": true, + "complete": true, + "progress": 10 + } + } + } + } + * </pre> + * @param {function} vgCanPlay Function name in controller's scope to call when video is able to begin playback + * @param {function} vgComplete Function name in controller's scope to call when video have been completed. + * @param {function} vgUpdateVolume Function name in controller's scope to call when volume changes. Receives a param with the new volume. + * @param {function} vgUpdatePlayback Function name in controller's scope to call when playback changes. Receives a param with the new playback rate. + * @param {function} vgUpdateTime Function name in controller's scope to call when video playback time is updated. Receives two params with current time and duration in milliseconds. + * @param {function} vgUpdateState Function name in controller's scope to call when video state changes. Receives a param with the new state. Possible values are "play", "stop" or "pause". + * @param {function} vgPlayerReady Function name in controller's scope to call when video have been initialized. Receives a param with the videogular API. + * @param {function} vgChangeSource Function name in controller's scope to change current video source. Receives a param with the new video. + * @param {function} vgPlaysInline Boolean to play video inline. Generally used in mobile devices. + * @param {function} vgNativeFullscreen Boolean to disable native fullscreen. + * @param {function} vgSeeking Function name in controller's scope to call when the video has finished jumping to a new time. Receives a param with the seeked time and duration in seconds. + * @param {function} vgSeeked Function name in controller's scope to call when the video is jumping to a new time. Receives two params with the seeked time and duration in seconds. + * @param {function} vgError Function name in controller's scope to receive an error from video object. Receives a param with the error event. + * This is a free parameter and it could be values like "new.mp4", "320" or "sd". This will allow you to use this to change a video or video quality. + * This callback will not change the video, you should do that by updating your sources scope variable. + * + */ +"use strict"; +angular.module("com.2fdevs.videogular") + .directive("videogular", + [function () { + return { + restrict: "EA", + scope: { + vgTheme: "=?", + vgAutoPlay: "=?", + vgPlaysInline: "=?", + vgNativeFullscreen: "=?", + vgClearMediaOnNavigate: "=?", + vgCuePoints: "=?", + vgConfig: "@", + vgCanPlay: "&", + vgComplete: "&", + vgUpdateVolume: "&", + vgUpdatePlayback: "&", + vgUpdateTime: "&", + vgUpdateState: "&", + vgPlayerReady: "&", + vgChangeSource: "&", + vgSeeking: "&", + vgSeeked: "&", + vgError: "&" + }, + controller: "vgController", + controllerAs: "API", + link: { + pre: function (scope, elem, attr, controller) { + controller.videogularElement = angular.element(elem); + } + } + } + } + ]); + +/** + * @ngdoc service + * @name com.2fdevs.videogular.service:vgConfigLoader + * + * @description + * Config loader service: + * + * vgConfigLoader.loadConfig(url): Param `url` is a url to a config JSON. + **/ +"use strict"; +angular.module("com.2fdevs.videogular") + .service("vgConfigLoader", ["$http", "$q", "$sce", function ($http, $q, $sce) { + this.loadConfig = function loadConfig(url) { + var deferred = $q.defer(); + + $http({method: 'GET', url: url}).then( + function success(response) { + var result = response.data; + + for (var i = 0, l = result.sources.length; i < l; i++) { + result.sources[i].src = $sce.trustAsResourceUrl(result.sources[i].src); + } + + deferred.resolve(result); + }, + function reject() { + deferred.reject(); + } + ); + + return deferred.promise; + }; + }]); + +/** + * @ngdoc service + * @name com.2fdevs.videogular.service:vgFullscreen + * + * @description + * Native fullscreen polyfill service. + * + * * vgFullscreen.onchange: String with the onchange event name. + * * vgFullscreen.onerror: String with the onerror event name. + * * vgFullscreen.isAvailable: Boolean with fullscreen availability. + * * vgFullscreen.isFullScreen: Boolean with current view mode. + * * vgFullscreen.exit: Exit fullscreen function. + * * vgFullscreen.request: Request for fullscreen access function. + **/ +"use strict"; +angular.module("com.2fdevs.videogular") + .service("vgFullscreen", ["VG_UTILS", function (VG_UTILS) { + // Native fullscreen polyfill + var element; + var polyfill = null; + var APIs = { + w3: { + enabled: "fullscreenEnabled", + element: "fullscreenElement", + request: "requestFullscreen", + exit: "exitFullscreen", + onchange: "fullscreenchange", + onerror: "fullscreenerror" + }, + newWebkit: { + enabled: "webkitFullscreenEnabled", + element: "webkitFullscreenElement", + request: "webkitRequestFullscreen", + exit: "webkitExitFullscreen", + onchange: "webkitfullscreenchange", + onerror: "webkitfullscreenerror" + }, + oldWebkit: { + enabled: "webkitIsFullScreen", + element: "webkitCurrentFullScreenElement", + request: "webkitRequestFullScreen", + exit: "webkitCancelFullScreen", + onchange: "webkitfullscreenchange", + onerror: "webkitfullscreenerror" + }, + moz: { + enabled: "mozFullScreen", + element: "mozFullScreenElement", + request: "mozRequestFullScreen", + exit: "mozCancelFullScreen", + onchange: "mozfullscreenchange", + onerror: "mozfullscreenerror" + }, + ios: { + enabled: "webkitFullscreenEnabled", + element: "webkitFullscreenElement", + request: "webkitEnterFullscreen", + exit: "webkitExitFullscreen", + onchange: "webkitfullscreenchange", + onerror: "webkitfullscreenerror" + }, + ms: { + enabled: "msFullscreenEnabled", + element: "msFullscreenElement", + request: "msRequestFullscreen", + exit: "msExitFullscreen", + onchange: "MSFullscreenChange", + onerror: "MSFullscreenError" + } + }; + + for (var browser in APIs) { + if (APIs[browser].enabled in document) { + polyfill = APIs[browser]; + break; + } + } + + // Override APIs on iOS + if (VG_UTILS.isiOSDevice()) { + polyfill = APIs.ios; + } + + function isFullScreen() { + var result = false; + + if (element) { + result = (document[polyfill.element] != null || element.webkitDisplayingFullscreen) + } + else { + result = (document[polyfill.element] != null) + } + + return result; + } + + this.isAvailable = (polyfill != null); + + if (polyfill) { + this.onchange = polyfill.onchange; + this.onerror = polyfill.onerror; + this.isFullScreen = isFullScreen; + this.exit = function () { + document[polyfill.exit](); + }; + this.request = function (elem) { + element = elem; + element[polyfill.request](); + }; + } + }]); + +"use strict"; +angular.module("com.2fdevs.videogular") + .service("VG_UTILS", ["$window", function ($window) { + this.fixEventOffset = function ($event) { + /** + * There's no offsetX in Firefox, so we fix that. + * Solution provided by Jack Moore in this post: + * http://www.jacklmoore.com/notes/mouse-position/ + * @param $event + * @returns {*} + */ + var matchedFF = navigator.userAgent.match(/Firefox\/(\d+)/i) + if (matchedFF && Number.parseInt(matchedFF.pop()) < 39) { + var style = $event.currentTarget.currentStyle || window.getComputedStyle($event.target, null); + var borderLeftWidth = parseInt(style['borderLeftWidth'], 10); + var borderTopWidth = parseInt(style['borderTopWidth'], 10); + var rect = $event.currentTarget.getBoundingClientRect(); + var offsetX = $event.clientX - borderLeftWidth - rect.left; + var offsetY = $event.clientY - borderTopWidth - rect.top; + + $event.offsetX = offsetX; + $event.offsetY = offsetY; + } + + return $event; + }; + + /** + * Inspired by Paul Irish + * https://gist.github.com/paulirish/211209 + * @returns {number} + */ + this.getZIndex = function () { + var zIndex = 1; + var elementZIndex; + + var tags = document.getElementsByTagName('*'); + + for (var i = 0, l = tags.length; i < l; i++) { + elementZIndex = parseInt(window.getComputedStyle(tags[i])["z-index"]); + + if (elementZIndex > zIndex) { + zIndex = elementZIndex + 1; + } + } + + return zIndex; + }; + + // Very simple mobile detection, not 100% reliable + this.isMobileDevice = function () { + return (typeof window.orientation !== "undefined") || (navigator.userAgent.indexOf("IEMobile") !== -1); + }; + + this.isiOSDevice = function () { + return (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/iPad/i)); + }; + + /** + * Test the browser's support for HTML5 localStorage. + * @returns {boolean} + */ + this.supportsLocalStorage = function () { + var testKey = 'videogular-test-key'; + var storage = $window.sessionStorage; + + try { + storage.setItem(testKey, '1'); + storage.removeItem(testKey); + return 'localStorage' in $window && $window['localStorage'] !== null; + } catch (e) { + return false; + } + }; + }]); diff --git a/www/lib/videogular/videogular.min.js b/www/lib/videogular/videogular.min.js new file mode 100644 index 00000000..977e6c0b --- /dev/null +++ b/www/lib/videogular/videogular.min.js @@ -0,0 +1 @@ +"use strict";angular.module("com.2fdevs.videogular",["ngSanitize"]).run(["$templateCache",function(a){a.put("vg-templates/vg-media-video","<video></video>"),a.put("vg-templates/vg-media-audio","<audio></audio>"),Function.prototype.bind||(Function.prototype.bind=function(a){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var b=Array.prototype.slice.call(arguments,1),c=this,d=function(){},e=function(){return c.apply(this instanceof d?this:a,b.concat(Array.prototype.slice.call(arguments)))};return d.prototype=this.prototype,e.prototype=new d,e})}]),angular.module("com.2fdevs.videogular").constant("VG_STATES",{PLAY:"play",PAUSE:"pause",STOP:"stop"}).constant("VG_VOLUME_KEY","videogularVolume"),angular.module("com.2fdevs.videogular").controller("vgController",["$scope","$window","vgConfigLoader","vgFullscreen","VG_UTILS","VG_STATES","VG_VOLUME_KEY",function(a,b,c,d,e,f,g){var h=null,i=!1,j=!1;this.videogularElement=null,this.clearMedia=function(){this.mediaElement[0].src=""},this.onRouteChange=function(){(void 0===this.clearMediaOnNavigate||this.clearMediaOnNavigate===!0)&&this.clearMedia()},this.onCanPlay=function(b){this.isBuffering=!1,a.$apply(a.vgCanPlay({$event:b}))},this.onVideoReady=function(){this.isReady=!0,this.autoPlay=a.vgAutoPlay,this.playsInline=a.vgPlaysInline,this.nativeFullscreen=a.vgNativeFullscreen||!0,this.cuePoints=a.vgCuePoints,this.clearMediaOnNavigate=a.vgClearMediaOnNavigate||!0,this.currentState=f.STOP,j=!0,e.supportsLocalStorage()&&this.setVolume(parseFloat(b.localStorage.getItem(g)||"1")),a.vgConfig?c.loadConfig(a.vgConfig).then(this.onLoadConfig.bind(this)):a.vgPlayerReady({$API:this})},this.onLoadConfig=function(b){this.config=b,a.vgTheme=this.config.theme,a.vgAutoPlay=this.config.autoPlay,a.vgPlaysInline=this.config.playsInline,a.vgNativeFullscreen=this.config.nativeFullscreen,a.vgCuePoints=this.config.cuePoints,a.vgClearMediaOnNavigate=this.config.clearMediaOnNavigate,a.vgPlayerReady({$API:this})},this.onLoadMetaData=function(a){this.isBuffering=!1,this.onUpdateTime(a)},this.onProgress=function(b){b.target.buffered.length&&(this.buffered=b.target.buffered,this.bufferEnd=1e3*b.target.buffered.end(b.target.buffered.length-1)),a.$apply()},this.onUpdateTime=function(b){this.currentTime=1e3*b.target.currentTime,b.target.buffered.length&&(this.buffered=b.target.buffered,this.bufferEnd=1e3*b.target.buffered.end(b.target.buffered.length-1)),b.target.duration!=1/0?(this.totalTime=1e3*b.target.duration,this.timeLeft=1e3*(b.target.duration-b.target.currentTime),this.isLive=!1):this.isLive=!0,this.cuePoints&&this.checkCuePoints(b.target.currentTime),a.vgUpdateTime({$currentTime:b.target.currentTime,$duration:b.target.duration}),a.$apply()},this.checkCuePoints=function(a){for(var b in this.cuePoints)for(var c=0,d=this.cuePoints[b].length;d>c;c++){var e=this.cuePoints[b][c],f=parseInt(a,10),g=parseInt(e.timeLapse.start,10);e.timeLapse.end||(e.timeLapse.end=e.timeLapse.start+1),a<e.timeLapse.end&&(e.$$isCompleted=!1),e.$$isDirty||f!==g||"function"!=typeof e.onEnter||(e.onEnter(a,e.timeLapse,e.params),e.$$isDirty=!0),a>e.timeLapse.start?(a<e.timeLapse.end&&(e.onUpdate&&e.onUpdate(a,e.timeLapse,e.params),e.$$isDirty||"function"!=typeof e.onEnter||e.onEnter(a,e.timeLapse,e.params)),a>=e.timeLapse.end&&e.onComplete&&!e.$$isCompleted&&(e.$$isCompleted=!0,e.onComplete(a,e.timeLapse,e.params)),e.$$isDirty=!0):(e.onLeave&&e.$$isDirty&&e.onLeave(a,e.timeLapse,e.params),e.$$isDirty=!1)}},this.onPlay=function(){this.setState(f.PLAY),a.$apply()},this.onPause=function(){0==this.mediaElement[0].currentTime?this.setState(f.STOP):this.setState(f.PAUSE),a.$apply()},this.onVolumeChange=function(){this.volume=this.mediaElement[0].volume,a.$apply()},this.onPlaybackChange=function(){this.playback=this.mediaElement[0].playbackRate,a.$apply()},this.onSeeking=function(b){a.vgSeeking({$currentTime:b.target.currentTime,$duration:b.target.duration})},this.onSeeked=function(b){a.vgSeeked({$currentTime:b.target.currentTime,$duration:b.target.duration})},this.seekTime=function(a,b){var c;b?(c=a*this.mediaElement[0].duration/100,this.mediaElement[0].currentTime=c):(c=a,this.mediaElement[0].currentTime=c),this.currentTime=1e3*c},this.playPause=function(){this.mediaElement[0].paused?this.play():this.pause()},this.setState=function(b){return b&&b!=this.currentState&&(a.vgUpdateState({$state:b}),this.currentState=b),this.currentState},this.play=function(){this.mediaElement[0].play(),this.setState(f.PLAY)},this.pause=function(){this.mediaElement[0].pause(),this.setState(f.PAUSE)},this.stop=function(){try{this.mediaElement[0].pause(),this.mediaElement[0].currentTime=0,this.currentTime=0,this.buffered=[],this.bufferEnd=0,this.setState(f.STOP)}catch(a){return a}},this.toggleFullScreen=function(){d.isAvailable&&this.nativeFullscreen?this.isFullScreen?e.isMobileDevice()||d.exit():e.isMobileDevice()?e.isiOSDevice()?j?this.enterElementInFullScreen(this.mediaElement[0]):(i=!0,this.play()):this.enterElementInFullScreen(this.mediaElement[0]):this.enterElementInFullScreen(this.videogularElement[0]):(this.isFullScreen?(this.videogularElement.removeClass("fullscreen"),this.videogularElement.css("z-index","auto")):(this.videogularElement.addClass("fullscreen"),this.videogularElement.css("z-index",e.getZIndex())),this.isFullScreen=!this.isFullScreen)},this.enterElementInFullScreen=function(a){d.request(a)},this.changeSource=function(b){a.vgChangeSource({$source:b})},this.setVolume=function(c){c=Math.max(Math.min(c,1),0),a.vgUpdateVolume({$volume:c}),this.mediaElement[0].volume=c,this.volume=c,e.supportsLocalStorage()&&b.localStorage.setItem(g,c.toString())},this.setPlayback=function(b){a.vgUpdatePlayback({$playBack:b}),this.mediaElement[0].playbackRate=b,this.playback=b},this.updateTheme=function(a){var b,c,d=document.getElementsByTagName("link");if(h)for(b=0,c=d.length;c>b;b++)if(d[b].outerHTML.indexOf(h)>=0){d[b].parentNode.removeChild(d[b]);break}if(a){var e=angular.element(document).find("head"),f=!1;for(b=0,c=d.length;c>b&&!(f=d[b].outerHTML.indexOf(a)>=0);b++);f||e.append("<link rel='stylesheet' href='"+a+"'>"),h=a}},this.onStartBuffering=function(b){this.isBuffering=!0,a.$apply()},this.onStartPlaying=function(b){this.isBuffering=!1,a.$apply()},this.onComplete=function(b){a.vgComplete(),this.setState(f.STOP),this.isCompleted=!0,a.$apply()},this.onVideoError=function(b){a.vgError({$event:b})},this.addListeners=function(){this.mediaElement[0].addEventListener("canplay",this.onCanPlay.bind(this),!1),this.mediaElement[0].addEventListener("loadedmetadata",this.onLoadMetaData.bind(this),!1),this.mediaElement[0].addEventListener("waiting",this.onStartBuffering.bind(this),!1),this.mediaElement[0].addEventListener("ended",this.onComplete.bind(this),!1),this.mediaElement[0].addEventListener("playing",this.onStartPlaying.bind(this),!1),this.mediaElement[0].addEventListener("play",this.onPlay.bind(this),!1),this.mediaElement[0].addEventListener("pause",this.onPause.bind(this),!1),this.mediaElement[0].addEventListener("volumechange",this.onVolumeChange.bind(this),!1),this.mediaElement[0].addEventListener("playbackchange",this.onPlaybackChange.bind(this),!1),this.mediaElement[0].addEventListener("timeupdate",this.onUpdateTime.bind(this),!1),this.mediaElement[0].addEventListener("progress",this.onProgress.bind(this),!1),this.mediaElement[0].addEventListener("seeking",this.onSeeking.bind(this),!1),this.mediaElement[0].addEventListener("seeked",this.onSeeked.bind(this),!1),this.mediaElement[0].addEventListener("error",this.onVideoError.bind(this),!1)},this.init=function(){this.isReady=!1,this.isCompleted=!1,this.buffered=[],this.bufferEnd=0,this.currentTime=0,this.totalTime=0,this.timeLeft=0,this.isLive=!1,this.isFullScreen=!1,this.playback=1,this.isConfig=void 0!=a.vgConfig,d.isAvailable&&(this.isFullScreen=d.isFullScreen()),this.updateTheme(a.vgTheme),this.addBindings(),d.isAvailable&&document.addEventListener(d.onchange,this.onFullScreenChange.bind(this))},this.onUpdateTheme=function(a){this.updateTheme(a)},this.onUpdateAutoPlay=function(a){a&&!this.autoPlay&&(this.autoPlay=a,this.play(this))},this.onUpdatePlaysInline=function(a){this.playsInline=a},this.onUpdateNativeFullscreen=function(a){void 0==a&&(a=!0),this.nativeFullscreen=a},this.onUpdateCuePoints=function(a){this.cuePoints=a,this.checkCuePoints(this.currentTime)},this.onUpdateClearMediaOnNavigate=function(a){this.clearMediaOnNavigate=a},this.addBindings=function(){a.$watch("vgTheme",this.onUpdateTheme.bind(this)),a.$watch("vgAutoPlay",this.onUpdateAutoPlay.bind(this)),a.$watch("vgPlaysInline",this.onUpdatePlaysInline.bind(this)),a.$watch("vgNativeFullscreen",this.onUpdateNativeFullscreen.bind(this)),a.$watch("vgCuePoints",this.onUpdateCuePoints.bind(this)),a.$watch("vgClearMediaOnNavigate",this.onUpdateClearMediaOnNavigate.bind(this))},this.onFullScreenChange=function(b){this.isFullScreen=d.isFullScreen(),a.$apply()},a.$on("$destroy",this.clearMedia.bind(this)),a.$on("$routeChangeStart",this.onRouteChange.bind(this)),this.init()}]),angular.module("com.2fdevs.videogular").directive("vgCrossorigin",[function(){return{restrict:"A",require:"^videogular",link:{pre:function(a,b,c,d){var e;a.setCrossorigin=function(a){a?d.mediaElement.attr("crossorigin",a):d.mediaElement.removeAttr("crossorigin")},d.isConfig?a.$watch(function(){return d.config},function(){d.config&&a.setCrossorigin(d.config.crossorigin)}):a.$watch(c.vgCrossorigin,function(b,c){e&&b==c||!b?a.setCrossorigin():(e=b,a.setCrossorigin(e))})}}}}]),angular.module("com.2fdevs.videogular").directive("vgLoop",[function(){return{restrict:"A",require:"^videogular",link:{pre:function(a,b,c,d){var e;a.setLoop=function(a){a?d.mediaElement.attr("loop",a):d.mediaElement.removeAttr("loop")},d.isConfig?a.$watch(function(){return d.config},function(){d.config&&a.setLoop(d.config.loop)}):a.$watch(c.vgLoop,function(b,c){e&&b==c||!b?a.setLoop():(e=b,a.setLoop(e))})}}}}]),angular.module("com.2fdevs.videogular").directive("vgMedia",["$timeout","VG_UTILS","VG_STATES",function(a,b,c){return{restrict:"E",require:"^videogular",templateUrl:function(a,b){var c=b.vgType||"video";return b.vgTemplate||"vg-templates/vg-media-"+c},scope:{vgSrc:"=?",vgType:"=?"},link:function(d,e,f,g){var h;f.vgType&&"video"!==f.vgType?f.vgType="audio":f.vgType="video",d.onChangeSource=function(a,b){h&&a==b||!a||(h=a,g.currentState!==c.PLAY&&(g.currentState=c.STOP),g.sources=h,d.changeSource())},d.changeSource=function(){var c="";if(g.mediaElement[0].canPlayType){for(var d=0,e=h.length;e>d;d++)if(c=g.mediaElement[0].canPlayType(h[d].type),"maybe"==c||"probably"==c){g.mediaElement.attr("src",h[d].src),g.mediaElement.attr("type",h[d].type),g.changeSource(h[d]);break}}else g.mediaElement.attr("src",h[0].src),g.mediaElement.attr("type",h[0].type),g.changeSource(h[0]);b.isMobileDevice()&&g.mediaElement[0].load(),a(function(){g.autoPlay&&!b.isMobileDevice()&&g.play()}),""==c&&g.onVideoError()},g.mediaElement=e.find(f.vgType),g.sources=d.vgSrc,g.addListeners(),g.onVideoReady(),d.$watch("vgSrc",d.onChangeSource),d.$watch(function(){return g.sources},d.onChangeSource),d.$watch(function(){return g.playsInline},function(a,b){a?g.mediaElement.attr("webkit-playsinline",""):g.mediaElement.removeAttr("webkit-playsinline")}),g.isConfig&&d.$watch(function(){return g.config},function(){g.config&&(d.vgSrc=g.config.sources)})}}}]),angular.module("com.2fdevs.videogular").directive("vgNativeControls",[function(){return{restrict:"A",require:"^videogular",link:{pre:function(a,b,c,d){var e;a.setControls=function(a){a?d.mediaElement.attr("controls",a):d.mediaElement.removeAttr("controls")},d.isConfig?a.$watch(function(){return d.config},function(){d.config&&a.setControls(d.config.controls)}):a.$watch(c.vgNativeControls,function(b,c){e&&b==c||!b?a.setControls():(e=b,a.setControls(e))})}}}}]),angular.module("com.2fdevs.videogular").directive("vgPreload",[function(){return{restrict:"A",require:"^videogular",link:{pre:function(a,b,c,d){var e;a.setPreload=function(a){a?d.mediaElement.attr("preload",a):d.mediaElement.removeAttr("preload")},d.isConfig?a.$watch(function(){return d.config},function(){d.config&&a.setPreload(d.config.preload)}):a.$watch(c.vgPreload,function(b,c){e&&b==c||!b?a.setPreload():(e=b,a.setPreload(e))})}}}}]),angular.module("com.2fdevs.videogular").directive("vgTracks",[function(){return{restrict:"A",require:"^videogular",link:{pre:function(a,b,c,d){var e,f,g,h=!1;a.onLoadMetaData=function(){h=!0,a.updateTracks()},a.updateTracks=function(){var b=d.mediaElement.children();for(f=0,g=b.length;g>f;f++)b[f].remove&&b[f].remove();if(e)for(f=0,g=e.length;g>f;f++){var c=document.createElement("track");for(var h in e[f])c[h]=e[f][h];c.addEventListener("load",a.onLoadTrack.bind(a,c)),d.mediaElement[0].appendChild(c)}},a.onLoadTrack=function(b){b["default"]?b.mode="showing":b.mode="hidden";for(var c=0,e=d.mediaElement[0].textTracks.length;e>c;c++)b.label==d.mediaElement[0].textTracks[c].label&&(b["default"]?d.mediaElement[0].textTracks[c].mode="showing":d.mediaElement[0].textTracks[c].mode="disabled");b.removeEventListener("load",a.onLoadTrack.bind(a,b))},a.setTracks=function(b){e=b,d.tracks=b,h?a.updateTracks():d.mediaElement[0].addEventListener("loadedmetadata",a.onLoadMetaData.bind(a),!1)},d.isConfig?a.$watch(function(){return d.config},function(){d.config&&a.setTracks(d.config.tracks)}):a.$watch(c.vgTracks,function(b,c){e&&b==c||a.setTracks(b)},!0)}}}}]),angular.module("com.2fdevs.videogular").directive("videogular",[function(){return{restrict:"EA",scope:{vgTheme:"=?",vgAutoPlay:"=?",vgPlaysInline:"=?",vgNativeFullscreen:"=?",vgClearMediaOnNavigate:"=?",vgCuePoints:"=?",vgConfig:"@",vgCanPlay:"&",vgComplete:"&",vgUpdateVolume:"&",vgUpdatePlayback:"&",vgUpdateTime:"&",vgUpdateState:"&",vgPlayerReady:"&",vgChangeSource:"&",vgSeeking:"&",vgSeeked:"&",vgError:"&"},controller:"vgController",controllerAs:"API",link:{pre:function(a,b,c,d){d.videogularElement=angular.element(b)}}}}]),angular.module("com.2fdevs.videogular").service("vgConfigLoader",["$http","$q","$sce",function(a,b,c){this.loadConfig=function(d){var e=b.defer();return a({method:"GET",url:d}).then(function(a){for(var b=a.data,d=0,f=b.sources.length;f>d;d++)b.sources[d].src=c.trustAsResourceUrl(b.sources[d].src);e.resolve(b)},function(){e.reject()}),e.promise}}]),angular.module("com.2fdevs.videogular").service("vgFullscreen",["VG_UTILS",function(a){function b(){var a=!1;return a=c?null!=document[d.element]||c.webkitDisplayingFullscreen:null!=document[d.element]}var c,d=null,e={w3:{enabled:"fullscreenEnabled",element:"fullscreenElement",request:"requestFullscreen",exit:"exitFullscreen",onchange:"fullscreenchange",onerror:"fullscreenerror"},newWebkit:{enabled:"webkitFullscreenEnabled",element:"webkitFullscreenElement",request:"webkitRequestFullscreen",exit:"webkitExitFullscreen",onchange:"webkitfullscreenchange",onerror:"webkitfullscreenerror"},oldWebkit:{enabled:"webkitIsFullScreen",element:"webkitCurrentFullScreenElement",request:"webkitRequestFullScreen",exit:"webkitCancelFullScreen",onchange:"webkitfullscreenchange",onerror:"webkitfullscreenerror"},moz:{enabled:"mozFullScreen",element:"mozFullScreenElement",request:"mozRequestFullScreen",exit:"mozCancelFullScreen",onchange:"mozfullscreenchange",onerror:"mozfullscreenerror"},ios:{enabled:"webkitFullscreenEnabled",element:"webkitFullscreenElement",request:"webkitEnterFullscreen",exit:"webkitExitFullscreen",onchange:"webkitfullscreenchange",onerror:"webkitfullscreenerror"},ms:{enabled:"msFullscreenEnabled",element:"msFullscreenElement",request:"msRequestFullscreen",exit:"msExitFullscreen",onchange:"MSFullscreenChange",onerror:"MSFullscreenError"}};for(var f in e)if(e[f].enabled in document){d=e[f];break}a.isiOSDevice()&&(d=e.ios),this.isAvailable=null!=d,d&&(this.onchange=d.onchange,this.onerror=d.onerror,this.isFullScreen=b,this.exit=function(){document[d.exit]()},this.request=function(a){c=a,c[d.request]()})}]),angular.module("com.2fdevs.videogular").service("VG_UTILS",["$window",function(a){this.fixEventOffset=function(a){var b=navigator.userAgent.match(/Firefox\/(\d+)/i);if(b&&Number.parseInt(b.pop())<39){var c=a.currentTarget.currentStyle||window.getComputedStyle(a.target,null),d=parseInt(c.borderLeftWidth,10),e=parseInt(c.borderTopWidth,10),f=a.currentTarget.getBoundingClientRect(),g=a.clientX-d-f.left,h=a.clientY-e-f.top;a.offsetX=g,a.offsetY=h}return a},this.getZIndex=function(){for(var a,b=1,c=document.getElementsByTagName("*"),d=0,e=c.length;e>d;d++)a=parseInt(window.getComputedStyle(c[d])["z-index"]),a>b&&(b=a+1);return b},this.isMobileDevice=function(){return"undefined"!=typeof window.orientation||-1!==navigator.userAgent.indexOf("IEMobile")},this.isiOSDevice=function(){return navigator.userAgent.match(/iPhone/i)||navigator.userAgent.match(/iPod/i)||navigator.userAgent.match(/iPad/i)},this.supportsLocalStorage=function(){var b="videogular-test-key",c=a.sessionStorage;try{return c.setItem(b,"1"),c.removeItem(b),"localStorage"in a&&null!==a.localStorage}catch(d){return!1}}}]);
\ No newline at end of file diff --git a/www/templates/events.html b/www/templates/events.html index 2d55b1f0..5f1bafd0 100644 --- a/www/templates/events.html +++ b/www/templates/events.html @@ -1,26 +1,23 @@ -<ion-view cache-view="false"> +<ion-view cache-view="false"> <ion-nav-title>{{scrollPosition();}}</ion-nav-title> <ion-nav-buttons side="left"> - <button class="button button-icon button-clear ion-navicon" - ng-click="openMenu()"> + <button class="button button-icon button-clear ion-navicon" ng-click="openMenu()"> </button> - - <button class="button button-icon icon ion-ios-minus-outline" - ng-click="eventList.showDelete = !eventList.showDelete;"></button> - - <button data-badge="{{$root.alarmCount}}" class="animated infinite tada button button-icon button-clear ion-ios-bell notification-badge" ng-click="handleAlarms();" ng-if="$root.isAlarm"></button> - + + <button class="button button-icon icon ion-ios-minus-outline" ng-click="eventList.showDelete = !eventList.showDelete;"></button> + + <button data-badge="{{$root.alarmCount}}" class="animated infinite tada button button-icon button-clear ion-ios-bell notification-badge" ng-click="handleAlarms();" ng-if="$root.isAlarm"></button> + </ion-nav-buttons> <ion-nav-buttons side="right"> - <a style="" class="button button-icon icon ion-android-more-vertical" ng-click="popover.show($event)";> </a> + <a style="" class="button button-icon icon ion-android-more-vertical" ng-click="popover.show($event)" ;> </a> <!-- <a style="" class="button button-icon icon ion-stats-bars" ng-href="#events-graphs"> </a> <a style="" class="button button-icon icon ion-refresh" ng-href="" ng-click="doRefresh();"> </a>--> - <a style="" class="button button-icon icon ion-search" ng-href="" - ng-click="searchClicked();"> </a> + <a style="" class="button button-icon icon ion-search" ng-href="" ng-click="searchClicked();"> </a> </ion-nav-buttons> @@ -31,8 +28,7 @@ <label class="item-input-wrapper"> <i class="icon ion-ios7-search placeholder-icon"></i> - <input type="search" placeholder="Search" - ng-model="search.text" autocorrect="off" autocomplete="off"> + <input type="search" placeholder="Search" ng-model="search.text" autocorrect="off" autocomplete="off"> </label> </ion-header-bar> </div> @@ -45,69 +41,76 @@ </ion-refresher>--> <!-- lets make sure the events list is not empty as collection repeat needs height --> - <div ng-if = "!eventsBeingLoaded"> - <ion-list show-delete="eventList.showDelete" > - <ion-item collection-repeat="event in events| filter:search.text" - item-height="event.Event.height" id="item-{{$index}}" > - <div > - <!--<span class="events-filter-on" ng-if="isEventFilterOn">Filter</span>--> + <div ng-if="!eventsBeingLoaded"> + <ion-list show-delete="eventList.showDelete"> + <ion-item collection-repeat="event in events| filter:search.text" item-height="event.Event.height" id="item-{{$index}}"> + <div> + <!--<span class="events-filter-on" ng-if="isEventFilterOn">Filter</span>--> - <span style="float:right;margin-top:-18px;background-color:#6d0909;color:#fff;font-size:11px;opacity:0.7;width:90px;border-radius: 0px 0px 5px 5px;"> <i class="ion-clock"></i> {{prettifyTime(event.Event.StartTime)}}</span> + <span style="float:right;margin-top:-18px;background-color:#6d0909;color:#fff;font-size:11px;opacity:0.7;width:90px;border-radius: 0px 0px 5px 5px;"> <i class="ion-clock"></i> {{prettifyTime(event.Event.StartTime)}}</span> - <span style="float:left;margin-top:-18px;background-color:#444444;color:#fff;font-size:11px;opacity:0.7;width:90px;border-radius: 0px 0px 5px 5px;"> <i class="ion-calendar"></i> {{prettifyDate(event.Event.StartTime)}}</span> + <span style="float:left;margin-top:-18px;background-color:#444444;color:#fff;font-size:11px;opacity:0.7;width:90px;border-radius: 0px 0px 5px 5px;"> <i class="ion-calendar"></i> {{prettifyDate(event.Event.StartTime)}}</span> - <div class="row"> - <div class="col col-left"> - <!-- this ngswitch displays different icons + <div class="row"> + <div class="col col-left"> + <!-- this ngswitch displays different icons depending on the cause of the event --> - <div ng-switch on="event.Event.Cause"> - <div ng-switch-when="Motion"> - - <i class="ion-android-walk" style="float:left; font-size:200%;"></i> - - <br/> - </div> - <div ng-switch-when="Signal"> - <i class="ion-wifi" style="float:left; font-size:200%;"></i> - <br/> + <div ng-switch on="event.Event.Cause"> + <div ng-switch-when="Motion"> + + <i class="ion-android-walk" style="float:left; font-size:200%;"></i> + <div ng-if="event.Event.DefaultVideo!=''"> + <i class="ion-ios-videocam" style="float:left; padding-left:5px; font-size:200%;"></i> + </div> + <br/> + </div> + <div ng-switch-when="Signal"> + <i class="ion-wifi" style="float:left; font-size:200%;"></i> + <div ng-if="event.Event.DefaultVideo!=''"> + <i class="ion-ios-videocam" style="float:left; padding-left:5px;font-size:200%;"></i> + </div> + <br/> + </div> + <div ng-switch-default> + <i class="ion-ionic" style="float:left; font-size:200%;"></i> + <div ng-if="event.Event.DefaultVideo!=''"> + <i class="ion-ios-videocam" style="float:left; padding-left:5px;font-size:200%;"></i> + </div> + <br/> + </div> </div> - <div ng-switch-default> - <i class="ion-ionic" style="float:left; font-size:200%;"></i> - <br/> - </div> - </div> - <!-- ng switch --> - <!-- {{event.Event.Cause}} --> + <!-- ng switch --> + <!-- {{event.Event.Cause}} --> - <br/> - <span style="font-size:80%; color:rgb(110,110,110)"> + <br/> + <span style="font-size:80%; color:rgb(110,110,110)"> {{event.Event.Length}}s </span> - </div> - <!-- col col left--> - <div class="col col-80"> - <div class="item-text-wrap"> - <i class="ion-monitor"></i> - <b>{{event.Event.MonitorName}}</b> ({{event.Event.Name}}) </div> + <!-- col col left--> + <div class="col col-80"> + <div class="item-text-wrap"> + <i class="ion-monitor"></i> + <b>{{event.Event.MonitorName}}</b> ({{event.Event.Name}}) + </div> - <i class="ion-images"></i> {{event.Event.Frames}} - <i class="ion-ios-bell-outline"></i> {{event.Event.AlarmFrames}} - <i class="ion-arrow-graph-up-right"></i> {{event.Event.TotScore}} + <i class="ion-images"></i> {{event.Event.Frames}} + <i class="ion-ios-bell-outline"></i> {{event.Event.AlarmFrames}} + <i class="ion-arrow-graph-up-right"></i> {{event.Event.TotScore}} + </div> </div> - </div> <!--row--> + <!--row--> - <div class="row" style="font-size:80%; color:rgb(110,110,110)"> - <div class="item-text-wrap"><i class="ion-calendar"></i> - {{prettify(event.Event.StartTime)}} - <br/> - <i class="ion-clipboard"></i> {{event.Event.Notes}} - <br/> + <div class="row" style="font-size:80%; color:rgb(110,110,110)"> + <div class="item-text-wrap"><i class="ion-calendar"></i> {{prettify(event.Event.StartTime)}} + <br/> + <i class="ion-clipboard"></i> {{event.Event.Notes}} + <!-- <br/> Default video:{{event.Event.relativePath}}{{event.Event.DefaultVideo}}--> + </div> </div> - </div> - <span style="float:right"> + <span style="float:right"> <button class="button button-small icon icon-left ion-ios-eye" ng-click="toggleGroup(event,$index,event.Event.Frames)" > Quick Scrub @@ -118,23 +121,27 @@ ng-click="closeIfOpen(event);openModal(event.Event.Id, event.Event.Name, event.Event.Length,event.Event.Frames, event.Event.BasePath, event.Event.relativePath)" > View Footage </button> </span> - - - <!-- this is the event scrub area --> - <div ng-if = "isGroupShown(event)"> - <br/> - <br/> - <br/> - <div style="width:90%"> - <input ng-model="ionRange.index" type="text" id="mySlider1" slider options="slider_options" /> - </div><br/> + <!-- this is the event scrub area --> + <div ng-if="isGroupShown(event)"> + + <div ng-if="event.Event.DefaultVideo==''"> + + + <br/> + <br/> + <br/> + + <div style="width:90%"> + <input ng-model="ionRange.index" type="text" id="mySlider1" slider options="slider_options" /> + </div> + <br/> - <!-- <div class="range" style="width:90%"> + <!-- <div class="range" style="width:90%"> <span class="events-alarm-line"></span> <input type="range" ng-model="ionRange.index" min="1" max="{{event.Event.Frames}}" @@ -148,23 +155,17 @@ </datalist> </div>--> - <p>{{mycarousel.index+1}}/{{event.Event.Frames}} Type: {{FrameArray[mycarousel.index].Type}}</p> - - <div style="height:190px"> - <ul rn-carousel rn-carousel-buffered - rn-carousel-transition="none" rn-swipe-disabled="true" - rn-carousel-index="mycarousel.index" - rn-carousel-auto-slide="{{calcMsTimer(event.Event.Frames, event.Event.Length)/1000.0}}" rn-carousel-pause-on-hover > - <li ng-repeat="slide in slides"> - <!-- Linwood scaling --> - <img imageonload="finishedLoadingImage($index)" - image-spinner-src="{{playbackURL}}/index.php?view=image&path={{event.Event.relativePath}}{{slide.img}}&height=380" - image-spinner-loader="lines" - height="190px";/> - <br/> + <p>{{mycarousel.index+1}}/{{event.Event.Frames}} Type: {{FrameArray[mycarousel.index].Type}}</p> + + <div style="height:190px"> + <ul rn-carousel rn-carousel-buffered rn-carousel-transition="none" rn-swipe-disabled="true" rn-carousel-index="mycarousel.index" rn-carousel-auto-slide="{{calcMsTimer(event.Event.Frames, event.Event.Length)/1000.0}}" rn-carousel-pause-on-hover> + <li ng-repeat="slide in slides"> + <!-- Linwood scaling --> + <img imageonload="finishedLoadingImage($index)" image-spinner-src="{{playbackURL}}/index.php?view=image&path={{event.Event.relativePath}}{{slide.img}}&height=380" image-spinner-loader="lines" height="190px" ;/> + <br/> - <!-- <img image-spinner-src="{{loginData.url}}cgi-bin/nph-zms?source=event&mode=jpeg&event={{eventId}}&frame=1&scale=100&rate=100&maxfps=5&replay=single&user={{loginData.username}}&pass={{loginData.password}}" height="190px;" + <!-- <img image-spinner-src="{{loginData.url}}cgi-bin/nph-zms?source=event&mode=jpeg&event={{eventId}}&frame=1&scale=100&rate=100&maxfps=5&replay=single&user={{loginData.username}}&pass={{loginData.password}}" height="190px;" image-spinner-loader="lines" />--> @@ -173,39 +174,54 @@ image-spinner-loader="lines" height="190px";/>--> - </li> - </ul> - </div> - </div> + </li> + </ul> + </div> + </div> <!-- no DefaultVideo --> + - <ion-delete-button class="ion-minus-circled" - ng-click="deleteEvent(event.Event.Id, $index)"> - </ion-delete-button> - <!-- + <div ng-if="event.Event.DefaultVideo!=''"> + <!--<br/>events/{{event.Event.relativePath}}{{event.Event.DefaultVideo}}<br/>--> + + <!-- <video controls="controls" preload="metadata" autoplay="autoplay" webkit-playsinline="webkit-playsinline" class="videoPlayer"><source src="http://173.228.105.6/zm/events/2/15/11/01/01/54/03/754-video.mp4" type="video/mp4"/></video>--> + <br/><br/><br/> + <div class="videogular-container"> + <videogular vg-theme="event.Event.video.config.theme"> + <vg-media vg-src="event.Event.video.config.sources" + + vg-native-controls="true"> + </vg-media> + </videogular> + </div> + + </div> <!-- DefaultVideo --> + </div> <!-- isGroupShown --> + + <ion-delete-button class="ion-minus-circled" ng-click="deleteEvent(event.Event.Id, $index)"> + </ion-delete-button> + <!-- <ion-option-button class="button-assertive" ng-click="deleteEvent(event.Event.Id, $index)"> Delete </ion-option-button>--> - + </div> </ion-item> </ion-list> </div> <ion-item ng-show="!events.length"> - No events to display. + No events to display. </ion-item> - <div ng-if = "!eventsBeingLoaded"> - <ion-infinite-scroll ng-if="moreDataCanBeLoaded()" - icon="ion-loading-c" - on-infinite="loadMore()" distance="2%"> + <div ng-if="!eventsBeingLoaded"> + <ion-infinite-scroll ng-if="moreDataCanBeLoaded()" icon="ion-loading-c" on-infinite="loadMore()" distance="2%"> </ion-infinite-scroll> </div> </ion-content> - <div class="events-float-filter" ng-if="isEventFilterOn" on-tap="filterTapped();">Filter On</div> + <div class="events-float-filter" ng-if="isEventFilterOn" on-tap="filterTapped();">Filter On</div> - <ion-pull-up-footer class="bar-energized" on-expand="footerExpand()" on-collapse="footerCollapse()" initial-state="minimized" default-behavior="expand" > + <ion-pull-up-footer class="bar-energized" on-expand="footerExpand()" on-collapse="footerCollapse()" initial-state="minimized" default-behavior="expand"> <ion-pull-up-handle width="100" height="25" toggle="ion-chevron-up ion-chevron-down" style="border-radius: 25px 25px 0 0"> <i class="icon ion-chevron-up"></i> @@ -214,12 +230,11 @@ <h1 class="title" ion-pull-up-trigger>Latest Events</h1> </ion-pull-up-bar> <ion-pull-up-content scroll="true"> - + <div class="list list-inset"> <div class="item item-divider">1 hour summary</div> - <div ng-repeat="hour in hours" - id="hour-{{$index}}"> - + <div ng-repeat="hour in hours" id="hour-{{$index}}"> + <span style="color:black"> <a class="item item-icon-right" href="" ng-click="showEvents('1', 'hour',hour.mid);"> @@ -227,15 +242,14 @@ <i class="icon ion-android-arrow-dropright"></i> </a> </span> - + </div> </div> - + <div class="list list-inset"> <div class="item item-divider">1 day summary</div> - <div ng-repeat="day in days" - id="day-{{$index}}"> - + <div ng-repeat="day in days" id="day-{{$index}}"> + <span style="color:black"> <a class="item item-icon-right" href="" ng-click="showEvents('1', 'day',day.mid);"> @@ -243,16 +257,15 @@ <i class="icon ion-android-arrow-dropright"></i> </a> </span> - + </div> </div> - - + + <div class="list list-inset"> <div class="item item-divider">1 week summary</div> - <div ng-repeat="week in weeks" - id="week-{{$index}}"> - + <div ng-repeat="week in weeks" id="week-{{$index}}"> + <span style="color:black"> <a class="item item-icon-right" href="" ng-click="showEvents('1', 'week',week.mid);"> @@ -260,15 +273,14 @@ <i class="icon ion-android-arrow-dropright"></i> </a> </span> - + </div> </div> - + <div class="list list-inset"> <div class="item item-divider">1 month summary</div> - <div ng-repeat="month in months" - id="month-{{$index}}"> - + <div ng-repeat="month in months" id="month-{{$index}}"> + <span style="color:black"> <a class="item item-icon-right" href="" ng-click="showEvents('1', 'months',month.mid);"> @@ -276,19 +288,16 @@ <i class="icon ion-android-arrow-dropright"></i> </a> </span> - + </div> </div> - - <br/><br/> - - - </ion-pull-up-content> - </ion-pull-up-footer> - - -</ion-view> + <br/> + <br/> + </ion-pull-up-content> + </ion-pull-up-footer> + +</ion-view>
\ No newline at end of file |
