Skip to content

Commit

Permalink
Fix: filmstrip on previously played video (#680)
Browse files Browse the repository at this point in the history
  • Loading branch information
DanDeMicco authored Feb 26, 2018
1 parent 5e8bacc commit d701f65
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 27 deletions.
31 changes: 27 additions & 4 deletions src/lib/viewers/media/MediaControls.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class MediaControls extends EventEmitter {
this.handleAutoplay = this.handleAutoplay.bind(this);
this.handleSubtitle = this.handleSubtitle.bind(this);
this.handleAudioTrack = this.handleAudioTrack.bind(this);
this.timeScrubberHandler = this.timeScrubberHandler.bind(this);

this.setDuration(this.mediaEl.duration);
this.setupSettings();
Expand All @@ -106,10 +107,13 @@ class MediaControls extends EventEmitter {
this.removeVolumeScrubberWrapperExpansionHandlers();
}

if (this.timeScrubberEl) {
this.timeScrubberEl.removeEventListener('mousemove', this.timeScrubberElShowHandler);
this.timeScrubberEl.removeEventListener('mouseleave', this.filmstripHideHandler);
}

if (this.timeScrubber) {
this.timeScrubber.getHandleEl().removeEventListener('mousedown', this.timeScrubbingStartHandler);
this.timeScrubber.getConvertedEl().removeEventListener('mousemove', this.filmstripShowHandler);
this.timeScrubber.getConvertedEl().removeEventListener('mouseleave', this.filmstripHideHandler);
this.timeScrubber.destroy();
this.timeScrubber = undefined;
}
Expand Down Expand Up @@ -170,6 +174,7 @@ class MediaControls extends EventEmitter {
this.filmstripContainerEl = undefined;
this.filmstripEl = undefined;
this.filmstripTimeEl = undefined;
this.timeScrubberElShowHandler = undefined;
}

/**
Expand Down Expand Up @@ -723,6 +728,8 @@ class MediaControls extends EventEmitter {
initFilmstrip(url, status, aspect, interval) {
this.filmstripUrl = url;
this.filmstripInterval = interval;
// event delegation for playerEl & convertedEl
this.timeScrubberElShowHandler = this.timeScrubberHandler(this.filmstripShowHandler);

this.filmstripContainerEl = this.containerEl.appendChild(document.createElement('div'));
this.filmstripContainerEl.className = 'bp-media-filmstrip-container';
Expand All @@ -748,8 +755,8 @@ class MediaControls extends EventEmitter {
this.timeScrubberEl.addEventListener('touchstart', this.timeScrubbingStartHandler);
}

this.timeScrubber.getConvertedEl().addEventListener('mousemove', this.filmstripShowHandler);
this.timeScrubber.getConvertedEl().addEventListener('mouseleave', this.filmstripHideHandler);
this.timeScrubberEl.addEventListener('mousemove', this.timeScrubberElShowHandler);
this.timeScrubberEl.addEventListener('mouseleave', this.filmstripHideHandler);

this.filmstripEl.onload = () => {
if (this.filmstripContainerEl) {
Expand All @@ -762,6 +769,22 @@ class MediaControls extends EventEmitter {
status.getPromise().then(this.setFilmstrip);
}

/**
* Called when user moves mouse over the scrubber
*
* @param {Function} cb - the callback function to be executed
* @return {Function} - the handler function
*/
timeScrubberHandler(cb) {
return (event) => {
const { target } = event;
const { playedEl, convertedEl } = this.timeScrubber;
if (target === convertedEl || target === playedEl) {
cb(event);
}
};
}

/**
* Called when the user has mouse pressed the scrubbler handler
*
Expand Down
95 changes: 72 additions & 23 deletions src/lib/viewers/media/__tests__/MediaControls-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ describe('lib/viewers/media/MediaControls', () => {
);
stubs.removeEventListener = sandbox.stub(document, 'removeEventListener');
stubs.removeActivationListener = sandbox.stub(util, 'removeActivationListener');
stubs.timeScrubberElShowHandler = sandbox.stub();

stubs.genericEl = {
getHandleEl: sandbox.stub().returns({
removeEventListener: sandbox.stub()
Expand All @@ -116,6 +118,10 @@ describe('lib/viewers/media/MediaControls', () => {
removeListener: sandbox.stub(),
removeEventListener: sandbox.stub()
};

stubs.timeScrubberEl = {
removeEventListener: sandbox.stub()
};
});

it('should remove all listeners', () => {
Expand All @@ -129,23 +135,26 @@ describe('lib/viewers/media/MediaControls', () => {

it('should remove time scrubber event listeners if it exists', () => {
mediaControls.timeScrubber = false;

mediaControls.timeScrubberEl = null;
mediaControls.destroy();
expect(mediaControls.timeScrubber).to.be.false;

mediaControls.timeScrubber = stubs.genericEl;

mediaControls.timeScrubberEl = stubs.timeScrubberEl;
mediaControls.timeScrubberElShowHandler = stubs.timeScrubberElShowHandler;

mediaControls.destroy();

expect(stubs.genericEl.getHandleEl().removeEventListener).to.be.calledWith(
'mousedown',
mediaControls.timeScrubbingStartHandler
);
expect(stubs.genericEl.getConvertedEl().removeEventListener).to.be.calledWith(
expect(stubs.timeScrubberEl.removeEventListener).to.be.calledWith(
'mousemove',
mediaControls.filmstripShowHandler
stubs.timeScrubberElShowHandler
);
expect(stubs.genericEl.getConvertedEl().removeEventListener).to.be.calledWith(
expect(stubs.timeScrubberEl.removeEventListener).to.be.calledWith(
'mouseleave',
mediaControls.filmstripHideHandler
);
Expand Down Expand Up @@ -245,7 +254,6 @@ describe('lib/viewers/media/MediaControls', () => {
expect(settingsStub).to.be.calledWith('quality', mediaControls.handleQuality);
expect(settingsStub).to.be.calledWith('speed', mediaControls.handleRate);
expect(settingsStub).to.be.calledWith('autoplay', mediaControls.handleAutoplay);

});
});

Expand Down Expand Up @@ -697,7 +705,7 @@ describe('lib/viewers/media/MediaControls', () => {

describe('isVisible()', () => {
beforeEach(() => {
stubs.wrapperParent = document.createElement('div')
stubs.wrapperParent = document.createElement('div');
mediaControls.wrapperEl = stubs.wrapperParent.appendChild(document.createElement('div'));
});

Expand Down Expand Up @@ -743,14 +751,11 @@ describe('lib/viewers/media/MediaControls', () => {
};
mediaControls.setupScrubbers();
stubs.handleElAddEventListener = sandbox.stub(mediaControls.timeScrubber.getHandleEl(), 'addEventListener');
stubs.getConvertedElAddEventListener = sandbox.stub(
mediaControls.timeScrubber.getConvertedEl(),
'addEventListener'
);

mediaControls.timeScrubberEl = {
addEventListener: sandbox.stub()
}
stubs.timeScrubberEl = {
addEventListener: sandbox.stub(),
removeEventListener: sandbox.stub()
};
mediaControls.timeScrubberEl = stubs.timeScrubberEl;
stubs.setFilmstrip = sandbox.stub(mediaControls, 'setFilmstrip');
});

Expand All @@ -771,25 +776,30 @@ describe('lib/viewers/media/MediaControls', () => {
});

it('should add the correct eventListeners to the handle and converted time scrubber elements', () => {
const spy = sandbox.spy(mediaControls, 'timeScrubberHandler');
mediaControls.initFilmstrip('url', stubs.status, '380', 1);
expect(stubs.handleElAddEventListener).to.be.calledWith(
'mousedown',
mediaControls.timeScrubbingStartHandler
);
expect(stubs.getConvertedElAddEventListener).to.be.calledWith(
expect(stubs.timeScrubberEl.addEventListener).to.be.calledWith(
'mousemove',
mediaControls.filmstripShowHandler
mediaControls.timeScrubberElShowHandler
);
expect(stubs.getConvertedElAddEventListener).to.be.calledWith(
expect(stubs.timeScrubberEl.addEventListener).to.be.calledWith(
'mouseleave',
mediaControls.filmstripHideHandler
);
expect(spy).to.have.been.called.twice;
});

it('should add the touchstart eventListener if touch is detected', () => {
mediaControls.hasTouch = true;
mediaControls.initFilmstrip('url', stubs.status, '380', 1);
expect(mediaControls.timeScrubberEl.addEventListener).to.be.calledWith('touchstart', mediaControls.timeScrubbingStartHandler)
expect(mediaControls.timeScrubberEl.addEventListener).to.be.calledWith(
'touchstart',
mediaControls.timeScrubbingStartHandler
);
});

it('should add the onload function to the filmstrip', () => {
Expand Down Expand Up @@ -1034,12 +1044,9 @@ describe('lib/viewers/media/MediaControls', () => {
describe('initAlternateAudio()', () => {
it('should load alternate audio', () => {
sandbox.stub(mediaControls.settings, 'loadAlternateAudio');
const audios = [
{ language: 'eng', role: 'audio0' },
{ language: 'rus', role: 'audio1' }
];
const audios = [{ language: 'eng', role: 'audio0' }, { language: 'rus', role: 'audio1' }];
mediaControls.initAlternateAudio(audios);
expect(mediaControls.settings.loadAlternateAudio).to.be.calledWith(audios);
expect(mediaControls.settings.loadAlternateAudio).to.be.calledWith(audios);
});
});

Expand All @@ -1051,5 +1058,47 @@ describe('lib/viewers/media/MediaControls', () => {
expect(mediaControls.settings.enableHD).to.be.called;
});
});

describe('timeScrubberHandler()', () => {
let handler;
beforeEach(() => {
stubs.timeScrubberCallbackSpy = sandbox.spy();
handler = mediaControls.timeScrubberHandler(stubs.timeScrubberCallbackSpy);

stubs.playedEl = {
removeEventListener: sandbox.stub()
};
stubs.convertedEl = {
removeEventListener: sandbox.stub()
};

mediaControls.timeScrubber.playedEl = stubs.playedEl;
mediaControls.timeScrubber.convertedEl = stubs.convertedEl;
});

it('should execute the callback when target is playedEl', () => {
const eventStub = {
target: stubs.playedEl
};
handler(eventStub);
expect(stubs.timeScrubberCallbackSpy).to.have.been.called;
});

it('should execute the callback when target is convertedEl', () => {
const eventStub = {
target: stubs.convertedEl
};
handler(eventStub);
expect(stubs.timeScrubberCallbackSpy).to.have.been.called;
});

it('should not execute the callback when target is not playedEl or convertedEl', () => {
const eventStub = {
target: sandbox.stub()
};
handler(eventStub);
expect(stubs.timeScrubberCallbackSpy).to.have.not.been.called;
});
});
});
/* eslint-enable no-unused-expressions */

0 comments on commit d701f65

Please sign in to comment.