Skip to content

Commit a6c0353

Browse files
authored
feat: make overlays mutable (#223)
* implement initial add/remove fns * add tests for add/remove fns * implement remove functionality with tests * update 'add' fn test * update docs to include add/remove fns and remove docs:toc stage * update index.html example * update readme toc * fix refactored docs * refactor overlays property to be a getter fn * refactor 'getOverlay' to 'get' * update readme toc * change example usage to use const instead of var --------- Co-authored-by: uomar <[email protected]>
1 parent 84f7ca9 commit a6c0353

File tree

5 files changed

+276
-34
lines changed

5 files changed

+276
-34
lines changed

README.md

+51
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ Maintenance Status: Stable
1818

1919
- [Getting Started](#getting-started)
2020
- [Documentation](#documentation)
21+
- [API](#api)
22+
- [`player.overlay()`](#playeroverlay)
23+
- [`overlay.get()`](#overlayget)
24+
- [`overlay.add(object|array)`](#overlayaddobjectarray)
25+
- [`overlay.remove(object)`](#overlayremoveobject)
2126
- [Plugin Options](#plugin-options)
2227
- [`align`](#align)
2328
- [`showBackground`](#showbackground)
@@ -45,6 +50,52 @@ There's also a [working example](https://github.com/brightcove/videojs-overlay/b
4550

4651
## Documentation
4752

53+
### API
54+
#### `player.overlay()`
55+
This is the main interface and the way to initialize this plugin. It takes [an options object as input](#plugin-options).
56+
57+
#### `overlay.get()`
58+
59+
Returns an array of all the overlays set up for the current video.
60+
61+
#### `overlay.add(Object|Array)`
62+
63+
Adds one or more overlays to the current list of overlays without replacing the current list of overlays.
64+
Returns a reference to the added overlays.
65+
66+
```js
67+
const overlay = player.overlay({
68+
content: 'Default overlay content',
69+
debug: true,
70+
overlays: [{
71+
content: 'The video is playing!',
72+
start: 'play',
73+
end: 'pause'
74+
}]
75+
});
76+
const addedOverlays = overlay.add({content: "this is a new one", start: "play", end: "pause"});
77+
```
78+
79+
80+
#### `overlay.remove(Object)`
81+
82+
Removes an individual overlay from the list of overlays. Calling this method with an invalid overlay object removes nothing from the list.
83+
84+
```js
85+
const overlay = player.overlay({
86+
content: 'Default overlay content',
87+
debug: true,
88+
overlays: [{
89+
content: 'The video is playing!',
90+
start: 'play',
91+
end: 'pause'
92+
}]
93+
});
94+
const overlayToRemove = overlay.get()[0];
95+
overlay.remove(overlayToRemove);
96+
```
97+
98+
4899
### Plugin Options
49100

50101
You may pass in an options object to the plugin upon initialization. This

index.html

+5-3
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818
<script src="dist/videojs-overlay.js"></script>
1919
<script>
2020
(function(window, videojs) {
21-
var player = window.player = videojs('videojs-overlay-player');
22-
player.overlay({
21+
const player = window.player = videojs('videojs-overlay-player');
22+
const overlay = player.overlay({
2323
content: 'Default overlay content',
2424
debug: true,
2525
overlays: [{
2626
content: 'The video is playing!',
2727
start: 'play',
28-
end: 'pause'
28+
end: 'pause',
29+
align: 'bottom-right'
2930
}, {
3031
start: 0,
3132
end: 15,
@@ -43,6 +44,7 @@
4344
end: 'pause'
4445
}]
4546
});
47+
overlay.add({content: "this is a new one", start: "play", end: "pause"});
4648
}(window, window.videojs));
4749
</script>
4850
</body>

package.json

-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@
8989
"git add"
9090
],
9191
"README.md": [
92-
"npm run docs:toc",
9392
"git add"
9493
]
9594
},

src/plugin.js

+93-30
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ const isNumber = n => typeof n === 'number' && n === n;
3636
/**
3737
* Whether a value is a string with no whitespace.
3838
*
39-
* @param {String} s
40-
* @return {Boolean}
39+
* @param {string} s
40+
* @return {boolean}
4141
*/
4242
const hasNoWhitespace = s => typeof s === 'string' && (/^\S+$/).test(s);
4343

@@ -116,6 +116,7 @@ class Overlay extends Component {
116116

117117
/**
118118
* Logs debug errors
119+
*
119120
* @param {...[type]} args [description]
120121
* @return {[type]} [description]
121122
*/
@@ -160,11 +161,11 @@ class Overlay extends Component {
160161
/**
161162
* Determine whether or not the overlay should hide.
162163
*
163-
* @param {Number} time
164+
* @param {number} time
164165
* The current time reported by the player.
165-
* @param {String} type
166+
* @param {string} type
166167
* An event type.
167-
* @return {Boolean}
168+
* @return {boolean}
168169
*/
169170
shouldHide_(time, type) {
170171
const end = this.options_.end;
@@ -195,11 +196,11 @@ class Overlay extends Component {
195196
/**
196197
* Determine whether or not the overlay should show.
197198
*
198-
* @param {Number} time
199+
* @param {number} time
199200
* The current time reported by the player.
200-
* @param {String} type
201+
* @param {string} type
201202
* An event type.
202-
* @return {Boolean}
203+
* @return {boolean}
203204
*/
204205
shouldShow_(time, type) {
205206
const start = this.options_.start;
@@ -301,6 +302,7 @@ videojs.registerComponent('Overlay', Overlay);
301302
* @param {Object} [options={}]
302303
*/
303304
const plugin = function(options) {
305+
const player = this;
304306
const settings = videojs.mergeOptions(defaults, options);
305307

306308
// De-initialize the plugin if it already has an array of overlays.
@@ -320,37 +322,98 @@ const plugin = function(options) {
320322
// because it doesn't make sense to pass it to each Overlay component.
321323
delete settings.overlays;
322324

323-
this.overlays_ = overlays.map(o => {
324-
const mergeOptions = videojs.mergeOptions(settings, o);
325-
const attachToControlBar = typeof mergeOptions.attachToControlBar === 'string' || mergeOptions.attachToControlBar === true;
325+
const mapOverlays = (items) => {
326+
return items.map(o => {
327+
const mergeOptions = videojs.mergeOptions(settings, o);
328+
const attachToControlBar = typeof mergeOptions.attachToControlBar === 'string' || mergeOptions.attachToControlBar === true;
326329

327-
if (!this.controls() || !this.controlBar) {
328-
return this.addChild('overlay', mergeOptions);
329-
}
330+
if (!this.controls() || !this.controlBar) {
331+
return this.addChild('overlay', mergeOptions);
332+
}
330333

331-
if (attachToControlBar && mergeOptions.align.indexOf('bottom') !== -1) {
332-
let referenceChild = this.controlBar.children()[0];
334+
if (attachToControlBar && mergeOptions.align.indexOf('bottom') !== -1) {
335+
let referenceChild = this.controlBar.children()[0];
333336

334-
if (this.controlBar.getChild(mergeOptions.attachToControlBar) !== undefined) {
335-
referenceChild = this.controlBar.getChild(mergeOptions.attachToControlBar);
336-
}
337+
if (this.controlBar.getChild(mergeOptions.attachToControlBar) !== undefined) {
338+
referenceChild = this.controlBar.getChild(mergeOptions.attachToControlBar);
339+
}
337340

338-
if (referenceChild) {
339-
const referenceChildIndex = this.controlBar.children().indexOf(referenceChild);
340-
const controlBarChild = this.controlBar.addChild('overlay', mergeOptions, referenceChildIndex);
341+
if (referenceChild) {
342+
const referenceChildIndex = this.controlBar.children().indexOf(referenceChild);
343+
const controlBarChild = this.controlBar.addChild('overlay', mergeOptions, referenceChildIndex);
341344

342-
return controlBarChild;
345+
return controlBarChild;
346+
}
343347
}
348+
349+
const playerChild = this.addChild('overlay', mergeOptions);
350+
351+
this.el().insertBefore(
352+
playerChild.el(),
353+
this.controlBar.el()
354+
);
355+
356+
return playerChild;
357+
});
358+
};
359+
360+
this.overlays_ = mapOverlays(overlays);
361+
362+
/**
363+
* Adds one or more items to the existing list of overlays.
364+
*
365+
* @param {Object|Array} item
366+
* An item (or an array of items) to be added as overlay/s
367+
*
368+
* @return {Array[Overlay]}
369+
* The array of overlay objects that were added
370+
*/
371+
function add(item) {
372+
if (!Array.isArray(item)) {
373+
item = [item];
344374
}
345375

346-
const playerChild = this.addChild('overlay', mergeOptions);
376+
const addedOverlays = mapOverlays(item);
377+
378+
player.overlays_ = player.overlays_.concat(addedOverlays);
379+
380+
return addedOverlays;
381+
}
382+
383+
/**
384+
*
385+
* @param {Overlay} item
386+
* An item to be removed from the array of overlays
387+
*
388+
* @throws {Error}
389+
* Item to remove must be present in the array of overlays
390+
*
391+
*/
392+
function remove(item) {
393+
const index = player.overlays_.indexOf(item);
394+
395+
if (index !== -1) {
396+
item.el().parentNode.removeChild(item.el());
397+
player.overlays_.splice(index, 1);
398+
} else {
399+
player.log.warn('overlay does not exist and cannot be removed');
400+
}
401+
}
402+
403+
/**
404+
* Gets the array of overlays used for the current video
405+
*
406+
* @return The array of overlay objects currently used by the plugin
407+
*/
408+
function get() {
409+
return player.overlays_;
410+
}
347411

348-
this.el().insertBefore(
349-
playerChild.el(),
350-
this.controlBar.el()
351-
);
352-
return playerChild;
353-
});
412+
return {
413+
add,
414+
remove,
415+
get
416+
};
354417
};
355418

356419
plugin.VERSION = VERSION;

0 commit comments

Comments
 (0)