Skip to content

Commit

Permalink
feat(controls): Moved keyboard events to each of the control elements…
Browse files Browse the repository at this point in the history
…; refactor way to add/remove default controls via settings
  • Loading branch information
rafa8626 committed Jun 26, 2019
1 parent b823689 commit 089942b
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 141 deletions.
117 changes: 34 additions & 83 deletions src/js/controls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Captions from './controls/captions';
import Fullscreen from './controls/fullscreen';
import Play from './controls/play';
import Progress from './controls/progress';
// import Quality from './controls/quality';
import Settings from './controls/settings';
import Time from './controls/time';
import Volume from './controls/volume';
Expand All @@ -21,77 +22,23 @@ import { isVideo } from './utils/general';
* @implements PlayerComponent
*/
class Controls implements PlayerComponent {
/**
* Instance of Play object.
*
* @public
* @type Play
* @memberof Controls
*/
public play: Play;

/**
* Instance of Time object.
*
* @public
* @type Time
* @memberof Controls
*/
public time: Time;

/**
* Instance of Volume object.
*
* @public
* @type Volume
* @memberof Controls
*/
public volume: Volume;

/**
* Instance of Progress object.
*
* @public
* @type Progress
* @memberof Controls
*/
public progress: Progress;

/**
* Instance of Settings object.
*
* @public
* @private
* @type Settings
* @memberof Controls
*/
public settings: Settings;

/**
* Instance of Fullscreen object.
*
* @public
* @type Fullscreen
* @memberof Controls
*/
public fullscreen: Fullscreen;

/**
* Instance of Captions object.
*
* @public
* @type Captions
* @memberof Controls
*/
public captions: Captions;
private settings: Settings;

/**
* Element that stores the time to hide controls.
*
* @public
* @private
* @type number
* @memberof Controls
*/
public timer: number;
private timer: number;

/**
* Main container of control elements.
Expand All @@ -118,7 +65,11 @@ class Controls implements PlayerComponent {
* @type any
* @memberof Controls
*/
private items: any;
private items: any = {
left: [],
middle: [],
right: [],
};

/**
* Events that will be triggered in Controls element:
Expand All @@ -134,6 +85,17 @@ class Controls implements PlayerComponent {
mouse: {},
};

private controlEls: any = {
Captions,
Fullscreen,
Play,
Progress,
// Quality,
Settings,
Time,
Volume,
};

/**
* Create an instance of Controls.
*
Expand Down Expand Up @@ -320,32 +282,22 @@ class Controls implements PlayerComponent {
* @memberof Controls
*/
private _setElements(): void {
this.play = new Play(this.player);
this.time = new Time(this.player);
this.progress = new Progress(this.player);
this.volume = new Volume(this.player);
this.captions = new Captions(this.player);
this.settings = new Settings(this.player);
this.items = {
left: [
this.play,
this.time,
this.volume,
],
middle: [
this.progress,
],
right: [
this.captions,
this.settings,
],
};
const controls = this.player.getOptions().controls;
controls.forEach((position: string) => {
controls[position].forEach((el: string) => {
const className = `${el.charAt(0).toUpperCase()}${el.slice(1)}`;
const item = new this.controlEls[className](this.player);
if (el === 'settings') {
this.settings = item;
}
this.items[position].push(item);
});
});

// Append/prepend the custom items (if any) depending on their position:
// If position is right, always prepend so Settings and Fullscreen are the last items;
// otherwise, append new controls
const customItems = this.player.getCustomControls();
customItems.forEach(item => {
this.player.getCustomControls().forEach(item => {
if (item.position === 'right') {
this.items[item.position].unshift(item);
} else {
Expand All @@ -355,8 +307,7 @@ class Controls implements PlayerComponent {

// Make sure fullscreen is always the last one
if (isVideo(this.player.getElement())) {
this.fullscreen = new Fullscreen(this.player);
this.items.right.push(this.fullscreen);
this.items.right.push(new Fullscreen(this.player));
}
}

Expand Down
19 changes: 19 additions & 0 deletions src/js/controls/fullscreen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ class Fullscreen implements PlayerComponent {

this._setFullscreenData(false);

this.player.getContainer().addEventListener('keydown', this._keydownEvent.bind(this));

this.fullscreenEvents.forEach(event => {
document.addEventListener(event, this._fullscreenChange.bind(this));
});
Expand Down Expand Up @@ -174,6 +176,8 @@ class Fullscreen implements PlayerComponent {
* @memberof Fullscreen
*/
public destroy(): void {
this.player.getContainer().removeEventListener('keydown', this._keydownEvent.bind(this));

this.fullscreenEvents.forEach(event => {
document.removeEventListener(event, this._fullscreenChange.bind(this));
});
Expand Down Expand Up @@ -296,6 +300,21 @@ class Fullscreen implements PlayerComponent {
video.style.width = width ? '100%' : null;
video.style.height = height ? '100%' : null;
}

/**
* Use the `F` key to go fullscreen if the focus is on player.
*
* @private
* @param {KeyboardEvent} e
* @memberof Fullscreen
*/
private _keydownEvent(e: KeyboardEvent) {
const key = e.which || e.keyCode || 0;
if (key === 70 && !e.ctrlKey && typeof this.fullScreenEnabled !== 'undefined') {
this.toggleFullscreen();
e.preventDefault();
}
}
}

export default Fullscreen;
24 changes: 24 additions & 0 deletions src/js/controls/play.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ class Play implements PlayerComponent {

this.player.getControls().getContainer().addEventListener('controlschanged', this.events.controls.controlschanged);

this.player.getContainer().addEventListener('keydown', this._keydownEvent.bind(this));

this.button.addEventListener('click', this.events.media.click);
}

Expand All @@ -196,9 +198,31 @@ class Play implements PlayerComponent {

this.player.getControls().getContainer().removeEventListener('controlschanged', this.events.controls.controlschanged);

this.player.getContainer().removeEventListener('keydown', this._keydownEvent.bind(this));

this.button.removeEventListener('click', this.events.media.click);
this.button.remove();
}

/**
* Use the `Enter` and space bar keys to play/pause.
*
* @private
* @param {KeyboardEvent} e
* @memberof Play
*/
private _keydownEvent(e: KeyboardEvent) {
const key = e.which || e.keyCode || 0;
const el = this.player.activeElement();
if (key === 13 || key === 32) {
if (el.paused) {
el.play();
} else {
el.pause();
}
e.preventDefault();
}
}
}

export default Play;
39 changes: 38 additions & 1 deletion src/js/controls/progress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ class Progress implements PlayerComponent {
// reach the end of the rail
const current = this.player.isMedia() ? el.currentTime :
((el.duration - el.currentTime) + 1 >= 100 ? 100 :
(el.duration - el.currentTime) + 1);
(el.duration - el.currentTime) + 1);
const min = parseFloat(this.slider.min);
const max = parseFloat(this.slider.max);
this.slider.value = current.toString();
Expand Down Expand Up @@ -377,6 +377,7 @@ class Progress implements PlayerComponent {
this.progress.addEventListener('keydown', this.player.getEvents().keydown);
this.progress.addEventListener('mousemove', this.events.container.mousemove);
document.addEventListener('mousemove', this.events.global.mousemove);
this.player.getContainer().addEventListener('keydown', this._keydownEvent.bind(this));
this.player.getControls().getContainer().addEventListener('controlschanged', this.events.controls.controlschanged);
this.player.getControls().getContainer().appendChild(this.progress);
}
Expand All @@ -400,6 +401,9 @@ class Progress implements PlayerComponent {

document.removeEventListener('mousemove', this.events.global.mousemove);

this.player.getContainer().removeEventListener('keydown', this._keydownEvent.bind(this));
this.player.getControls().getContainer().removeEventListener('controlschanged', this.events.controls.controlschanged);

this.buffer.remove();
this.played.remove();
this.slider.remove();
Expand All @@ -408,6 +412,39 @@ class Progress implements PlayerComponent {
}
this.progress.remove();
}

/**
* Use the left and right arrow keys to manipulate current media time.
*
* Also, the `Home` and `End` keys to restart or end media.
* @private
* @param {KeyboardEvent} e
* @memberof Progress
*/
private _keydownEvent(e: KeyboardEvent) {
const el = this.player.activeElement();
const isAd = this.player.isAd();
const key = e.which || e.keyCode || 0;
// By default, if no `step` set, it will skip 5% of the duration of the media
const newStep = this.player.getOptions().step ? this.player.getOptions().step : el.duration * 0.05;
const step = el.duration !== Infinity ? newStep : 0;

if (key === 35 && !isAd) {
el.currentTime = el.duration;
e.preventDefault();
} else if (key === 36 && !isAd) {
el.currentTime = 0;
e.preventDefault();
} else if ((key === 37 || key === 39) && !isAd && el.duration !== Infinity) {
el.currentTime += key === 37 ? (step * -1) : step;
if (el.currentTime < 0) {
el.currentTime = 0;
} else if (el.currentTime >= el.duration) {
el.currentTime = el.duration;
}
e.preventDefault();
}
}
}

export default Progress;
22 changes: 22 additions & 0 deletions src/js/controls/volume.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ class Volume implements PlayerComponent {
this.slider.addEventListener(event, this.events.slider[event]);
});

this.player.getContainer().addEventListener('keydown', this._keydownEvent.bind(this));

if (!IS_ANDROID && !IS_IOS) {
const controls = this.player.getControls().getContainer();
controls.appendChild(this.button);
Expand All @@ -278,10 +280,30 @@ class Volume implements PlayerComponent {
this.slider.removeEventListener(event, this.events.slider[event]);
});

this.player.getContainer().removeEventListener('keydown', this._keydownEvent.bind(this));

this.slider.remove();
this.display.remove();
this.container.remove();
}

/**
* Use the up and down arrow keys to manipulate volume.
*
* @private
* @param {KeyboardEvent} e
* @memberof Volume
*/
private _keydownEvent(e: KeyboardEvent) {
const key = e.which || e.keyCode || 0;
const el = this.player.activeElement();
if (key === 38 || key === 40) {
const newVol = key === 38 ? Math.min(el.volume + 0.1, 1) : Math.max(el.volume - 0.1, 0);
el.volume = newVol;
el.muted = !(newVol > 0);
e.preventDefault();
}
}
}

export default Volume;

0 comments on commit 089942b

Please sign in to comment.