Skip to content

Commit 83db81a

Browse files
CJAllen056iq-dot
authored andcommitted
Player refactor (MailOnline#19)
* copied across imports and render function into new file Player.jsx from App.jsx. May not all be needed, but will trim as I go * moved videoJSInit into player.js and moved event listeners to props * moved all state from player.jsx to app.jsx * reverting changes to bring videojsinit into player.jsx. I think this was the wrong approach, but can still go back and grab it if needs be * moved most of componentDidMount into Player.jsx, along with static function getVideos * passing necessary stuff for Player via props * App.js accessing this.videoNode through this.playerNode * moved handleScroll event listeners into Player.jsx, and passed function via props * some further adjustments to the handleScroll event to get it working properly across App.jsx and Player.jsx * moved handleScroll and related stuff to Player.jsx, passing necessary state via props * binding functions passed as props in constructor | passing player as parameter back to functions in App.jsx * removing unneccessary imports from Player.jsx * changed Player to React.PureComponent | moved getVideos back to App.jsx and passing result as props * Passing videoJsOptions to Player through props. The options are stored on the App state * moved logic to dispose player from componentWillUnmount in App.jsx to Player.jsx * have handleScroll working, but not sure I'm following best practice here * readded console.log of CLIENT, seeing as I have componentDidMount in App.jsx now * moved plugins across to Player and passed in stuff via props * believe I've done everything to get plugins() working correctly * moved overlay and videoJsInit functions from App.js to Player.js * updated overlay and videoJsInit to use props and state correctly * further adjustments to get functions working * minor changes. Made Modernizr a prop, and made url a const in render to be passed to App.getVideos
1 parent e95698e commit 83db81a

2 files changed

Lines changed: 285 additions & 250 deletions

File tree

src/App.jsx

Lines changed: 51 additions & 250 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import 'videojs-playlist';
77
import 'imports-loader?videojs=video.js!videojs-vast-vpaid/dist/videojs_5.vast.vpaid';
88
import 'whatwg-fetch';
99

10+
import Player from './Player.jsx';
11+
1012
import { itn, bristolsport, londontheinside, spectator, telegraph } from './playlist';
1113

1214
const Modernizr = window.suggestv.Modernizr;
@@ -19,7 +21,7 @@ function getClient() {
1921
const href = window.location.href;
2022

2123
if (urlMatch('localhost')) return 'localhost';
22-
if (urlMatch(['delta.sugges.tv/test/index', 'build.suggestv.io/test/index'])) return 'test';
24+
if (urlMatch(['delta.sugges.tv/test/index', 'build.suggestv.io/test/index', 'build.suggestv.io/test/cjallen'])) return 'test';
2325
if (urlMatch(['delta.sugges.tv/test', 'build.suggestv.io/test'])) return 'client-test';
2426
if (urlMatch('telegraph.co.uk')) return 'telegraph';
2527
if (urlMatch('londontheinside.com')) return 'londontheinside';
@@ -49,7 +51,6 @@ function getClient() {
4951
const CLIENT = getClient();
5052

5153
class App extends React.Component {
52-
5354
static getVideos(url, client) {
5455
let endpoint = `https://api.suggestv.io/semantics?url=${url}`;
5556

@@ -67,9 +68,10 @@ class App extends React.Component {
6768
const rect = element.getBoundingClientRect();
6869
const html = document.documentElement;
6970
return rect.top >= 0 &&
70-
rect.left >= 0 &&
71-
rect.bottom <= (window.innerHeight || html.clientHeight) &&
72-
rect.right <= (window.innerWidth || html.clientWidth);
71+
rect.left >= 0 &&
72+
rect.bottom <= (window.innerHeight || html.clientHeight) &&
73+
rect.right <= (window.innerWidth || html.clientWidth)
74+
;
7375
}
7476

7577
static getAdTag(player, cb) {
@@ -124,6 +126,14 @@ class App extends React.Component {
124126
this.state = {
125127
videos: '',
126128
videosFrom: '',
129+
videoJsOptions: {
130+
controls: true,
131+
preload: 'auto',
132+
loop: false,
133+
muted: true,
134+
width: 640,
135+
height: 264,
136+
},
127137
adError: 'N/A',
128138
adStart: 'N/A',
129139
adSrc: 'N/A',
@@ -142,60 +152,22 @@ class App extends React.Component {
142152
spectator: spectator.slice(0).sort(() => 0.5 - Math.random()),
143153
telegraph: telegraph.slice(0).sort(() => 0.5 - Math.random()),
144154
};
145-
this.plugins = this.plugins.bind(this);
155+
this.setVideos = this.setVideos.bind(this);
146156
this.playlist = this.playlist.bind(this);
147-
this.overlay = this.overlay.bind(this);
148-
this.handleScroll = this.handleScroll.bind(this);
149157
this.postAnalytics = this.postAnalytics.bind(this);
158+
this.handleScroll = throttle(this.handleScroll.bind(this), 400);
159+
this.updateState = this.updateState.bind(this);
150160
}
151161

152162
componentDidMount() {
153-
const url = window.location.href;
154-
const videoJsOptions = {
155-
controls: true,
156-
preload: 'auto', // try auto
157-
loop: false,
158-
muted: true,
159-
width: 640,
160-
height: 264,
161-
};
162-
console.log('SUGGESTV: Client is - ', CLIENT);
163-
164-
// initialise the video player and do set-up work after the player is ready
165-
this.player = videojs(this.videoNode, videoJsOptions, () => {
166-
this.plugins();
167-
168-
App.getVideos(url, CLIENT).then((data) => {
169-
console.log('SUGGESTV: DATA', data);
170-
171-
this.setVideos(data);
172-
const container = document.getElementById('suggestvplayer');
173-
174-
// only deal with tap events from users, ignore generated events
175-
container.addEventListener('tap', (e) => {
176-
if (!e.isTrusted) e.stopImmediatePropagation();
177-
}, true);
178-
179-
this.videoJsInit(this.state.videos);
180-
this.videoNode.muted = true;
181-
})
182-
.catch((err) => {
183-
console.log('SUGGESTV: Promise Error', err);
184-
this.player.dispose();
185-
});
186-
});
187-
188-
window.addEventListener('scroll', throttle(this.handleScroll.bind(this), 400));
189-
window.addEventListener('touchmove', throttle(this.handleScroll.bind(this), 400));
163+
console.log('SUGGESTV: client is ', CLIENT);
164+
window.addEventListener('scroll', this.handleScroll);
165+
window.addEventListener('touchmove', this.handleScroll);
190166
}
191167

192168
componentWillUnmount() {
193169
window.removeEventListener('scroll', this.handleScroll);
194170
window.removeEventListener('touchmove', this.handleScroll);
195-
196-
if (this.player) {
197-
this.player.dispose();
198-
}
199171
}
200172

201173
setVideos(data) {
@@ -283,20 +255,22 @@ class App extends React.Component {
283255
}
284256
}
285257

286-
handleScroll() {
287-
const { pausedByUser, playedByUser, flashTestFinished, videoLoaded } = this.state;
288-
if (App.isInViewport(this.videoNode)) {
289-
290-
if (this.videoNode && !pausedByUser && videoLoaded && flashTestFinished) {
258+
updateState(obj) {
259+
this.setState(obj);
260+
}
291261

262+
handleScroll(player) {
263+
const { pausedByUser, playedByUser, flashTestFinished, videoLoaded } = this.state;
264+
if (App.isInViewport(this.playerNode.videoNode)) {
265+
if (this.playerNode.videoNode && !pausedByUser && videoLoaded && flashTestFinished) {
292266
if (CLIENT === 'cityam' || CLIENT === 'beautyandthedirt') {
293267
console.log('SUGGESTV: click-to-play');
294268
} else {
295-
this.player.play();
269+
this.playerNode.player.play();
296270
}
297271
}
298272
} else if (!playedByUser) {
299-
this.player.pause();
273+
this.playerNode.player.pause();
300274
}
301275
}
302276

@@ -341,205 +315,32 @@ class App extends React.Component {
341315
});
342316
}
343317

344-
plugins() {
345-
videojs.plugin('adform', () => {
346-
const player = this.player;
347-
const adsCancelTimeout = 7000;
348-
const self = this;
349-
350-
function getTagWrapper(cb) {
351-
player.poster(self.state.adLoadingPoster);
352-
player.pause();
353-
player.currentTime(0);
354-
App.getAdTag(player, (err, adTag) => {
355-
console.log('SUGGESTV: AdTag = ', adTag);
356-
self.setState({ adTag });
357-
cb(err, adTag);
358-
});
359-
}
360-
361-
const options = {
362-
playAdAlways: true,
363-
adCancelTimeout: adsCancelTimeout,
364-
adsEnabled: true,
365-
vpaidFlashLoaderPath: 'https://build.suggestv.io/assets/VPAIDFlash.swf',
366-
verbosity: 0,
367-
preferredTech: 'html5',
368-
};
369-
370-
// Does this client require a manual Ad XML retreival or just a URL
371-
if (CLIENT === 'test') {
372-
options.adTagXML = App.getAdTagXML;
373-
} else {
374-
options.getAdTag = getTagWrapper;
375-
}
376-
377-
console.log('SUGGESTV: vastOptions', options);
378-
const vastAd = player.vastClient(options);
379-
380-
// Check if we have flash enabled and if flash test is running
381-
console.log('SUGGESTV Flash:', Modernizr.flash);
382-
if (Modernizr.flash && !Modernizr.flash.blocked) {
383-
window.vpaid_video_flash_tester.on('change', () => this.setState({ flashTestFinished: true }));
384-
} else {
385-
this.setState({ flashTestFinished: true });
386-
}
387-
388-
player.on('vast.adStart', () => {
389-
console.log('SUGGESTV: start ad', vastAd, player);
390-
this.setState({
391-
adStart: this.state.adStart ? `${this.state.adStart},adStart` : 'adStart',
392-
adSrc: player.vast.vastResponse.mediaFiles.length ? player.vast.vastResponse.mediaFiles[0].src : 'N/A',
393-
});
394-
document.querySelectorAll('.delta-overlay').forEach((overlay) => {
395-
overlay.style.display = 'none';
396-
});
397-
});
398-
399-
player.on('vast.adError', (obj) => {
400-
console.log('SUGGESTV: error ad', obj);
401-
this.setState({ adError: obj.error.message });
402-
});
403-
404-
player.on('vast.contentStart', () => {
405-
player.currentTime(0);
406-
document.querySelectorAll('.delta-overlay').forEach((overlay) => {
407-
overlay.style.display = '';
408-
});
409-
410-
this.setState({
411-
adError: 'N/A',
412-
adStart: 'N/A',
413-
adSrc: 'N/A',
414-
adTag: '',
415-
videoCompleted: false,
416-
watchedDuration: 0,
417-
});
418-
419-
this.postAnalytics(player);
420-
});
421-
422-
player.on('vpaid.AdPaused', () => {
423-
/* eslint no-param-reassign: ["off"] */
424-
this.setState({ adStart: `${this.state.adStart},AdPaused` });
425-
document.querySelectorAll('.delta-overlay').forEach((overlay) => {
426-
overlay.style.display = 'none';
427-
});
428-
});
429-
430-
function doVastAdTracking(ctx, events, eventName) {
431-
console.log('SUGGESTV: vast event - ', eventName);
432-
const event = events[eventName];
433-
ctx.setState({ adStart: `${ctx.state.adStart},${eventName}` });
434-
435-
if (event) {
436-
fetch(event[0].uri)
437-
.then(r => r.json())
438-
.then(data => console.log(`SUGGESTV: vast.${eventName}`, data));
439-
}
440-
}
441-
442-
player.on('vast.impression', () => doVastAdTracking(this, player.vast.vastResponse.trackingEvents, 'impression'));
443-
player.on('vast.creativeView', () => doVastAdTracking(this, player.vast.vastResponse.trackingEvents, 'creativeView'));
444-
player.on('vast.start', () => doVastAdTracking(this, player.vast.vastResponse.trackingEvents, 'start'));
445-
player.on('vast.firstQuartile', () => doVastAdTracking(this, player.vast.vastResponse.trackingEvents, 'firstQuartile'));
446-
player.on('vast.midpoint', () => doVastAdTracking(this, player.vast.vastResponse.trackingEvents, 'midpoint'));
447-
player.on('vast.thirdQuartile', () => doVastAdTracking(this, player.vast.vastResponse.trackingEvents, 'thirdQuartile'));
448-
player.on('vast.complete', () => doVastAdTracking(this, player.vast.vastResponse.trackingEvents, 'complete'));
449-
player.on('vast.pause', () => doVastAdTracking(this, player.vast.vastResponse.trackingEvents, 'pause'));
450-
player.on('vast.resume', () => doVastAdTracking(this, player.vast.vastResponse.trackingEvents, 'resume'));
451-
player.on('vast.fullscreen', () => doVastAdTracking(this, player.vast.vastResponse.trackingEvents, 'fullscreen'));
452-
player.on('vast.exitFullscreen', () => doVastAdTracking(this, player.vast.vastResponse.trackingEvents, 'exitFullscreen'));
453-
player.on('vast.mute', () => doVastAdTracking(this, player.vast.vastResponse.trackingEvents, 'mute'));
454-
player.on('vast.unmute', () => doVastAdTracking(this, player.vast.vastResponse.trackingEvents, 'unmute'));
455-
player.on('vast.adclick', () => doVastAdTracking(this, player.vast.vastResponse.trackingEvents, 'adclick'));
456-
457-
player.on('vast.contentEnd', () => videojs(this.videoNode).playlist.next());
458-
});
459-
460-
this.player.adform();
461-
}
462-
463-
playlist(videos) {
318+
playlist(videos, player) {
464319
console.log('SUGGESTV: Do playlist -', videos);
465-
this.player.playlist(videos);
466-
this.player.playlist.autoadvance(0);
467-
}
468-
469-
overlay(title) {
470-
this.player.overlay({
471-
content: 'Video has been paused',
472-
debug: false,
473-
overlays: [{
474-
content: `<h1>${title.substr(0, 60)}...</h1>`,
475-
showBackground: false,
476-
class: 'delta-overlay',
477-
start: 'pause',
478-
end: 'playing',
479-
}],
480-
});
481-
}
482-
483-
videoJsInit(videos) {
484-
console.log('SUGGESTV: Do videojs', this.state);
485-
486-
this.playlist(videos);
487-
const player = this.player;
488-
489-
player.muted(true);
490-
491-
player.tech({ IWillNotUseThisInPlugins: true }).on('touchend', (e) => {
492-
player.muted(!player.muted());
493-
});
494-
495-
player.tech({ IWillNotUseThisInPlugins: true }).on('click', (e) => {
496-
this.setState({
497-
pausedByUser: player.paused(),
498-
playedByUser: !player.paused(),
499-
});
500-
});
501-
502-
player.controlBar.playToggle.on('click', () => {
503-
this.setState({
504-
pausedByUser: player.paused(),
505-
playedByUser: !player.paused(),
506-
});
507-
});
508-
509-
player.on('pause', () => {
510-
this.setState({ watchedDuration: player.currentTime() });
511-
this.postAnalytics(player);
512-
});
513-
514-
player.on('loadstart', () => {
515-
const playlist = player.playlist();
516-
const currentItem = player.playlist.currentItem();
517-
const title = playlist[currentItem < 0 ? 0 : currentItem].title;
518-
519-
player.controlBar.volumeMenuButton.show();
520-
521-
if (CLIENT === 'telegraph') player.addClass('telegraph-player');
522-
523-
this.overlay(title);
524-
});
525-
526-
player.on('ended', () => {
527-
this.setState({ videoCompleted: true });
528-
this.postAnalytics(player);
529-
});
530-
531-
this.setState({ videoLoaded: true });
320+
player.playlist(videos);
321+
player.playlist.autoadvance(0);
532322
}
533323

534324
render() {
325+
const url = window.location.href;
535326
return (
536-
<div data-vjs-player>
537-
<video
538-
playsInline
539-
ref={node => (this.videoNode = node)}
540-
className="video-js vjs-default-skin vjs-16-9 vjs-big-play-centered"
541-
/>
542-
</div>
327+
<Player
328+
ref={p => (this.playerNode = p)}
329+
updateState={this.updateState}
330+
plugins={this.plugins}
331+
setVideos={this.setVideos}
332+
getVideos={App.getVideos(url, CLIENT)}
333+
videos={this.state.videos}
334+
playlist={this.playlist}
335+
videoJsOptions={this.state.videoJsOptions}
336+
adLoadingPoster={this.state.adLoadingPoster}
337+
getAdTag={App.getAdTag}
338+
getAdTagXML={App.getAdTagXML}
339+
adStart={this.state.adStart}
340+
postAnalytics={this.postAnalytics}
341+
CLIENT={CLIENT}
342+
Modernizr={Modernizr}
343+
/>
543344
);
544345
}
545346

0 commit comments

Comments
 (0)