Skip to content
This repository has been archived by the owner on Nov 26, 2021. It is now read-only.

Commit

Permalink
Merge pull request #13 from Financial-Times/browser-bugs
Browse files Browse the repository at this point in the history
Moves files to src/js and fixes video in modern mobile browsers
  • Loading branch information
Alberto Elias authored Jul 25, 2016
2 parents 3e2eac1 + 26f2401 commit fd03d8b
Show file tree
Hide file tree
Showing 14 changed files with 110 additions and 83 deletions.
4 changes: 0 additions & 4 deletions demos/src/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,3 @@
min-height: 228px;
position: relative;
}
video,
img {
width: 100%;
}
2 changes: 0 additions & 2 deletions demos/src/placeholder.js

This file was deleted.

4 changes: 2 additions & 2 deletions demos/src/placeholder.mustache
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div>
<div class="o-video video-container" data-o-component="o-video"
<div class="video-container">
<div class="o-video" data-o-component="o-video"
data-o-video-source="Brightcove"
data-o-video-id="4165329773001"
data-o-video-advertising="true"
Expand Down
7 changes: 4 additions & 3 deletions demos/src/video.mustache
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<div>
<div class="o-video video-container" data-o-component="o-video"
<div class="video-container">
<div class="o-video" data-o-component="o-video"
data-o-video-source="Brightcove"
data-o-video-id="4165329773001"
data-o-video-advertising="true"></div>
data-o-video-advertising="true">
</div>
</div>
2 changes: 1 addition & 1 deletion main.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Video from './src/video.js';
import Video from './src/js/video.js';

const constructAll = () => {
Video.init();
Expand Down
13 changes: 11 additions & 2 deletions main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ $_o-video_applied: false !default;
@if (not $_o-video_applied) {
.o-video {
position: relative;
cursor: pointer;
width: 100%;
height: 100%;

&:before {
content: '';
Expand All @@ -19,14 +19,22 @@ $_o-video_applied: false !default;

.o-video__video,
.o-video__placeholder,
.o-video__ad {
.o-video__placeholder-image,
.o-video__ad,
.o-video__overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}

.o-video__placeholder,
.o-video__overlay {
z-index: 1;
cursor: pointer;
}

.o-video__title {
position: absolute;
top: 0;
Expand Down Expand Up @@ -63,6 +71,7 @@ $_o-video_applied: false !default;
transition: opacity 0.1s;
border-radius: 20px;
}

&:hover .o-video__play-button-icon {
opacity: 0.5;
}
Expand Down
78 changes: 53 additions & 25 deletions src/ads.js → src/js/ads.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
/* global google */

function createVideoOverlayElement() {
const overlayEl = document.createElement('div');
overlayEl.classList.add('o-video__overlay');
return overlayEl;
}

class VideoAds {
constructor(video) {
this.video = video;
this.adsLoaded = false;
this.videoLoad = false;

if (!this.video.placeholderEl) {
this.overlayEl = createVideoOverlayElement();
this.video.containerEl.appendChild(this.overlayEl);
}
}

loadAdsLibrary() {
Expand All @@ -21,8 +34,8 @@ class VideoAds {
resolve();
});

googleSdkScript.addEventListener('error', () => {
reject();
googleSdkScript.addEventListener('error', (e) => {
reject(e);
});
});
}
Expand Down Expand Up @@ -71,6 +84,14 @@ class VideoAds {
this.adErrorHandler,
false);

this.requestAds();

this.playAdEventHandler = this.playAdEventHandler.bind(this);
this.overlayEl && this.overlayEl.addEventListener('click', this.playAdEventHandler);
this.video.placeholderEl && this.video.placeholderEl.addEventListener('click', this.playAdEventHandler);
}

requestAds() {
// Request video ads.
const adsRequest = new google.ima.AdsRequest();

Expand All @@ -84,7 +105,7 @@ class VideoAds {

adsRequest.adTagUrl = advertisingUrl;

// Specify the linear and nonlinear slot sizes. This helps the SDK to
// Specify the linear and nonlinear slot sizes. This helps the SDK
// select the correct creative if multiple are returned.
adsRequest.linearAdSlotWidth = 592;
adsRequest.linearAdSlotHeight = 333;
Expand All @@ -96,10 +117,6 @@ class VideoAds {
}

adsManagerLoadedHandler(adsManagerLoadedEvent) {
// If the video has started before the ad loaded, don't load the ad
if (this.video.videoEl.played.length > 0) {
return;
}
// Get the ads manager.
const adsRenderingSettings = new google.ima.AdsRenderingSettings();
adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true;
Expand All @@ -116,17 +133,13 @@ class VideoAds {
this.adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, this.adEventHandler);
this.adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, this.adEventHandler);

this.playAdEventHandler = this.playAdEventHandler.bind(this);
this.video.videoEl.addEventListener('play', this.playAdEventHandler);
this.adsLoaded = true;
if (this.videoLoaded) {
this.startAds();
}
}

playAdEventHandler() {
// Sets the styling now so the ad occupies the space of the video
this.adContainerEl.classList.add('o-video__ad');
// Initialize the video. Must be done via a user action on mobile devices.
this.video.videoEl.load();
this.adDisplayContainer.initialize();

startAds() {
try {
// Initialize the ads manager. Ad rules playlist will start at this time.
this.adsManager.init(this.video.videoEl.clientWidth, this.video.videoEl.clientHeight, google.ima.ViewMode.NORMAL);
Expand All @@ -137,15 +150,32 @@ class VideoAds {
// An error may be thrown if there was a problem with the VAST response.
this.video.videoEl.play();
}
}

playAdEventHandler() {
// Sets the styling now so the ad occupies the space of the video
this.adContainerEl.classList.add('o-video__ad');

this.video.videoEl.removeEventListener('play', this.playAdEventHandler);
this.adDisplayContainer.initialize();
this.video.videoEl.addEventListener('loadedmetadata', () => {
this.videoLoaded = true;
if (this.adsLoaded) {
this.startAds();
}
});

// Initialize the video. Must be done via a user action on mobile devices.
this.video.videoEl.load();

this.overlayEl && this.overlayEl.removeEventListener('click', this.playAdEventHandler);
this.overlayEl && this.video.containerEl.removeChild(this.overlayEl);
this.video.placeholderEl && this.video.placeholderEl.removeEventListener('click', this.playAdEventHandler);
}

adEventHandler(adEvent) {
// Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED)
// don't have ad object associated.
const ad = adEvent.getAd();
let intervalTimer;
switch (adEvent.type) {
case google.ima.AdEvent.Type.LOADED:
// This is the first event sent for an ad - it is possible to
Expand All @@ -164,24 +194,22 @@ class VideoAds {
// For a linear ad, a timer can be started to poll for
// the remaining time.
// TODO: We could use this to add a skip ad button
intervalTimer = setInterval(() => {
// Currently not used
// const remainingTime = this.adsManager.getRemainingTime();
}, 300); // every 300ms
// Currently not used, could be used in an interval
// const remainingTime = this.adsManager.getRemainingTime();
}
break;
case google.ima.AdEvent.Type.COMPLETE:
this.adContainerEl.style.display = 'none';
if (ad.isLinear()) {
clearInterval(intervalTimer);
// Would be used to clear the interval
}
break;
}
}

adErrorHandler() {
// Todo: Handle the error logging.
this.adsManager.destroy();
this.adsManager && this.adsManager.destroy();
this.video.videoEl.play();
}

contentPauseRequestHandler() {
Expand Down
File renamed without changes.
File renamed without changes.
55 changes: 27 additions & 28 deletions src/video.js → src/js/video.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ const defaultOpts = {
optimumwidth: null,
placeholder: false,
placeholdertitle: false,
playButton: true,
data: null
};

Expand Down Expand Up @@ -137,7 +136,11 @@ class Video {
loadAdsLibraryPromise = this.videoAds.loadAdsLibrary();
}
return loadAdsLibraryPromise
.then(() => this.getData())
.then(() => this.getData(), () => {
// If ad doesn't load for some reason, load video as normal
this.opts.advertising = false;
return this.getData();
})
.then(() => this.renderVideo());
}

Expand All @@ -161,47 +164,43 @@ class Video {
}

addPlaceholder() {
this.placeholderEl = document.createElement('img');
this.placeholderEl.setAttribute('src', this.posterImage);
this.placeholderEl = document.createElement('div');
this.placeholderEl.classList.add('o-video__placeholder');
this.containerEl.appendChild(this.placeholderEl);
const placeholderImageEl = document.createElement('img');
placeholderImageEl.classList.add('o-video__placeholder-image');
placeholderImageEl.setAttribute('src', this.posterImage);
this.placeholderEl.appendChild(placeholderImageEl);

let titleEl;
if (this.opts.placeholdertitle) {
titleEl = document.createElement('div');
titleEl.className = 'o-video__title';
titleEl.textContent = this.videoData && this.videoData.name;
this.containerEl.appendChild(titleEl);
this.placeholderEl.appendChild(titleEl);
}

if (this.opts.playButton) {
const playButtonEl = document.createElement('button');
playButtonEl.className = 'o-video__play-button';
const playButtonEl = document.createElement('button');
playButtonEl.className = 'o-video__play-button';

const playButtonTextEl = document.createElement('dd');
playButtonTextEl.className = 'o-video__play-button-text';
playButtonTextEl.textContent = 'Play video';
playButtonEl.appendChild(playButtonTextEl);
const playButtonTextEl = document.createElement('span');
playButtonTextEl.className = 'o-video__play-button-text';
playButtonTextEl.textContent = 'Play video';
playButtonEl.appendChild(playButtonTextEl);

const playIconEl = document.createElement('i');
playIconEl.className = 'o-video__play-button-icon';
playButtonEl.appendChild(playIconEl);
const playIconEl = document.createElement('i');
playIconEl.className = 'o-video__play-button-icon';
playButtonEl.appendChild(playIconEl);

this.containerEl.appendChild(playButtonEl);
this.placeholderEl.appendChild(playButtonEl);

playButtonEl.addEventListener('click', () => {
this.containerEl.removeChild(playButtonEl);
if (titleEl) {
this.containerEl.removeChild(titleEl);
}
this.containerEl.removeChild(this.placeholderEl);
this.placeholderEl.addEventListener('click', () => {
this.containerEl.removeChild(this.placeholderEl);

this.videoEl.style.display = 'block';
this.videoEl.play();
this.videoEl.focus();
});
}
this.videoEl.style.display = 'block';
this.videoEl.focus();
});

this.containerEl.appendChild(this.placeholderEl);
// Adds video soon so ads can start loading
this.addVideo();
// Hide it so it doesn't flash until the placeholder image loads
Expand Down
2 changes: 1 addition & 1 deletion test/ads.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* global describe, it, beforeEach, afterEach, google */
const Ads = require('./../src/ads');
const Ads = require('./../src/js/ads');
const sinon = require('sinon/pkg/sinon');

describe('Ads', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* global describe, it */
const getRendition = require('./../../src/helpers/get-rendition');
const getRendition = require('./../../src/js/helpers/get-rendition');
const renditions = require('./../fixtures/brightcove.json').renditions;

describe('Get Appropriate Renditions', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/helpers/supported-formats.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* global describe, it */
const supportedFormats = require('./../../src/helpers/supported-formats');
const supportedFormats = require('./../../src/js/helpers/supported-formats');

describe('Supported Formats', () => {

Expand Down
Loading

0 comments on commit fd03d8b

Please sign in to comment.