Commit 6cc69fd9ca14ea2cc79b4ed7ce025646713126f3
1 parent
3d10ff83
Exists in
master
and in
8 other branches
Add video handler
Showing
6 changed files
with
225 additions
and
22 deletions
Show diff stats
src/app/index.constants.js
src/app/partials/article/article.service.js
... | ... | @@ -11,9 +11,13 @@ |
11 | 11 | |
12 | 12 | var articlesRest = Restangular.all('articles'); |
13 | 13 | |
14 | + var _savedAbstract = null; | |
15 | + | |
14 | 16 | var service = { |
15 | 17 | getList: articlesRest.getList, |
16 | - getHome: getHome | |
18 | + getHome: getHome, | |
19 | + setHomeAbstract: setHomeAbstract, | |
20 | + getHomeAbstract: getHomeAbstract | |
17 | 21 | }; |
18 | 22 | |
19 | 23 | return service; |
... | ... | @@ -24,5 +28,13 @@ |
24 | 28 | fields: 'id,children,categories,abstract,title,image,url,setting,position' |
25 | 29 | }); |
26 | 30 | } |
31 | + | |
32 | + function setHomeAbstract (newAbstract) { | |
33 | + return _savedAbstract = newAbstract; | |
34 | + } | |
35 | + | |
36 | + function getHomeAbstract () { | |
37 | + return _savedAbstract; | |
38 | + } | |
27 | 39 | } |
28 | 40 | })(); | ... | ... |
src/app/partials/inicio/inicio.controller.js
... | ... | @@ -7,33 +7,137 @@ |
7 | 7 | |
8 | 8 | /** @ngInject */ |
9 | 9 | function InicioController(ArticleService, $sce, $log) { |
10 | - $log.debug('InicioController'); | |
10 | + var vm = this; | |
11 | + | |
12 | + // aliases | |
13 | + vm.ArticleService = ArticleService; | |
14 | + vm.$sce = $sce; | |
15 | + vm.$log = $log; | |
16 | + | |
17 | + vm.init(); | |
18 | + vm.$log.debug('InicioController'); | |
19 | + } | |
20 | + InicioController.prototype.init = function() { | |
21 | + this.loadHomeArticle(); | |
22 | + }; | |
11 | 23 | |
24 | + InicioController.prototype.loadHomeArticle = function() { | |
12 | 25 | var vm = this; |
13 | 26 | |
27 | + vm.content = vm.ArticleService.getHomeAbstract(); | |
28 | + vm.isCached = !!vm.content; | |
14 | 29 | |
15 | - $log.log('ArticleService', ArticleService); | |
30 | + if (vm.isCached) { | |
31 | + hideBackground(2000); | |
32 | + } | |
16 | 33 | |
17 | - vm.loading = true; | |
18 | - ArticleService.getHome().then(function(homeArticle){ | |
34 | + vm.ArticleService.getHome().then(function(homeArticle) { | |
19 | 35 | vm.article = homeArticle.article; |
20 | - vm.article.abstract = $sce.trustAsHtml(vm.article.abstract); | |
21 | - vm.loading = false; | |
22 | - }, function () { | |
23 | - $log.error('error'); | |
24 | - vm.loading = false; | |
36 | + }, function(error) { | |
37 | + vm.$log.error(error); | |
38 | + }); | |
39 | + }; | |
40 | + | |
41 | + InicioController.prototype.showVideo = function() { | |
42 | + var vm = this; | |
43 | + | |
44 | + // we need handle home content | |
45 | + if (vm.isCached) { | |
46 | + hideBackground(0); // force to hide | |
47 | + vm.$log.warn('The content already cached. Aborting.'); | |
48 | + return; | |
49 | + } | |
50 | + | |
51 | + vm.content = vm.handleHomeAbstract(vm.article.abstract); | |
52 | + vm.ArticleService.setHomeAbstract(vm.content); | |
53 | + | |
54 | + // inject dependencies | |
55 | + injectIframeApiJs(); | |
56 | + window.onYouTubeIframeAPIReady = window.onYouTubeIframeAPIReady || onYouTubeIframeAPIReady; | |
57 | + window.onYouTubePlayerReady = window.onYouTubePlayerReady || onYouTubePlayerReady; | |
58 | + }; | |
59 | + | |
60 | + InicioController.prototype.handleHomeAbstract = function(abstract) { | |
61 | + var vm = this; | |
62 | + | |
63 | + abstract = forceIframeParams(abstract); | |
64 | + abstract = removeStylefromIframe(abstract); | |
65 | + | |
66 | + return vm.$sce.trustAsHtml(abstract); | |
67 | + }; | |
68 | + | |
69 | + function injectIframeApiJs() { | |
70 | + var tag = document.createElement('script'); | |
71 | + tag.src = 'https://www.youtube.com/iframe_api'; | |
72 | + | |
73 | + var firstScriptTag = document.getElementsByTagName('script')[0]; | |
74 | + firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); | |
75 | + } | |
76 | + | |
77 | + function onYouTubeIframeAPIReady() { | |
78 | + var ytIframe = angular.element.find('.js-iframe iframe'); | |
79 | + new window.YT.Player(ytIframe[0], { | |
80 | + events: { | |
81 | + 'onReady': onYouTubePlayerReady | |
82 | + } | |
25 | 83 | }); |
84 | + } | |
85 | + | |
86 | + function onYouTubePlayerReady (event) { | |
87 | + event.target.playVideo(); | |
88 | + hideBackground(1000); | |
89 | + } | |
90 | + | |
91 | + function hideBackground (ms) { | |
92 | + var $elBg = angular.element.find('.video-background'); | |
93 | + angular.element($elBg).fadeOut(ms || 100); | |
94 | + // angular.element($elBg).hide(); | |
95 | + } | |
96 | + | |
97 | + function forceIframeParams(abstract) { | |
98 | + var patternIframe = '<iframe src="'; | |
99 | + var indexOfIframe = abstract.indexOf(patternIframe); | |
100 | + | |
101 | + if (indexOfIframe === -1) { | |
102 | + return abstract; | |
103 | + } | |
104 | + | |
105 | + var startSrcUrl = indexOfIframe + patternIframe.length; | |
106 | + var endSrcUrl = abstract.indexOf('"', startSrcUrl); | |
107 | + var srcUrl = abstract.substring(startSrcUrl , endSrcUrl); | |
108 | + var resultUrl = srcUrl; | |
109 | + var c = (srcUrl.indexOf('?') !== -1) ? '&' : ''; // already have url params. So, append-it | |
110 | + | |
111 | + // enable js api | |
112 | + if (srcUrl.indexOf('enablejsapi=1') === -1) { | |
113 | + resultUrl += c + 'enablejsapi=1'; | |
114 | + c = '&'; // force to always use '&' after here | |
115 | + } | |
116 | + | |
117 | + // set opaque mode | |
118 | + if (srcUrl.indexOf('wmode=opaque') === -1) { | |
119 | + resultUrl += c + 'wmode=opaque'; | |
120 | + // c = '&'; // force to always use '&' after here | |
121 | + } | |
122 | + | |
123 | + abstract = abstract.replace(srcUrl, resultUrl); | |
124 | + | |
125 | + return abstract; | |
126 | + } | |
127 | + | |
128 | + function removeStylefromIframe (abstract) { | |
129 | + var patternIframe = 'style="'; | |
130 | + var indexOfIframe = abstract.indexOf('<iframe'); | |
131 | + var indexOfStyleOnIframe = abstract.indexOf('style="', indexOfIframe); | |
26 | 132 | |
27 | - // vm.awesomeThings = []; | |
28 | - // vm.classAnimation = ''; | |
29 | - // vm.creationDate = 1438689506090; | |
133 | + if (indexOfStyleOnIframe === -1) { | |
134 | + return abstract; | |
135 | + } | |
30 | 136 | |
31 | - // activate(); | |
137 | + var startStyleContent = indexOfStyleOnIframe + patternIframe.length; | |
138 | + var endStyleContent = abstract.indexOf('"', startStyleContent); | |
139 | + var style = abstract.substring(startStyleContent , endStyleContent); | |
32 | 140 | |
33 | - // function activate() { | |
34 | - // $timeout(function() { | |
35 | - // vm.classAnimation = 'rubberBand'; | |
36 | - // }, 4000); | |
37 | - // } | |
141 | + return abstract.replace(style, ''); | |
38 | 142 | } |
39 | 143 | })(); | ... | ... |
src/app/partials/inicio/inicio.html
1 | -<section class="container"> | |
2 | - <div class="embed-responsive embed-responsive-16by9" ng-bind-html="inicio.article.abstract"></div> | |
1 | +<section class="container video-wrapper"> | |
2 | + <div class="video-player js-youtube"> | |
3 | + <div class="embed-responsive embed-responsive-16by9"> | |
4 | + <div class="js-iframe" ng-show="inicio.content" ng-bind-html="inicio.content"></div> | |
5 | + <div class="video-background" ng-click="inicio.showVideo()"> | |
6 | + <div class="video-thumbnail" style="background-image:url(/assets/images/youtube-background.webp)"></div> | |
7 | + <button class="video-play-button" aria-live="assertive" aria-label="Assistir o vídeo tutorial Dialoga Brasil"> | |
8 | + <svg height="100%" version="1.1" viewBox="0 0 68 48" width="100%"><path class="ytp-play-button-bg" d="m .66,37.62 c 0,0 .66,4.70 2.70,6.77 2.58,2.71 5.98,2.63 7.49,2.91 5.43,.52 23.10,.68 23.12,.68 .00,-1.3e-5 14.29,-0.02 23.81,-0.71 1.32,-0.15 4.22,-0.17 6.81,-2.89 2.03,-2.07 2.70,-6.77 2.70,-6.77 0,0 .67,-5.52 .67,-11.04 l 0,-5.17 c 0,-5.52 -0.67,-11.04 -0.67,-11.04 0,0 -0.66,-4.70 -2.70,-6.77 C 62.03,.86 59.13,.84 57.80,.69 48.28,0 34.00,0 34.00,0 33.97,0 19.69,0 10.18,.69 8.85,.84 5.95,.86 3.36,3.58 1.32,5.65 .66,10.35 .66,10.35 c 0,0 -0.55,4.50 -0.66,9.45 l 0,8.36 c .10,4.94 .66,9.45 .66,9.45 z" fill="#1f1f1e" fill-opacity="0.9"></path><path d="m 26.96,13.67 18.37,9.62 -18.37,9.55 -0.00,-19.17 z" fill="#fff"></path><path d="M 45.02,23.46 45.32,23.28 26.96,13.67 43.32,24.34 45.02,23.46 z" fill="#ccc"></path></svg> | |
9 | + </button> | |
10 | + </div> | |
11 | + </div> | |
12 | + </div> | |
3 | 13 | </section> |
4 | 14 | <section class="container-fluid section-programas"> |
5 | 15 | <programa-list></programa-list> | ... | ... |
src/app/partials/inicio/inicio.scss
1 | 1 | .section-programas { |
2 | 2 | background-color: #f1f1f1; |
3 | 3 | } |
4 | + | |
5 | +.video-wrapper { | |
6 | + margin-bottom: 30px; | |
7 | +} | |
8 | + | |
9 | +.video-player { | |
10 | + position: relative; | |
11 | + border: 1px solid #333; | |
12 | + | |
13 | + .video-background { | |
14 | + text-align: center; | |
15 | + cursor: pointer; | |
16 | + } | |
17 | + | |
18 | + .video-thumbnail { | |
19 | + position: absolute; | |
20 | + width: 100%; | |
21 | + height: 100%; | |
22 | + top: 0; | |
23 | + left: 0; | |
24 | + z-index: 10; | |
25 | + background-position: center; | |
26 | + background-repeat: no-repeat; | |
27 | + -moz-transition: opacity .5s cubic-bezier(0.0,0.0,0.2,1); | |
28 | + -webkit-transition: opacity .5s cubic-bezier(0.0,0.0,0.2,1); | |
29 | + transition: opacity .5s cubic-bezier(0.0,0.0,0.2,1); | |
30 | + background-size: cover; | |
31 | + -moz-background-size: cover; | |
32 | + -webkit-background-size: cover; | |
33 | + } | |
34 | + | |
35 | + .video-play-button { | |
36 | + border: none; | |
37 | + outline: 0; | |
38 | + color: inherit; | |
39 | + text-align: inherit; | |
40 | + font-size: 100%; | |
41 | + font-family: inherit; | |
42 | + cursor: pointer; | |
43 | + line-height: inherit; | |
44 | + background: transparent; | |
45 | + padding: 0; | |
46 | + | |
47 | + position: absolute; | |
48 | + top: 50%; | |
49 | + left: 50%; | |
50 | + width: 68px; | |
51 | + height: 48px; | |
52 | + margin-left: -34px; | |
53 | + margin-top: -24px; | |
54 | + z-index: 15; | |
55 | + | |
56 | + -moz-transition: opacity .25s cubic-bezier(0.0,0.0,0.2,1); | |
57 | + -webkit-transition: opacity .25s cubic-bezier(0.0,0.0,0.2,1); | |
58 | + transition: opacity .25s cubic-bezier(0.0,0.0,0.2,1); | |
59 | + } | |
60 | + | |
61 | + .ytp-play-button-bg { | |
62 | + -moz-transition: fill .1s cubic-bezier(0.4,0.0,1,1),opacity .1s cubic-bezier(0.4,0.0,1,1); | |
63 | + -webkit-transition: fill .1s cubic-bezier(0.4,0.0,1,1),opacity .1s cubic-bezier(0.4,0.0,1,1); | |
64 | + transition: fill .1s cubic-bezier(0.4,0.0,1,1),opacity .1s cubic-bezier(0.4,0.0,1,1); | |
65 | + fill: #1f1f1f; | |
66 | + opacity: .9; | |
67 | + } | |
68 | + | |
69 | + &:hover { | |
70 | + .ytp-play-button-bg { | |
71 | + fill: #cc181e; | |
72 | + opacity: 1; | |
73 | + } | |
74 | + } | |
75 | + | |
76 | + @media screen and (min-width: 992px) { | |
77 | + width: 80%; | |
78 | + margin: 0 auto; | |
79 | + } | |
80 | +} | ... | ... |
src/assets/images/youtube-background.webp
No preview for this file type