├── .gitignore ├── .travis.yml ├── README.md ├── bower.json ├── demo └── index.html ├── dist ├── vidBg.css ├── vidBg.js ├── vidBg.min.css └── vidBg.min.js ├── gulpfile.coffee ├── karma.conf.js ├── package.json ├── src ├── vidBg.coffee ├── vidBg.scss └── vidBgTemplate.html └── test └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | bower_components 3 | node_modules 4 | .sass-cache 5 | .DS_Store -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | before_install: 5 | - npm install -g bower 6 | - npm install -g gulp 7 | - npm install 8 | - bower install 9 | script: 10 | - gulp test 11 | after_script: 12 | - gulp coveralls -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | angular-video-background 2 | ======================== 3 | 4 | > html5 fullscreen video background in angular 5 | 6 | [![Build Status](https://travis-ci.org/2013gang/angular-video-background.svg?branch=master)](https://travis-ci.org/2013gang/angular-video-background) 7 | 8 | ## Description 9 | 10 | Eye-catching fullscreen video background is adopted by many modern websites for telling their stories. If you want to tell your own story in angular, you now have a choice. Just provide the video resouces, you can have your stunning video background right away. 11 | 12 | ## Demo 13 | you can see a demo here :) 14 | 15 | ## Dependency 16 | + angular (*) 17 | 18 | ## How to get it 19 | 20 | ```bower install --save angular-video-background``` 21 | 22 | or 23 | 24 | ```npm install --save angular-vidbg``` 25 | 26 | ## Usage 27 | 28 | include 3rd dependencies (angular, lodash) and dist/vidBg.js in your js file 29 | 30 | include dist/vidBg.css in your css file 31 | 32 | then: 33 | 34 | ```html 35 | 36 | ``` 37 | ```js 38 | angular 39 | .module('demo', ['ngVidBg']) 40 | .controller('mainCtrl', ['$scope', function ($scope) { 41 | $scope.resources = [ 42 | 'http://techslides.com/demos/sample-videos/small.webm', 43 | '*.ogv', 44 | '*.mp4', 45 | '*.swf' 46 | ]; 47 | $scope.poster = 'http://placehold.it/2000&text=you%20may%20want%20to%20have%20a%20poster'; 48 | $scope.fullScreen = true; 49 | $scope.muted = true; 50 | $scope.zIndex = '22'; 51 | $scope.playInfo = {}; 52 | $scope.pausePlay = true; 53 | }]); 54 | ``` 55 | Note: .webm, .ogv, .mp4 are the supported resource types. .swf is the fallback resource for environment that does not support the above types. 56 | 57 | ## options 58 | 59 | | attribute | optional? | example | description | 60 | |-------------------|-----------|----------------------|---------------------------------------------------| 61 | | resources | no | ['xx.webm','yy.mp4'] | video resources | 62 | | poster | yes | 'zzz.jpg' | image shown before video loaded | 63 | | full-screen | yes | true | video will fill the width of its container | 64 | | pause | yes | false | whether to pause the video | 65 | 66 | there are a few other configurable options you may also want to use: 67 | `muted`, `control`, `loop`, `auto-play`, `z-index`, `error-msg` 68 | 69 | ### Features 70 | + Dynamic change video resources and pause video 71 | + Show video buffer status and played status 72 | 73 | ## Coming soon 74 | + dynamic video change 75 | + detailed accessible information about your video including loading status, played range, etc. 76 | + testing on different browsers/devices 77 | + how to deal with legacy browsers and mobile 78 | 79 | ### Credits 80 | Inspired by this 81 | 82 | references: [1], [2], [3] 83 | 84 | ### License 85 | MIT 86 | 87 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-vidbg", 3 | "version": "0.0.12", 4 | "authors": [ 5 | "2013gangli@gmail.com" 6 | ], 7 | "description": "Video background", 8 | "keywords": [ 9 | "angular", 10 | "video", 11 | "background" 12 | ], 13 | "dependencies": { 14 | "angular": "*" 15 | }, 16 | "devDependencies": { 17 | "angular-mocks": "*" 18 | }, 19 | "license": "MIT", 20 | "main": [ 21 | "dist/vidBg.css", 22 | "dist/vidBg.js" 23 | ], 24 | "ignore": [ 25 | "**/.*", 26 | "node_modules", 27 | "bower_components", 28 | "test", 29 | "src", 30 | "Gruntfile.coffee", 31 | "gulpfile.coffee" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | ngVidBg demo 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 |
18 |
Buffer status: {{playInfo.buffer}}
19 |
Played: {{playInfo.played}}
20 | 21 | 22 | 23 | 24 | 25 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /dist/vidBg.css: -------------------------------------------------------------------------------- 1 | video.vidBg-body { 2 | background-size: cover; 3 | -webkit-transition: 1s opacity; 4 | transition: 1s opacity; 5 | } 6 | 7 | video.vidBg-fade { 8 | opacity: .5; 9 | } 10 | 11 | video.vidBg-fullScreen { 12 | position: fixed; 13 | right: 0; 14 | bottom: 0; 15 | min-width: 100%; 16 | min-height: 100%; 17 | width: auto; 18 | height: auto; 19 | } 20 | 21 | video.vidBg-autoWidth { 22 | width: 100%; 23 | height: auto; 24 | } 25 | -------------------------------------------------------------------------------- /dist/vidBg.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | angular.module('ngVidBg', ['vidBgTemplate']).constant('vidBgDefaults', { 3 | muted: true, 4 | control: false, 5 | loop: true, 6 | autoPlay: true, 7 | zIndex: -1000, 8 | errorMsg: 'Your browser does not support the video element.' 9 | }).directive('vidBg', [ 10 | '$log', 'vidBgDefaults', function($log, vidBgDefaults) { 11 | return { 12 | restrict: 'E', 13 | templateUrl: 'vidBgTemplate.html', 14 | scope: { 15 | resources: '=', 16 | fullScreen: '=', 17 | poster: '=', 18 | pausePlay: '=', 19 | playInfo: '=' 20 | }, 21 | compile: function(ele, attr) { 22 | var appendResourceToDom, processResources, vid, vidEle; 23 | vid = ele.children().children(); 24 | vidEle = vid.eq(0); 25 | processResources = function(resources) { 26 | var resourceMap; 27 | resourceMap = {}; 28 | if (angular.isArray(resources)) { 29 | angular.forEach(resources, function(ele, index) { 30 | if (angular.isString(ele)) { 31 | if (ele.toUpperCase().indexOf('.WEBM', ele.length - '.WEBM'.length) !== -1) { 32 | resourceMap.webm = ele; 33 | } else if (ele.toUpperCase().indexOf('.MP4', ele.length - '.MP4'.length) !== -1) { 34 | resourceMap.mp4 = ele; 35 | } else if (ele.toUpperCase().indexOf('.OGV', ele.length - '.OGV'.length) !== -1) { 36 | resourceMap.ogv = ele; 37 | } else if (ele.toUpperCase().indexOf('.SWF', ele.length - '.SWF'.length) !== -1) { 38 | resourceMap.swf = ele; 39 | } 40 | } 41 | }); 42 | } 43 | return resourceMap; 44 | }; 45 | appendResourceToDom = function(resourceMap) { 46 | vid.children().eq(0).attr('src', resourceMap.webm ? resourceMap.webm : ''); 47 | vid.children().eq(1).attr('src', resourceMap.mp4 ? resourceMap.mp4 : ''); 48 | vid.children().eq(2).attr('src', resourceMap.ogv ? resourceMap.ogv : ''); 49 | return vid.children().eq(3).children().eq(0).attr('value', resourceMap.swf ? resourceMap.swf : ''); 50 | }; 51 | return { 52 | pre: function(scope, ele, attr) { 53 | scope.posterUrl = scope.poster ? scope.poster : ''; 54 | scope.resourceMap = processResources(scope.resources); 55 | scope.muted = (scope.$parent.$eval(attr.muted)) || vidBgDefaults.muted; 56 | scope.control = (scope.$parent.$eval(attr.control)) || vidBgDefaults.control; 57 | scope.loop = (scope.$parent.$eval(attr.loop)) || vidBgDefaults.loop; 58 | scope.autoPlay = (scope.$parent.$eval(attr.autoPlay)) || vidBgDefaults.autoPlay; 59 | scope.zIndex = +(scope.$parent.$eval(attr.zIndex)) || vidBgDefaults.zIndex; 60 | scope.errorMsg = (scope.$parent.$eval(attr.errorMsg)) || vidBgDefaults.errorMsg; 61 | scope.playInfo = { 62 | buffer: 0, 63 | played: 0 64 | }; 65 | }, 66 | post: function(scope, ele, attr) { 67 | appendResourceToDom(scope.resourceMap); 68 | if (!scope.loop) { 69 | vidEle.on('ended', function() { 70 | return this.addClass('vidBg-fade'); 71 | }); 72 | } 73 | scope.$watch('pausePlay', function(val) { 74 | if (val) { 75 | vidEle.addClass('vidBg-fade'); 76 | return vidEle[0].pause(); 77 | } else { 78 | vidEle.removeClass('vidBg-fade'); 79 | return vidEle[0].play(); 80 | } 81 | }); 82 | scope.$watch('resources', function(val) { 83 | vidEle.removeClass('vidBg-fade'); 84 | vidEle[0].pause(); 85 | appendResourceToDom(processResources(val)); 86 | vidEle[0].load(); 87 | return vidEle[0].play(); 88 | }, true); 89 | vidEle.on('progress', function() { 90 | if (this.buffered.length > 0) { 91 | scope.playInfo.buffer = this.buffered.end(0) / this.duration; 92 | return scope.$apply(); 93 | } 94 | }); 95 | return vidEle.on('timeupdate', function() { 96 | scope.playInfo.played = this.currentTime / this.duration; 97 | return scope.$apply(); 98 | }); 99 | } 100 | }; 101 | } 102 | }; 103 | } 104 | ]); 105 | 106 | }).call(this); 107 | 108 | (function(module) { 109 | try { 110 | module = angular.module('vidBgTemplate'); 111 | } catch (e) { 112 | module = angular.module('vidBgTemplate', []); 113 | } 114 | module.run(['$templateCache', function($templateCache) { 115 | $templateCache.put('vidBgTemplate.html', 116 | '
\n' + 117 | ' \n' + 129 | '
'); 130 | }]); 131 | })(); 132 | -------------------------------------------------------------------------------- /dist/vidBg.min.css: -------------------------------------------------------------------------------- 1 | video.vidBg-body{background-size:cover;-webkit-transition:1s opacity;transition:1s opacity}video.vidBg-fade{opacity:.5}video.vidBg-fullScreen{position:fixed;right:0;bottom:0;min-width:100%;min-height:100%;width:auto;height:auto}video.vidBg-autoWidth{width:100%;height:auto} -------------------------------------------------------------------------------- /dist/vidBg.min.js: -------------------------------------------------------------------------------- 1 | (function(){angular.module("ngVidBg",["vidBgTemplate"]).constant("vidBgDefaults",{muted:!0,control:!1,loop:!0,autoPlay:!0,zIndex:-1e3,errorMsg:"Your browser does not support the video element."}).directive("vidBg",["$log","vidBgDefaults",function(e,r){return{restrict:"E",templateUrl:"vidBgTemplate.html",scope:{resources:"=",fullScreen:"=",poster:"=",pausePlay:"=",playInfo:"="},compile:function(e,n){var t,a,o,l;return o=e.children().children(),l=o.eq(0),a=function(e){var r;return r={},angular.isArray(e)&&angular.forEach(e,function(e,n){angular.isString(e)&&(-1!==e.toUpperCase().indexOf(".WEBM",e.length-".WEBM".length)?r.webm=e:-1!==e.toUpperCase().indexOf(".MP4",e.length-".MP4".length)?r.mp4=e:-1!==e.toUpperCase().indexOf(".OGV",e.length-".OGV".length)?r.ogv=e:-1!==e.toUpperCase().indexOf(".SWF",e.length-".SWF".length)&&(r.swf=e))}),r},t=function(e){return o.children().eq(0).attr("src",e.webm?e.webm:""),o.children().eq(1).attr("src",e.mp4?e.mp4:""),o.children().eq(2).attr("src",e.ogv?e.ogv:""),o.children().eq(3).children().eq(0).attr("value",e.swf?e.swf:"")},{pre:function(e,n,t){e.posterUrl=e.poster?e.poster:"",e.resourceMap=a(e.resources),e.muted=e.$parent.$eval(t.muted)||r.muted,e.control=e.$parent.$eval(t.control)||r.control,e.loop=e.$parent.$eval(t.loop)||r.loop,e.autoPlay=e.$parent.$eval(t.autoPlay)||r.autoPlay,e.zIndex=+e.$parent.$eval(t.zIndex)||r.zIndex,e.errorMsg=e.$parent.$eval(t.errorMsg)||r.errorMsg,e.playInfo={buffer:0,played:0}},post:function(e,r,n){return t(e.resourceMap),e.loop||l.on("ended",function(){return this.addClass("vidBg-fade")}),e.$watch("pausePlay",function(e){return e?(l.addClass("vidBg-fade"),l[0].pause()):(l.removeClass("vidBg-fade"),l[0].play())}),e.$watch("resources",function(e){return l.removeClass("vidBg-fade"),l[0].pause(),t(a(e)),l[0].load(),l[0].play()},!0),l.on("progress",function(){return this.buffered.length>0?(e.playInfo.buffer=this.buffered.end(0)/this.duration,e.$apply()):void 0}),l.on("timeupdate",function(){return e.playInfo.played=this.currentTime/this.duration,e.$apply()})}}}}}])}).call(this),function(e){try{e=angular.module("vidBgTemplate")}catch(r){e=angular.module("vidBgTemplate",[])}e.run(["$templateCache",function(e){e.put("vidBgTemplate.html",'
\n \n
')}])}(); -------------------------------------------------------------------------------- /gulpfile.coffee: -------------------------------------------------------------------------------- 1 | gulp = require 'gulp' 2 | runSequence = require 'run-sequence' 3 | $ = (require 'gulp-load-plugins') 4 | rename: 5 | 'gulp-ruby-sass': 'sass' 6 | 'gulp-minify-css': 'minifycss' 7 | 'gulp-add-src': 'addsrc' 8 | 'gulp-ng-html2js': 'html2js' 9 | 'gulp-ng-annotate': 'annotate' 10 | 11 | AUTOPREFIXER_BROWSERS = [ 12 | 'ie >= 10' 13 | 'ie_mob >= 10' 14 | 'ff >= 30' 15 | 'chrome >= 34' 16 | 'safari >= 7' 17 | 'opera >= 23' 18 | 'ios >= 7' 19 | 'android >= 4.4' 20 | 'bb >= 10' 21 | ] 22 | 23 | gulp.task 'styles', -> 24 | gulp.src 'src/sb.scss' 25 | .pipe $.sass 26 | style: 'expanded' 27 | .pipe $.autoprefixer 28 | browsers: AUTOPREFIXER_BROWSERS 29 | .pipe gulp.dest 'dist' 30 | .pipe $.rename 31 | suffix: '.min' 32 | .pipe do $.minifycss 33 | .pipe gulp.dest 'dist' 34 | .pipe $.notify 35 | message: 'styles task done' 36 | 37 | gulp.task 'scripts', -> 38 | gulp.src 'src/*.coffee' 39 | .pipe do $.coffeelint 40 | .pipe do $.coffeelint.reporter 41 | .pipe do $.coffee 42 | .pipe $.addsrc 'src/template.js' 43 | .pipe $.concat 'sb.js' 44 | .pipe do $.annotate 45 | .pipe do $.jshint 46 | .pipe $.jshint.reporter 'default' 47 | .pipe gulp.dest 'dist' 48 | .pipe do $.uglify 49 | .pipe $.rename 50 | suffix: '.min' 51 | .pipe gulp.dest 'dist' 52 | .pipe $.notify 53 | message: 'scripts task done' 54 | 55 | gulp.task 'html2js', -> 56 | gulp.src 'src/*.html' 57 | .pipe $.html2js 58 | moduleName: 'vidBgTemplate' 59 | prefix: '' 60 | .pipe $.concat 'template.js' 61 | .pipe gulp.dest 'src' 62 | .pipe $.notify 63 | message: 'html2js task done' 64 | 65 | gulp.task 'watch', -> 66 | gulp.watch 'src/*.coffee', ['srcOrTemplateTask'] 67 | gulp.watch 'src/*.html', ['srcOrTemplateTask'] 68 | gulp.watch 'src/*.scss', ['styles'] 69 | 70 | gulp.task 'srcOrTemplateTask', -> 71 | runSequence 'html2js', 'scripts', 'clean' 72 | 73 | gulp.task 'default', ['watch'], (cb) -> 74 | runSequence 'html2js', ['styles', 'scripts'], 'clean', cb 75 | 76 | gulp.task 'test', -> 77 | gulp.src './foobar' 78 | .pipe $.karma 79 | configFile: 'karma.conf.js', 80 | action: 'run' 81 | .on 'error', (err) -> 82 | console.log err 83 | this.emit 'end' 84 | 85 | gulp.task 'coveralls', -> 86 | gulp.src './coverage/*/lcov.info' 87 | .pipe do $.coveralls 88 | 89 | gulp.task 'clean', -> 90 | gulp.src ['*.tmp', 'src/*.js', 'src/*.css'], 91 | read: false 92 | .pipe do $.clean 93 | .pipe $.notify 94 | message: 'clean task done' -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // Generated on Thu Jul 09 2015 10:39:43 GMT-0700 (PDT) 3 | 4 | module.exports = function(config) { 5 | config.set({ 6 | 7 | // base path that will be used to resolve all patterns (eg. files, exclude) 8 | basePath: '', 9 | 10 | 11 | // frameworks to use 12 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 13 | frameworks: ['jasmine'], 14 | 15 | 16 | // list of files / patterns to load in the browser 17 | files: [ 18 | 'bower_components/angular/angular.js', 19 | 'bower_components/angular-mocks/angular-mocks.js', 20 | 'dist/vidBg.js', 21 | 'test/test.js' 22 | ], 23 | 24 | 25 | // list of files to exclude 26 | exclude: [ 27 | ], 28 | 29 | 30 | // preprocess matching files before serving them to the browser 31 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 32 | preprocessors: { 33 | 'dist/vidBg.js': ['coverage'] 34 | }, 35 | 36 | 37 | // test results reporter to use 38 | // possible values: 'dots', 'progress' 39 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 40 | reporters: ['progress', 'coverage'], 41 | 42 | 43 | // web server port 44 | port: 9876, 45 | 46 | 47 | // enable / disable colors in the output (reporters and logs) 48 | colors: true, 49 | 50 | 51 | // level of logging 52 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 53 | logLevel: config.LOG_INFO, 54 | 55 | 56 | // enable / disable watching file and executing tests whenever any file changes 57 | autoWatch: true, 58 | 59 | 60 | // start these browsers 61 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 62 | browsers: ['Chrome'], 63 | 64 | 65 | // Continuous Integration mode 66 | // if true, Karma captures browsers, runs the tests and exits 67 | singleRun: false, 68 | 69 | // optionally, configure the reporter 70 | coverageReporter: { 71 | type : 'lcov', 72 | dir : 'coverage/' 73 | } 74 | }) 75 | } 76 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-vidbg", 3 | "version": "0.0.12", 4 | "description": "angular video background", 5 | "main": "dist/vidBg.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [ 10 | "angular", 11 | "video", 12 | "background" 13 | ], 14 | "author": "2013gangli@gmail.com", 15 | "license": "MIT", 16 | "devDependencies": { 17 | "coffee-script": "^1.8.0", 18 | "gulp": "^3.8.10", 19 | "gulp-add-src": "^0.2.0", 20 | "gulp-autoprefixer": "^2.0.0", 21 | "gulp-clean": "^0.3.1", 22 | "gulp-coffee": "^2.2.0", 23 | "gulp-coffeeify": "^0.1.2", 24 | "gulp-coffeelint": "^0.4.0", 25 | "gulp-concat": "^2.4.3", 26 | "gulp-coveralls": "^0.1.4", 27 | "gulp-jasmine": "^2.0.1", 28 | "gulp-jshint": "^1.9.0", 29 | "gulp-karma": "0.0.4", 30 | "gulp-load-plugins": "^0.8.0", 31 | "gulp-minify-css": "^0.3.11", 32 | "gulp-ng-annotate": "^0.4.3", 33 | "gulp-ng-html2js": "^0.1.8", 34 | "gulp-notify": "^2.1.0", 35 | "gulp-rename": "^1.2.0", 36 | "gulp-ruby-sass": "^0.7.1", 37 | "gulp-uglify": "^1.0.2", 38 | "jasmine-core": "^2.3.4", 39 | "karma":"~0.11.14", 40 | "karma-chrome-launcher": "^0.2.0", 41 | "karma-coverage": "^0.4.2", 42 | "karma-jasmine": "^0.3.5", 43 | "karma-phantomjs-launcher": "^0.2.0", 44 | "karma-spec-reporter": "0.0.19", 45 | "phantomjs": "^1.9.17", 46 | "run-sequence": "^1.0.2" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/vidBg.coffee: -------------------------------------------------------------------------------- 1 | angular 2 | .module 'ngVidBg', ['vidBgTemplate'] 3 | .constant 'vidBgDefaults', 4 | muted: true 5 | control: false 6 | loop: true 7 | autoPlay: true 8 | zIndex: -1000 9 | errorMsg: 'Your browser does not support the 10 | video element.' 11 | .directive 'vidBg', ['$log', 'vidBgDefaults', ($log, vidBgDefaults) -> 12 | restrict: 'E' 13 | templateUrl: 'vidBgTemplate.html' 14 | scope: 15 | resources: '=' 16 | fullScreen: '=' 17 | poster: '=' 18 | pausePlay: '=' 19 | playInfo: '=' 20 | compile: (ele, attr) -> 21 | vid = do ele.children().children 22 | vidEle = vid.eq 0 23 | processResources = (resources) -> 24 | resourceMap = {} 25 | if angular.isArray resources 26 | angular.forEach resources, (ele, index) -> 27 | if angular.isString ele 28 | if ele.toUpperCase().indexOf( 29 | '.WEBM', ele.length - '.WEBM'.length) isnt -1 30 | resourceMap.webm = ele 31 | return 32 | else if ele.toUpperCase().indexOf( 33 | '.MP4', ele.length - '.MP4'.length) isnt -1 34 | resourceMap.mp4 = ele 35 | return 36 | else if ele.toUpperCase().indexOf( 37 | '.OGV', ele.length - '.OGV'.length) isnt -1 38 | resourceMap.ogv = ele 39 | return 40 | else if ele.toUpperCase().indexOf( 41 | '.SWF', ele.length - '.SWF'.length) isnt -1 42 | resourceMap.swf = ele 43 | return 44 | return resourceMap 45 | appendResourceToDom = (resourceMap) -> 46 | # Need to mannually add src because of 47 | # https://docs.angularjs.org/api/ng/service/$sce 48 | vid.children() 49 | .eq(0).attr('src', if resourceMap.webm then resourceMap.webm else '') 50 | 51 | vid.children() 52 | .eq(1).attr('src', if resourceMap.mp4 then resourceMap.mp4 else '') 53 | 54 | vid.children() 55 | .eq(2).attr('src', if resourceMap.ogv then resourceMap.ogv else '') 56 | 57 | vid.children() 58 | .eq(3).children().eq(0) 59 | .attr('value', if resourceMap.swf then resourceMap.swf else '') 60 | 61 | pre: (scope, ele, attr) -> 62 | scope.posterUrl = if scope.poster then scope.poster else '' 63 | scope.resourceMap = processResources scope.resources 64 | scope.muted = (scope.$parent.$eval attr.muted) || 65 | vidBgDefaults.muted 66 | scope.control = (scope.$parent.$eval attr.control) || 67 | vidBgDefaults.control 68 | scope.loop = (scope.$parent.$eval attr.loop) || 69 | vidBgDefaults.loop 70 | scope.autoPlay = (scope.$parent.$eval attr.autoPlay) || 71 | vidBgDefaults.autoPlay 72 | scope.zIndex = +(scope.$parent.$eval attr.zIndex) || 73 | vidBgDefaults.zIndex 74 | scope.errorMsg = (scope.$parent.$eval attr.errorMsg) || 75 | vidBgDefaults.errorMsg 76 | scope.playInfo = 77 | buffer: 0 78 | played: 0 79 | return 80 | 81 | post: (scope, ele, attr) -> 82 | appendResourceToDom scope.resourceMap 83 | if !scope.loop 84 | vidEle.on 'ended', -> 85 | this.addClass 'vidBg-fade' 86 | 87 | scope.$watch 'pausePlay', (val) -> 88 | if (val) 89 | vidEle.addClass 'vidBg-fade' 90 | do vidEle[0].pause 91 | else 92 | vidEle.removeClass 'vidBg-fade' 93 | do vidEle[0].play 94 | scope.$watch 'resources', (val) -> 95 | vidEle.removeClass 'vidBg-fade' 96 | do vidEle[0].pause 97 | appendResourceToDom processResources val 98 | do vidEle[0].load 99 | do vidEle[0].play 100 | , true 101 | 102 | vidEle.on 'progress', -> 103 | if this.buffered.length > 0 104 | scope.playInfo.buffer = this.buffered.end(0) / this.duration 105 | do scope.$apply 106 | vidEle.on 'timeupdate', -> 107 | scope.playInfo.played = this.currentTime / this.duration 108 | do scope.$apply 109 | 110 | ] 111 | -------------------------------------------------------------------------------- /src/vidBg.scss: -------------------------------------------------------------------------------- 1 | video.vidBg-body { 2 | background-size: cover; 3 | transition: 1s opacity; 4 | } 5 | 6 | video.vidBg-fade { 7 | opacity: .5; 8 | } 9 | 10 | video.vidBg-fullScreen { 11 | position: fixed; 12 | right: 0; 13 | bottom: 0; 14 | min-width: 100%; 15 | min-height: 100%; 16 | width: auto; 17 | height: auto; 18 | } 19 | 20 | video.vidBg-autoWidth { 21 | width: 100%; 22 | height: auto; 23 | } -------------------------------------------------------------------------------- /src/vidBgTemplate.html: -------------------------------------------------------------------------------- 1 |
2 | 14 |
-------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | describe('sorting the list of users', function() { 2 | it('sorts in descending order by default', function() { 3 | var users = ['jack', 'igor', 'jeff']; 4 | expect(users.length).toBe(3); 5 | }); 6 | }); --------------------------------------------------------------------------------