diff options
Diffstat (limited to 'client/src/assets/player/shared/playlist/playlist-menu.ts')
-rw-r--r-- | client/src/assets/player/shared/playlist/playlist-menu.ts | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/client/src/assets/player/shared/playlist/playlist-menu.ts b/client/src/assets/player/shared/playlist/playlist-menu.ts new file mode 100644 index 000000000..1ec9ac804 --- /dev/null +++ b/client/src/assets/player/shared/playlist/playlist-menu.ts | |||
@@ -0,0 +1,137 @@ | |||
1 | import videojs from 'video.js' | ||
2 | import { VideoPlaylistElement } from '@shared/models' | ||
3 | import { PlaylistPluginOptions } from '../../types' | ||
4 | import { PlaylistMenuItem } from './playlist-menu-item' | ||
5 | |||
6 | const Component = videojs.getComponent('Component') | ||
7 | |||
8 | class PlaylistMenu extends Component { | ||
9 | private menuItems: PlaylistMenuItem[] | ||
10 | |||
11 | constructor (player: videojs.Player, options?: PlaylistPluginOptions) { | ||
12 | super(player, options as any) | ||
13 | |||
14 | const self = this | ||
15 | |||
16 | function userInactiveHandler () { | ||
17 | self.close() | ||
18 | } | ||
19 | |||
20 | this.el().addEventListener('mouseenter', () => { | ||
21 | this.player().off('userinactive', userInactiveHandler) | ||
22 | }) | ||
23 | |||
24 | this.el().addEventListener('mouseleave', () => { | ||
25 | this.player().one('userinactive', userInactiveHandler) | ||
26 | }) | ||
27 | |||
28 | this.player().on('click', event => { | ||
29 | let current = event.target as HTMLElement | ||
30 | |||
31 | do { | ||
32 | if ( | ||
33 | current.classList.contains('vjs-playlist-menu') || | ||
34 | current.classList.contains('vjs-playlist-button') | ||
35 | ) { | ||
36 | return | ||
37 | } | ||
38 | |||
39 | current = current.parentElement | ||
40 | } while (current) | ||
41 | |||
42 | this.close() | ||
43 | }) | ||
44 | } | ||
45 | |||
46 | createEl () { | ||
47 | this.menuItems = [] | ||
48 | |||
49 | const options = this.getOptions() | ||
50 | |||
51 | const menu = super.createEl('div', { | ||
52 | className: 'vjs-playlist-menu', | ||
53 | innerHTML: '', | ||
54 | tabIndex: -1 | ||
55 | }) | ||
56 | |||
57 | const header = super.createEl('div', { | ||
58 | className: 'header' | ||
59 | }) | ||
60 | |||
61 | const headerLeft = super.createEl('div') | ||
62 | |||
63 | const leftTitle = super.createEl('div', { | ||
64 | innerHTML: options.playlist.displayName, | ||
65 | className: 'title' | ||
66 | }) | ||
67 | |||
68 | const playlistChannel = options.playlist.videoChannel | ||
69 | const leftSubtitle = super.createEl('div', { | ||
70 | innerHTML: playlistChannel | ||
71 | ? this.player().localize('By {1}', [ playlistChannel.displayName ]) | ||
72 | : '', | ||
73 | className: 'channel' | ||
74 | }) | ||
75 | |||
76 | headerLeft.appendChild(leftTitle) | ||
77 | headerLeft.appendChild(leftSubtitle) | ||
78 | |||
79 | const tick = super.createEl('div', { | ||
80 | className: 'cross' | ||
81 | }) | ||
82 | tick.addEventListener('click', () => this.close()) | ||
83 | |||
84 | header.appendChild(headerLeft) | ||
85 | header.appendChild(tick) | ||
86 | |||
87 | const list = super.createEl('ol') | ||
88 | |||
89 | for (const playlistElement of options.elements) { | ||
90 | const item = new PlaylistMenuItem(this.player(), { | ||
91 | element: playlistElement, | ||
92 | onClicked: () => this.onItemClicked(playlistElement) | ||
93 | }) | ||
94 | |||
95 | list.appendChild(item.el()) | ||
96 | |||
97 | this.menuItems.push(item) | ||
98 | } | ||
99 | |||
100 | menu.appendChild(header) | ||
101 | menu.appendChild(list) | ||
102 | |||
103 | return menu | ||
104 | } | ||
105 | |||
106 | update () { | ||
107 | const options = this.getOptions() | ||
108 | |||
109 | this.updateSelected(options.getCurrentPosition()) | ||
110 | } | ||
111 | |||
112 | open () { | ||
113 | this.player().addClass('playlist-menu-displayed') | ||
114 | } | ||
115 | |||
116 | close () { | ||
117 | this.player().removeClass('playlist-menu-displayed') | ||
118 | } | ||
119 | |||
120 | updateSelected (newPosition: number) { | ||
121 | for (const item of this.menuItems) { | ||
122 | item.setSelected(item.getElement().position === newPosition) | ||
123 | } | ||
124 | } | ||
125 | |||
126 | private getOptions () { | ||
127 | return this.options_ as PlaylistPluginOptions | ||
128 | } | ||
129 | |||
130 | private onItemClicked (element: VideoPlaylistElement) { | ||
131 | this.getOptions().onItemClicked(element) | ||
132 | } | ||
133 | } | ||
134 | |||
135 | Component.registerComponent('PlaylistMenu', PlaylistMenu) | ||
136 | |||
137 | export { PlaylistMenu } | ||