@vidispine/vdt-videojs 21.3.0 → 22.1.0-pre.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +4 -4
  2. package/deprecated-app/README.md +21 -0
  3. package/{demo.html → deprecated-app/index.html} +1 -1
  4. package/{demo.js → deprecated-app/index.js} +69 -41
  5. package/{samples → deprecated-app/samples}/birds-es.vvt +0 -0
  6. package/{samples → deprecated-app/samples}/birds.vvt +0 -0
  7. package/{tests.js → deprecated-app/tests.js} +87 -54
  8. package/{lib/style.css → dist/index.css} +755 -55
  9. package/dist/index.es.js +2099 -0
  10. package/dist/index.js +2112 -0
  11. package/dist/index.umd.js +2115 -0
  12. package/package.json +29 -85
  13. package/rollup.config.js +54 -0
  14. package/src/constants.js +1 -1
  15. package/src/externalControls.js +14 -18
  16. package/src/helpOverlay.js +12 -16
  17. package/src/helpers.js +3 -3
  18. package/src/index.js +3 -9
  19. package/src/index.stories.mdx +59 -0
  20. package/src/menu.api.stories.mdx +59 -0
  21. package/src/menu.js +23 -19
  22. package/src/{menu.example.md → menu.usage.stories.mdx} +31 -21
  23. package/src/osd.js +24 -18
  24. package/src/player.api.stories.mdx +120 -0
  25. package/src/player.js +157 -108
  26. package/src/player.scss +2 -0
  27. package/src/{player.example.md → player.usage.stories.mdx} +18 -8
  28. package/src/seekBar.js +85 -48
  29. package/src/timeCodeDisplay.js +39 -31
  30. package/src/videoTime.js +4 -4
  31. package/build.js +0 -233
  32. package/lib/index.cjs.js +0 -3240
  33. package/lib/index.esm.js +0 -3227
  34. package/lib/index.umd.js +0 -3243
  35. package/lib/package.json +0 -13
  36. package/lib/src/constants.js +0 -51
  37. package/lib/src/externalControls.js +0 -307
  38. package/lib/src/helpOverlay.js +0 -106
  39. package/lib/src/helpers.js +0 -34
  40. package/lib/src/index.js +0 -13
  41. package/lib/src/menu.js +0 -365
  42. package/lib/src/osd.js +0 -91
  43. package/lib/src/player.js +0 -943
  44. package/lib/src/seekBar.js +0 -833
  45. package/lib/src/timeCodeDisplay.js +0 -253
  46. package/lib/src/videoTime.js +0 -66
  47. package/log.js +0 -24
  48. package/src/_index.stories.js +0 -24
  49. package/src/externalControls.stories.js +0 -6
  50. package/src/helpOverlay.stories.js +0 -6
  51. package/src/menu.classMethods.md +0 -47
  52. package/src/player.classMethods.md +0 -108
  53. package/src/player.stories.js +0 -14
  54. package/src/seekBar.stories.js +0 -8
  55. package/tmp/player.css +0 -1
package/package.json CHANGED
@@ -1,101 +1,45 @@
1
1
  {
2
2
  "name": "@vidispine/vdt-videojs",
3
- "version": "21.3.0",
3
+ "version": "22.1.0-pre.1",
4
4
  "license": "UNLICENSED",
5
5
  "private": false,
6
- "main": "lib/index.cjs.js",
7
- "module": "lib/index.es.js",
6
+ "main": "dist/index.js",
7
+ "module": "dist/index.es.js",
8
+ "browser": "dist/index.umd.js",
8
9
  "author": "Oto Inša <otoinsa@bertelsmann.de>",
9
10
  "scripts": {
10
- "cleanup": "rm -rf ./dist && rm -rf ./.cache",
11
- "start": "npm run cleanup && parcel ./demo.html --no-source-maps --no-hmr -p 2222 -t browser --open --out-dir ./dev",
12
- "build-legacy": "parcel build ./src/player.js --out-dir ./lib --no-source-maps",
13
- "build": "node ./build.js",
14
- "build:watch": "node ./build.js --watch",
15
- "build:demo": "rm -rf ./demo/ && parcel build ./demo.html --out-file index.html --out-dir ./demo --no-source-maps --public-url ./",
16
- "docs": "jsdoc ./src/player.js -d ./docs/"
17
- },
18
- "devDependencies": {
19
- "@babel/core": "^7.7.7",
20
- "babel-plugin-transform-runtime": "^6.23.0",
21
- "chokidar": "^3.3.1",
22
- "colors": "^1.4.0",
23
- "parcel-bundler": "^1.12.4",
24
- "rollup": "^2.20.0",
25
- "rollup-plugin-json": "^4.0.0",
26
- "sass": "^1.24.3",
27
- "strip-comments": "^2.0.1"
11
+ "build": "rm -rf dist/ && rollup -c",
12
+ "build:watch": "rm -rf dist/*.js* && rollup -c -w --environment DEVELOPMENT",
13
+ "lint": "eslint \"./{src/**/*,*}.{js,md}\"",
14
+ "lint:fix": "yarn lint --fix"
28
15
  },
29
16
  "dependencies": {
30
17
  "mousetrap": "^1.6.3",
31
18
  "video.js": "^7.6.6"
32
19
  },
20
+ "devDependencies": {
21
+ "@babel/core": "^7.17.0",
22
+ "@rollup/plugin-babel": "^5.3.0",
23
+ "@rollup/plugin-commonjs": "^21.0.1",
24
+ "@rollup/plugin-json": "^4.1.0",
25
+ "@rollup/plugin-node-resolve": "^13.1.3",
26
+ "@vidispine/eslint-config-base": "^22.1.0-pre.1",
27
+ "@vidispine/eslint-config-storybook": "*",
28
+ "babel-plugin-transform-runtime": "^6.23.0",
29
+ "rollup": "^2.67.0",
30
+ "rollup-plugin-cleanup": "^3.2.1",
31
+ "rollup-plugin-peer-deps-external": "^2.2.4",
32
+ "rollup-plugin-sass": "^1.2.10"
33
+ },
33
34
  "browserslist": [
34
35
  "since 2017-06"
35
36
  ],
36
- "changelog": {
37
- "0.1.2": [
38
- "Removed unwanted videojs markup",
39
- "Implemented playback hotkeys",
40
- "Borrowed styling ideas from a popular online video platform",
41
- "Visual feedback gizmo as hotkey feedback",
42
- "Subtitle support (VVT)",
43
- "Persistance - volume level",
44
- "Custom timecode display (SMPTE)",
45
- "Frame forward / frame backward 6unctionality"
46
- ],
47
- "0.1.3": [
48
- "Renamed 'subtitles off' to just 'off'",
49
- "Timecode SMPTE - current time in SMPTE with input capabilities",
50
- "Timecode SMPTE - total video duration timecode (read-only)",
51
- "Settings persistance - storing wether subtitles should be on and the selected language as well"
52
- ],
53
- "0.1.4": [
54
- "Subtitles toggle hotkey - c",
55
- "Now accepts Blob as subtitles source file",
56
- "Timecode input improvements",
57
- "Screenshot button with currentTime callback",
58
- "Moved OSD in its own class"
59
- ],
60
- "0.1.6": [
61
- "Help overlay for keyboard controls",
62
- "External player controls component (js, React)",
63
- "External seek-bar component (js, React)"
64
- ],
65
- "0.1.7": [
66
- "In / Out markers for seek bar"
67
- ],
68
- "0.1.8": [
69
- "External TimeCodeDisplay support for player"
70
- ],
71
- "0.1.9": [
72
- "Multiple regions with annotations for SeekBar"
73
- ],
74
- "0.2.2": [
75
- "Overall version bump (improvements)"
76
- ],
77
- "0.3.0": [
78
- "controlsBelowPlayer - reactive option",
79
- "onDark - used in conjuction with controlsBelowPlayer for dark backgrounds",
80
- "Bug fixes, convenience class methods"
81
- ],
82
- "0.3.1": [
83
- "SeekBar - Seek animation, dark mode improvements",
84
- "Bug fixes, refactor & code sharing improvements"
85
- ],
86
- "0.5.3": [
87
- "vdt-videojs now provides a commonjs module with named exports"
88
- ],
89
- "0.6.1": [
90
- "Internal refactor before splitting main features into videojs plugins",
91
- "More bugfixes"
37
+ "eslintConfig": {
38
+ "extends": [
39
+ "@vidispine/eslint-config-base",
40
+ "@vidispine/eslint-config-storybook"
92
41
  ]
93
42
  },
94
- "wishlist": [
95
- "Timecode offset capabilities - i.e. start time from 10:00:00:00"
96
- ],
97
- "backlog": [
98
- "External player controls component",
99
- "Check for hijacked hotkeys and player focus"
100
- ]
101
- }
43
+ "prettier": "@vidispine/prettier-config",
44
+ "gitHead": "9e1d15560719544a68e6bc881e1a40901fe9f786"
45
+ }
@@ -0,0 +1,54 @@
1
+ import { babel } from '@rollup/plugin-babel';
2
+ import commonjs from '@rollup/plugin-commonjs';
3
+ import json from '@rollup/plugin-json';
4
+ import { nodeResolve } from '@rollup/plugin-node-resolve';
5
+ import cleanup from 'rollup-plugin-cleanup';
6
+ import peerDepsExternal from 'rollup-plugin-peer-deps-external';
7
+ import sass from 'rollup-plugin-sass';
8
+
9
+ import pkg from './package.json';
10
+
11
+ const isDevelopment = !!process.env.DEVELOPMENT;
12
+
13
+ export default {
14
+ external: Object.keys(pkg.dependencies || {}).map(
15
+ (packageName) => new RegExp(`^${packageName}(/.*)?`),
16
+ ),
17
+ input: 'src/index.js',
18
+ output: [
19
+ {
20
+ file: pkg.main,
21
+ format: 'cjs',
22
+ sourcemap: isDevelopment,
23
+ },
24
+ {
25
+ file: pkg.module,
26
+ format: 'esm',
27
+ sourcemap: isDevelopment,
28
+ },
29
+ {
30
+ file: pkg.browser,
31
+ format: 'umd',
32
+ sourcemap: isDevelopment,
33
+ name: 'vdtVideojs',
34
+ globals: { mousetrap: 'mousetrap', 'video.js/dist/alt/video.core.min': 'videojs' },
35
+ },
36
+ ],
37
+ plugins: [
38
+ json(),
39
+ sass({
40
+ output: 'dist/index.css',
41
+ }),
42
+ peerDepsExternal(),
43
+ nodeResolve(),
44
+ commonjs(),
45
+ babel({
46
+ babelHelpers: 'runtime',
47
+ exclude: /^(.+\/)?node_modules\/.+$/,
48
+ presets: ['@babel/preset-env'],
49
+ plugins: ['@babel/plugin-transform-runtime'],
50
+ compact: isDevelopment ? false : 'auto',
51
+ }),
52
+ ...(isDevelopment ? [] : [cleanup()]),
53
+ ],
54
+ };
package/src/constants.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import pkgInfo from '../package.json';
2
2
 
3
3
  export const defaults = Object.freeze({
4
- frameRate: (30000 / 1001),
4
+ frameRate: 30000 / 1001,
5
5
  jumpSeconds: 10,
6
6
  inactivityTimeout: 1200, // hide player controls if user inactive for this duration
7
7
  audioInactivityTimeout: 0,
@@ -1,7 +1,5 @@
1
- /* eslint-disable no-plusplus */
2
- /* eslint-disable no-unused-expressions */
3
- import { reactiveSetters } from './helpers';
4
1
  import { classNames, colors } from './constants';
2
+ import { reactiveSetters } from './helpers';
5
3
 
6
4
  const buttonNames = Object.freeze({
7
5
  play: 'play-pause',
@@ -11,7 +9,8 @@ const buttonNames = Object.freeze({
11
9
  end: 'end',
12
10
  });
13
11
 
14
- const buttons = [ // order matters
12
+ const buttons = [
13
+ // order matters
15
14
  buttonNames.start,
16
15
  buttonNames.fb,
17
16
  buttonNames.play,
@@ -217,10 +216,10 @@ class ExternalControls {
217
216
  }
218
217
 
219
218
  handlePress(buttonName) {
220
- if (this.props.player) { // control a vdt player instance directly
221
- const player = this.props.player;
222
- console.log(player)
223
- player.osd && player.osd.disable(); // temporarily disable OSD
219
+ if (this.props.player) {
220
+ // control a vdt player instance directly
221
+ const { player } = this.props;
222
+ if (player.osd) player.osd.disable(); // temporarily disable OSD
224
223
 
225
224
  switch (buttonName) {
226
225
  case buttonNames.start:
@@ -243,27 +242,25 @@ class ExternalControls {
243
242
  break;
244
243
  }
245
244
 
246
- player.osd && player.osd.enable(); // re-enable OSD
245
+ if (player.osd) player.osd.enable(); // re-enable OSD
247
246
  } else {
248
247
  switch (buttonName) {
249
248
  case buttonNames.start:
250
- this.props.onPrev && this.props.onPrev();
249
+ if (this.props.onPrev) this.props.onPrev();
251
250
  break;
252
251
  case buttonNames.fb:
253
- this.props.onFB && this.props.onFB();
252
+ if (this.props.onFB) this.props.onFB();
254
253
  break;
255
254
  case buttonNames.play:
256
255
  if (this.playing) {
257
- this.props.onPause && this.props.onPause();
258
- } else {
259
- this.props.onPlay && this.props.onPlay();
260
- }
256
+ if (this.props.onPause) this.props.onPause();
257
+ } else if (this.props.onPlay) this.props.onPlay();
261
258
  break;
262
259
  case buttonNames.ff:
263
- this.props.onFF && this.props.onFF();
260
+ if (this.props.onFF) this.props.onFF();
264
261
  break;
265
262
  case buttonNames.end:
266
- this.props.onNext && this.props.onNext();
263
+ if (this.props.onNext) this.props.onNext();
267
264
  break;
268
265
  default:
269
266
  // do nothing
@@ -318,5 +315,4 @@ class ExternalControls {
318
315
 
319
316
  ExternalControls.buttonNames = buttonNames;
320
317
 
321
-
322
318
  export default ExternalControls;
@@ -1,6 +1,3 @@
1
- /* eslint-disable no-plusplus */
2
- /* eslint-disable no-unused-expressions */
3
-
4
1
  import mousetrap from 'mousetrap';
5
2
 
6
3
  export default class HelpOverlay {
@@ -18,12 +15,13 @@ export default class HelpOverlay {
18
15
  this.hide();
19
16
  };
20
17
 
21
- this.props.target && this.props.target.appendChild(this.container);
18
+ if (this.props.target) this.props.target.appendChild(this.container);
22
19
 
23
20
  this.draw();
24
21
  }
25
22
 
26
- draw() { // draws keyboard controls
23
+ draw() {
24
+ // draws keyboard controls
27
25
  let tableRowMarkup = ''; // will insert a DOM string here
28
26
  const rows = [
29
27
  ['⎵', 'Play / Pause'],
@@ -41,23 +39,19 @@ export default class HelpOverlay {
41
39
  ['H', 'Toggle this help overlay'],
42
40
  ];
43
41
 
44
-
45
42
  // split the data for 2 columns
46
43
  const halfpointIndex = Math.round(rows.length / 2);
47
- const columns = [
48
- rows.slice(0, halfpointIndex),
49
- rows.slice(halfpointIndex, rows.length),
50
- ];
44
+ const columns = [rows.slice(0, halfpointIndex), rows.slice(halfpointIndex, rows.length)];
51
45
 
52
46
  // table will niceley auto adjust td's according to length
53
- for (let i = 0; i < halfpointIndex; i++) {
47
+ for (let i = 0; i < halfpointIndex; i += 1) {
54
48
  tableRowMarkup += `
55
49
  <tr>
56
50
  <td><div>${columns[0][i][0]}</div></td>
57
51
  <td>- ${columns[0][i][1]}</td>
58
52
 
59
- <td>${(columns[1][i]) ? `<div>${columns[1][i][0]}</div>` : ''}</td>
60
- <td>${(columns[1][i]) ? `- ${columns[1][i][1]}` : ''}</td>
53
+ <td>${columns[1][i] ? `<div>${columns[1][i][0]}</div>` : ''}</td>
54
+ <td>${columns[1][i] ? `- ${columns[1][i][1]}` : ''}</td>
61
55
  </tr>
62
56
  `;
63
57
  }
@@ -87,9 +81,11 @@ export default class HelpOverlay {
87
81
  this.container.classList.add('active');
88
82
  this.state.active = true;
89
83
 
90
- mousetrap.bind('esc', () => { this.hide(); });
84
+ mousetrap.bind('esc', () => {
85
+ this.hide();
86
+ });
91
87
 
92
- this.props.onToggle && this.props.onToggle(true);
88
+ if (this.props.onToggle) this.props.onToggle(true);
93
89
  }
94
90
  }
95
91
 
@@ -100,7 +96,7 @@ export default class HelpOverlay {
100
96
 
101
97
  mousetrap.unbind('esc');
102
98
 
103
- this.props.onToggle && this.props.onToggle(false);
99
+ if (this.props.onToggle) this.props.onToggle(false);
104
100
  }
105
101
  }
106
102
 
package/src/helpers.js CHANGED
@@ -3,7 +3,6 @@ export function truncate(input, len) {
3
3
  return input;
4
4
  }
5
5
 
6
-
7
6
  /*
8
7
  Make certain component props React-ive
9
8
  by being able to call respective component .handleNewProps()
@@ -20,7 +19,8 @@ export function reactiveSetters() {
20
19
  // check for own setters / getters
21
20
  const descriptor = Object.getOwnPropertyDescriptor(proto, key);
22
21
 
23
- if (descriptor && descriptor.set) { // if a setter is defined, apply the prop
22
+ if (descriptor && descriptor.set) {
23
+ // if a setter is defined, apply the prop
24
24
  this[key] = props[key];
25
25
  }
26
26
  });
@@ -32,7 +32,7 @@ export function reactiveSetters() {
32
32
  }
33
33
 
34
34
  // an elegant way to prevent xss attacks
35
- export function sanitize(str) {
35
+ export function sanitize(str) {
36
36
  const temp = document.createElement('div');
37
37
  temp.textContent = str;
38
38
  return temp.innerHTML;
package/src/index.js CHANGED
@@ -1,13 +1,7 @@
1
- import Player from './player';
2
- import TimeCodeDisplay from './timeCodeDisplay';
3
1
  import ExternalControls from './externalControls';
2
+ import Player from './player';
4
3
  import SeekBar from './seekBar';
4
+ import TimeCodeDisplay from './timeCodeDisplay';
5
5
  import VideoTime from './videoTime';
6
6
 
7
- export {
8
- TimeCodeDisplay,
9
- ExternalControls,
10
- SeekBar,
11
- Player,
12
- VideoTime,
13
- };
7
+ export { TimeCodeDisplay, ExternalControls, SeekBar, Player, VideoTime };
@@ -0,0 +1,59 @@
1
+ import { Meta, Description } from '@storybook/addon-docs';
2
+
3
+ import pkgJson from '../package.json';
4
+ import playerReadme from '../README.md';
5
+
6
+ <Meta
7
+ title="vdt-videojs/Introduction"
8
+ parameters={{
9
+ viewMode: 'docs',
10
+ previewTabs: {
11
+ canvas: { hidden: true },
12
+ },
13
+ }}
14
+ />
15
+
16
+ export const changelogMd = () => {
17
+ let mdChangeLog = '';
18
+ Object.keys(pkgJson.changelog)
19
+ .reverse()
20
+ .forEach((changelogKey) => {
21
+ mdChangeLog += `### ${changelogKey}:\n\n`;
22
+ pkgJson.changelog[changelogKey].forEach((entry) => {
23
+ mdChangeLog += `- ${entry}\n`;
24
+ });
25
+ });
26
+ return mdChangeLog;
27
+ };
28
+
29
+ # Introduction
30
+
31
+ ```
32
+ ┌───────────┐ ┌───────┐
33
+ │ vdt-react ---------------- ( hooks, providers, wrappers ) --> │ │
34
+ └───────────┘ │ │
35
+ ┌─────────┐ │ │
36
+ │ vdt-api ------------------------- ( API js Promises ) ------> │ │
37
+ └─────────┘ │ │
38
+ ┌────────────────┐ │ │
39
+ │ vdt-materialui -- (Customized Material UI React library) ---> │ │
40
+ └────────────────┘ │ Your │
41
+ ┌─── player components ──┐ │ SPA │
42
+ │┌───────────────────────┐ │ │
43
+ open-source player packages --> ││ vdt-videojs-react ---> │ │
44
+ │└───────────────────────┘ │ │
45
+ ┌─────────────┐ │┌───────────────────────┐ │ │
46
+ │ vdt-videojs ------------------> ││ vdt-videojs-vue (?) ---> │ │
47
+ └─────────────┘ │└───────────────────────┘ └───────┘
48
+ (pure js) └ wrapped for frameworks ┘
49
+
50
+ ```
51
+
52
+ vdt-videojs sets out to build a pure javascript video player on top of [video.js](https://videojs.com) and delivers more features with a "familiar" user interface / experience. There is an every-so-often manually deployed [live demo here](https://vdt-js-player.netlify.app/).
53
+
54
+ vdt-videojs is written in ES6 Javascript and has minimal dependencies; It's wrapable for supported frameworks.
55
+
56
+ Additionally vdt-videojs package exports other pure js components closely related to Player (SeekBar, TimeCodeDisplay, ExternalControls and others) for
57
+ use with react / other frameworks within their respective wrappers.
58
+
59
+ See the [vdt-videojs-react](./?path=/story/vdt-videojs-react-videoplayer--basic) package for use with React.
@@ -0,0 +1,59 @@
1
+ import { Meta } from '@storybook/addon-docs';
2
+
3
+ <Meta
4
+ title="vdt-videojs/Player Menu/Class Methods"
5
+ parameters={{
6
+ viewMode: 'docs',
7
+ previewTabs: {
8
+ canvas: { hidden: true },
9
+ },
10
+ }}
11
+ />
12
+
13
+ ## Class Methods
14
+
15
+ Menu is initialized at `player.menu`, so you can access
16
+ the Menu class instance methods via `player.menu.methodName()`.
17
+
18
+ <br />
19
+ <table>
20
+ <thead>
21
+ <tr>
22
+ <th>Method</th>
23
+ <th>Description</th>
24
+ <th>Associated hotkey</th>
25
+ </tr>
26
+ </thead>
27
+ <tbody>
28
+ <tr>
29
+ <td>.open()</td>
30
+ <td>Open menu</td>
31
+ <td>N</td>
32
+ </tr>
33
+ <tr>
34
+ <td>.close()</td>
35
+ <td>Close menu</td>
36
+ <td>ESC, N</td>
37
+ </tr>
38
+ <tr>
39
+ <td>.toggle()</td>
40
+ <td>Toggle open / close</td>
41
+ <td>N</td>
42
+ </tr>
43
+ <tr>
44
+ <td>.up()</td>
45
+ <td>Go up to main level</td>
46
+ <td />
47
+ </tr>
48
+ <tr>
49
+ <td>.render()</td>
50
+ <td>Update selected items in main level</td>
51
+ <td />
52
+ </tr>
53
+ <tr>
54
+ <td>.opened</td>
55
+ <td>Getter property (bool) - use this to get the state of menu</td>
56
+ <td />
57
+ </tr>
58
+ </tbody>
59
+ </table>
package/src/menu.js CHANGED
@@ -4,7 +4,6 @@
4
4
  /* eslint-disable max-classes-per-file */
5
5
  import mousetrap from 'mousetrap';
6
6
 
7
-
8
7
  const constants = Object.freeze({
9
8
  className: 'vdt-menu',
10
9
  menuClassName: 'menu',
@@ -21,7 +20,6 @@ const constants = Object.freeze({
21
20
  },
22
21
  });
23
22
 
24
-
25
23
  const CSS = () => `
26
24
  .${constants.menuClassName}{
27
25
  position: relative;
@@ -149,19 +147,19 @@ class MenuDisplayItem {
149
147
  this.container = document.createElement('tr');
150
148
  this.container.className = classNames.join(' ');
151
149
 
152
-
153
- this.props.target && this.props.target.appendChild(this.container);
150
+ if (this.props.target) this.props.target.appendChild(this.container);
154
151
 
155
152
  // bind click
156
153
  this.container.onclick = (event) => {
157
- this.props.onClick && this.props.onClick(event);
154
+ if (this.props.onClick) this.props.onClick(event);
158
155
  };
159
156
 
160
157
  this.render();
161
158
  }
162
159
 
163
160
  render() {
164
- if (this.props.items) { // will transition to 2nd level
161
+ if (this.props.items) {
162
+ // will transition to 2nd level
165
163
  this.container.innerHTML = `
166
164
  <td class="title"></td>
167
165
  <td class="subtitle"></td>
@@ -174,10 +172,12 @@ class MenuDisplayItem {
174
172
  }
175
173
 
176
174
  const titleNode = this.container.getElementsByClassName('title')[0];
177
- const subtitleNode = (this.props.items) ? this.container.getElementsByClassName('subtitle')[0] : false;
175
+ const subtitleNode = this.props.items
176
+ ? this.container.getElementsByClassName('subtitle')[0]
177
+ : false;
178
178
 
179
179
  titleNode.textContent = this.props.title;
180
- subtitleNode && (subtitleNode.textContent = this.props.subtitle);
180
+ if (subtitleNode) subtitleNode.textContent = this.props.subtitle;
181
181
  }
182
182
  }
183
183
 
@@ -213,8 +213,7 @@ export default class Menu {
213
213
 
214
214
  // shadow node encapsulates style and prevents css collisions
215
215
  this.shadow = this.container.attachShadow({ mode: 'open' });
216
- this.props.target && this.props.target.appendChild(this.container);
217
-
216
+ if (this.props.target) this.props.target.appendChild(this.container);
218
217
 
219
218
  // node for menu itself
220
219
  this.menuContainer = document.createElement('div');
@@ -230,7 +229,8 @@ export default class Menu {
230
229
  }
231
230
  }
232
231
 
233
- draw() { // first draw
232
+ draw() {
233
+ // first draw
234
234
  const mainDiv = document.createElement('div');
235
235
  mainDiv.className = 'level-1';
236
236
  this.mainLevel = document.createElement('table');
@@ -240,12 +240,13 @@ export default class Menu {
240
240
  const subDiv = document.createElement('div');
241
241
  subDiv.className = 'level-2';
242
242
  this.subLvlTitle = document.createElement('h3');
243
- this.subLvlTitle.onclick = () => { this.up(); };
243
+ this.subLvlTitle.onclick = () => {
244
+ this.up();
245
+ };
244
246
  subDiv.appendChild(this.subLvlTitle);
245
247
  this.secondaryLevel = document.createElement('table');
246
248
  subDiv.appendChild(this.secondaryLevel);
247
249
 
248
-
249
250
  this.menuContainer.appendChild(mainDiv);
250
251
  this.menuContainer.appendChild(subDiv);
251
252
 
@@ -269,11 +270,12 @@ export default class Menu {
269
270
  this.render();
270
271
 
271
272
  this.menuContainer.classList.add('open');
272
- this.props.onOpen && this.props.onOpen();
273
+ if (this.props.onOpen) this.props.onOpen();
273
274
  this.state.opened = true;
274
275
 
275
276
  // close the menu when user clicks outside it
276
277
  if (!this.handleClicksWhenMenuOpened) {
278
+ // eslint-disable-next-line func-names
277
279
  this.handleClicksWhenMenuOpened = function (event) {
278
280
  if (this.state.opened) {
279
281
  event.stopPropagation();
@@ -295,10 +297,11 @@ export default class Menu {
295
297
  this.menuContainer.classList.remove('open');
296
298
  this.state.opened = false;
297
299
 
298
- this.handleClicksWhenMenuOpenedTimeout && clearTimeout(this.handleClicksWhenMenuOpenedTimeout);
300
+ if (this.handleClicksWhenMenuOpenedTimeout)
301
+ clearTimeout(this.handleClicksWhenMenuOpenedTimeout);
299
302
  document.removeEventListener('click', this.handleClicksWhenMenuOpened);
300
303
 
301
- this.props.onClose && this.props.onClose();
304
+ if (this.props.onClose) this.props.onClose();
302
305
 
303
306
  mousetrap.unbind('esc');
304
307
  }
@@ -311,7 +314,8 @@ export default class Menu {
311
314
  }
312
315
  }
313
316
 
314
- up() { // go to level 1
317
+ up() {
318
+ // go to level 1
315
319
  this.menuContainer.classList.remove(constants.subLvlClassName);
316
320
  this.render();
317
321
  }
@@ -333,7 +337,7 @@ export default class Menu {
333
337
  onClick: (event) => {
334
338
  this.handleSubItemSelected(event, menuItem);
335
339
  },
336
- selected: (index === activeIndex), // mark selected
340
+ selected: index === activeIndex, // mark selected
337
341
  });
338
342
 
339
343
  subItemRefs.push(displayItem);
@@ -344,7 +348,7 @@ export default class Menu {
344
348
 
345
349
  handleSubItemSelected(event, item) {
346
350
  this.close();
347
- item.onClick && item.onClick(event, item);
351
+ if (item.onClick) item.onClick(event, item);
348
352
  this.up();
349
353
  }
350
354