├── .gitignore
├── package.json
├── dilation-player.template.audio.html
├── dilation-player.template.html
├── config.js
├── plugins
└── dilation-player.plugin.ads.js
├── index.html
├── README.md
├── dilation-player.css
└── dilation-player.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dilation-player",
3 | "version": "1.0.0",
4 | "description": "The player for video html5",
5 | "main": "dilation-player.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/cobonla/DilationPlayer.git"
12 | },
13 | "keywords": [
14 | "video player",
15 | "free player",
16 | "html5 player",
17 | "free video player",
18 | "custom video player",
19 | "stream video player",
20 | "stream video"
21 | ],
22 | "author": "Cobonla",
23 | "license": "MIT license",
24 | "bugs": {
25 | "url": "https://github.com/cobonla/DilationPlayer/issues"
26 | },
27 | "homepage": "https://github.com/cobonla/DilationPlayer#readme"
28 | }
29 |
--------------------------------------------------------------------------------
/dilation-player.template.audio.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
10 |
13 |
16 |
19 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
35 |
36 |
51 |
52 |
--------------------------------------------------------------------------------
/dilation-player.template.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
10 |
13 |
16 |
19 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
35 |
36 |
51 |
52 |
--------------------------------------------------------------------------------
/config.js:
--------------------------------------------------------------------------------
1 | __dp.defaultConfig = {
2 | elements: {
3 | object: null,
4 | container: '.dp',
5 | video: '.dp-video',
6 | audio: '.dp-audio',
7 | logo: '.dp-logo',
8 | progress: '.dp-progress',
9 | progressLoading: '.dp-progress .dp-loading',
10 | progressPlaying: '.dp-progress .dp-playing',
11 | progressHoverTooltipText: '.dp-progress-tooltip-text',
12 | progressHoverTooltipImage: '.dp-progress-tooltip-image',
13 | control: '.dp-control',
14 | button: '.dp-button',
15 | controlPlayPause: '.dp-btn-play',
16 | controlFullScreen: '.dp-btn-fullscreen',
17 | controlLargeScreen: '.dp-btn-largescreen',
18 | controlVolume: '.dp-btn-volume',
19 | controlVolumeTooltip: '.dp-volume-tooltip',
20 | controlVolumeRange: '.dp-volume-range',
21 | controlTimer: '.dp-timer',
22 | modal: '.dp-modal',
23 | loaderModal: '.dp-modal-loader',
24 | loaderModalIcon: '.dp-modal-loader-icon',
25 | playerModal: '.dp-modal-player',
26 | playerModalIcon: '.dp-modal-player-icon',
27 | menu: '.dp-menu',
28 | menuList: '.dp-menu-list',
29 | menuItem: '.dp-menu-item',
30 | menuItemLoop: '.dp-menu-item-loop',
31 | menuItemCopyUrl: '.dp-menu-item-copy-url',
32 | ads: '.dp-ads',
33 | adsItem: '.dp-ads .dp-ads-item',
34 | adsContent: '.dp-ads .dp-ads-content',
35 | adsClose: '.dp-ads .dp-ads-close',
36 | },
37 | icons: {
38 | loaderModal: '',
39 | playerModal: '',
40 | fullScreen: '',
41 | actualScreen: '',
42 | largeScreen: '',
43 | smallScreen: '',
44 | pause: '',
45 | play: '',
46 | volumeMute: '',
47 | volume1: '',
48 | volume2: '',
49 | volume3: '',
50 | close: '[X]'
51 | },
52 | volume: 100,
53 | view: {
54 | content: null,
55 | import: null
56 | },
57 | sources: {},
58 | logo: {
59 | height: '10%',
60 | rate: 1
61 | },
62 | size: {
63 | width: '100%',
64 | rate: 2 / 3
65 | },
66 | largeScreen: false,
67 | locale: 'en',
68 | menu: {},
69 | poster: null,
70 | schedules: [],
71 | type: 'video',
72 | plugins: {},
73 | startAt: 0,
74 | preview: {}
75 | };
--------------------------------------------------------------------------------
/plugins/dilation-player.plugin.ads.js:
--------------------------------------------------------------------------------
1 | // ====================================================
2 | // Plugin {DPAds}
3 | // ====================================================
4 | class DPAdsPlugin extends DPBase {
5 | /**
6 | * constructor
7 | * @param app
8 | */
9 | constructor(app) {
10 | super();
11 | this.app = app;
12 | this.currentSetting = {};
13 | this.usedType = [];
14 | }
15 |
16 | /**
17 | * Run
18 | * @return {DilationPlayerPluginsAds}
19 | */
20 | init() {
21 | let icon = this.app.config.get('icons.close');
22 | let close = this.app.config.el('elements.adsClose');
23 | let instance = this;
24 | let runner = this.app.config.runner(true).node();
25 | this.isPlay = !runner.paused;
26 | this.runningAds = null;
27 | this.types = {full: 'full', line: 'line', require: 'require'};
28 |
29 | // Event when click on button close
30 | close.listen('click', function () {
31 | instance.close();
32 | });
33 |
34 | close.html(icon);
35 |
36 | function __callResize(){
37 | instance.resize();
38 | }
39 |
40 | __dp.node(window).listen('resize', __callResize);
41 |
42 | // Event when control change
43 | this.app.event.listen('dp.control.hide', __callResize)
44 | .listen('dp.control.show', __callResize);
45 |
46 | return this;
47 | }
48 |
49 | /**
50 | * Resize
51 | */
52 | resize(){
53 | if (this.currentSetting.type === 'line') {
54 | let control = this.app.config.el('elements.control');
55 | let ads = this.app.config.el('elements.ads');
56 |
57 | if (control.hasClass('active')) {
58 | let height = control.height();
59 | ads.css('bottom', (height + 1)+'px');
60 | } else {
61 | ads.css('bottom', '10px');
62 | }
63 | }
64 | }
65 |
66 | /**
67 | * Run
68 | * @return {DilationPlayerPluginsAds}
69 | */
70 | open(content, conf) {
71 | let ads = this.app.config.el('elements.ads');
72 | let adsClose = this.app.config.el('elements.adsClose');
73 | let adsContent = this.app.config.el('elements.adsContent');
74 | let runner = this.app.config.runner(true).node();
75 | let instance = this;
76 | this.isPlay = !runner.paused;
77 |
78 | if (conf !== undefined) {
79 | this.currentSetting = this.or(conf, {});
80 | }
81 |
82 | this.currentSetting.type = this.or(this.currentSetting.type, this.types.line);
83 |
84 | ads.removeClass(this.types.line)
85 | .removeClass(this.types.full)
86 | .removeClass(this.types.require);
87 |
88 | ads.addClass(this.currentSetting.type);
89 | ads.active(true);
90 |
91 | if (content !== undefined) {
92 | adsContent.html(content);
93 | }
94 |
95 | if (this.currentSetting.type === this.types.require) {
96 | this.app.source.pause();
97 | adsClose.active(false);
98 |
99 | this.runningAds = window.setTimeout(function(){
100 | instance.close();
101 | }, this.currentSetting.time);
102 | } else if (this.currentSetting.type === this.types.full) {
103 | this.app.source.pause();
104 | adsClose.active(true);
105 | } else {
106 | adsClose.active(true);
107 | }
108 |
109 | this.resize();
110 |
111 | return this;
112 | }
113 |
114 | /**
115 | * Close
116 | * @return {DilationPlayerPluginsAds}
117 | */
118 | close(){
119 | let ads = this.app.config.el('elements.ads');
120 |
121 | window.clearTimeout(this.runningAds);
122 | ads.active(false);
123 |
124 | if ((this.currentSetting.type === this.types.require
125 | || this.currentSetting.type === this.types.full)
126 | && this.isPlay) {
127 | this.app.source.play();
128 | }
129 | }
130 | }
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Video Demo
5 |
6 |
8 |
10 |
11 |
12 |
13 |
19 |
20 |
21 |
22 |
23 |
25 |
91 |
92 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DilationPlayer
2 |
3 | DilationPlayer is object, It provide methods to play video/audio. **[Video demo](https://dilationplayer.cobonla.org/)**
4 |
5 | **Using**
6 |
7 | Import file DilationPlayer.js to your html page.
8 |
9 | Html page:
10 |
11 | ```
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
22 |
23 | ```
24 |
25 | Then create new object.
26 |
27 | ```
28 | var player = new DilationPlayer('#video-container', json_config);
29 | ```
30 |
31 | Then it auto apply to your elements. If you want to custom, then change **json_config** value bellow.
32 |
33 | ```
34 | {
35 | elements: {
36 | object: null,
37 | container: '.dp',
38 | video: '.dp-video',
39 | audio: '.dp-audio',
40 | logo: '.dp-logo',
41 | progress: '.dp-progress',
42 | progressLoading: '.dp-progress .dp-loading',
43 | progressPlaying: '.dp-progress .dp-playing',
44 | progressHoverTooltipText: '.dp-progress-tooltip-text',
45 | progressHoverTooltipImage: '.dp-progress-tooltip-image',
46 | control: '.dp-control',
47 | button: '.dp-button',
48 | controlPlayPause: '.dp-btn-play',
49 | controlFullScreen: '.dp-btn-fullscreen',
50 | controlLargeScreen: '.dp-btn-largescreen',
51 | controlVolume: '.dp-btn-volume',
52 | controlVolumeTooltip: '.dp-volume-tooltip',
53 | controlVolumeRange: '.dp-volume-range',
54 | controlTimer: '.dp-timer',
55 | modal: '.dp-modal',
56 | loaderModal: '.dp-modal-loader',
57 | loaderModalIcon: '.dp-modal-loader-icon',
58 | playerModal: '.dp-modal-player',
59 | playerModalIcon: '.dp-modal-player-icon',
60 | menu: '.dp-menu',
61 | menuList: '.dp-menu-list',
62 | menuItem: '.dp-menu-item',
63 | menuItemLoop: '.dp-menu-item-loop',
64 | menuItemCopyUrl: '.dp-menu-item-copy-url',
65 | ads: '.dp-ads',
66 | adsItem: '.dp-ads .dp-ads-item',
67 | adsContent: '.dp-ads .dp-ads-content',
68 | adsClose: '.dp-ads .dp-ads-close',
69 | },
70 | icons: {
71 | loaderModal: '',
72 | playerModal: '',
73 | fullScreen: '',
74 | actualScreen: '',
75 | largeScreen: '',
76 | smallScreen: '',
77 | pause: '',
78 | play: '',
79 | volumeMute: '',
80 | volume1: '',
81 | volume2: '',
82 | volume3: '',
83 | close: '[X]'
84 | },
85 | volume: 100,
86 | view: {
87 | content: null,
88 | import: null
89 | },
90 | sources: {},
91 | logo: {
92 | height: '10%',
93 | rate: 1
94 | },
95 | size: {
96 | width: '100%',
97 | rate: 2 / 3
98 | },
99 | largeScreen: false,
100 | locale: 'en',
101 | menu: {},
102 | poster: null,
103 | schedules: [],
104 | type: 'video',
105 | plugins: {},
106 | startAt: 0
107 | }
108 | ```
109 |
110 | Example, you would like to show video without **logo** then:
111 |
112 | ```
113 | var player = new DilationPlayer('#video-container', {
114 | logo: false
115 | });
116 | ```
117 |
118 | Or you want to show the poster before start video then:
119 |
120 | ```
121 | var player = new DilationPlayer('#video-container', {
122 | poster: 'https://mywebsite.com/poster.png'
123 | });
124 | ```
125 |
126 | Full source code after config:
127 |
128 | ```
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
139 |
145 |
146 | ```
147 |
148 | OK, now it's working!
149 |
--------------------------------------------------------------------------------
/dilation-player.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | padding: 0;
3 | margin: 0;
4 | height: 100%;
5 | width: 100%;
6 | position: relative;
7 | }
8 |
9 | .hidden-cursor {
10 | /*cursor: url("blank.cur"),auto !important;*/
11 | }
12 |
13 | .notransition {
14 | -webkit-transition: none !important;
15 | -moz-transition: none !important;
16 | -o-transition: none !important;
17 | transition: none !important;
18 | }
19 |
20 | .dp {
21 | width: 100%;
22 | height: 100%;
23 | background-color: #000;
24 | position: relative;
25 | overflow: hidden;
26 | }
27 |
28 | .dp .dp-video,
29 | .dp .dp-audio{
30 | width: 100%;
31 | height: 100%;
32 | position: absolute;
33 | top: 0
34 | }
35 |
36 | /* ============ CSS for logo =============== */
37 | .dp .dp-logo {
38 | position: absolute;
39 | top: 4%;
40 | left: 3%;
41 | height: 7%;
42 | z-index: 9;
43 | opacity: 0.7;
44 | cursor: pointer;
45 | background-position: left;
46 | background-size: contain;
47 | background-repeat: no-repeat;
48 | display: none;
49 | }
50 |
51 | .dp .dp-logo.active{
52 | display: block;
53 | }
54 |
55 | .dp .dp-logo:hover {
56 | opacity: 1
57 | }
58 |
59 | /* ============ CSS for menu =================*/
60 | .dp-menu {
61 | position: absolute;
62 | top: 0;
63 | left: 0;
64 | width: 100%;
65 | height: 100%;
66 | z-index: 10;
67 | visibility: hidden;
68 | opacity: 0;
69 | transition: visibility 0.1s, opacity 0.1s, background-color 0.2s linear;
70 | }
71 |
72 | .dp-menu.active {
73 | visibility: visible;
74 | opacity: 1;
75 | }
76 |
77 | .dp-menu .dp-menu-list {
78 | background-color: rgba(51, 47, 47, 0.75);
79 | color: #fff;
80 | min-width: 100px;
81 | position: fixed;
82 | }
83 |
84 | .dp-menu .dp-menu-list .dp-menu-item {
85 | padding: 10px 10px 10px 20px;
86 | cursor: pointer
87 | }
88 |
89 | .dp-menu .dp-menu-list .dp-menu-item:hover {
90 | background-color: rgba(0, 0, 0, 0.3);
91 | }
92 |
93 | .dp-menu .dp-menu-list .dp-menu-item:before {
94 | content: "✓";
95 | color: #fff;
96 | margin-left: -15px;
97 | margin-right: 10px;
98 | font-size: 0.8em;
99 | visibility: hidden;
100 | }
101 |
102 | .dp-menu .dp-menu-list .dp-menu-item.active:before {
103 | visibility: visible;
104 | }
105 |
106 | /* ============ CSS for controls =============== */
107 | .dp .dp-control {
108 | position: absolute;
109 | bottom: 0;
110 | left: 0;
111 | width: 100%;
112 | z-index: 9;
113 | height: 7%;
114 | min-height: 40px;
115 | max-height: 50px;
116 | transform: translateY(88%);
117 | transition: all 0.2s ease;
118 | background-color: transparent;
119 | background-image: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.8));
120 | }
121 |
122 | .dp .dp-control.active {
123 | transform: translateY(0);
124 | }
125 |
126 | /* CSS for PROGRESS */
127 | .dp .dp-control .dp-progress {
128 | width: 96%;
129 | position: relative;
130 | height: 12%;
131 | cursor: pointer;
132 | margin: 0 auto;
133 | z-index: 9;
134 | }
135 |
136 | .dp .dp-control .dp-progress .dp-line {
137 | width: 100%;
138 | height: 40%;
139 | transition: all 0.2s linear;
140 | position: absolute;
141 | bottom: 0px;
142 | left: 0px;
143 | }
144 |
145 | .dp .dp-control .dp-progress:hover .dp-line {
146 | height: 70%;
147 | }
148 |
149 | .dp .dp-control .dp-progress .dp-line > div {
150 | height: 100%;
151 | width: 100%;
152 | position: absolute;
153 | bottom: 0px;
154 | left: 0px;
155 | }
156 |
157 | .dp .dp-control .dp-progress .dp-line .dp-playing {
158 | background-color: #FF5722;
159 | z-index: 3;
160 | }
161 |
162 | .dp .dp-control .dp-progress .dp-line .dp-loading {
163 | background-color: rgba(255, 255, 255, 0.5);
164 | width: 100%;
165 | z-index: 1;
166 | }
167 |
168 | .dp .dp-control .dp-progress .dp-progress-tooltip-text {
169 | display: none;
170 | background-color: black;
171 | color: #fff;
172 | text-align: center;
173 | padding: 1px 5px;
174 | position: absolute;
175 | z-index: 1;
176 | top: -1.8em;
177 | transform: translateX(-50%);
178 | }
179 |
180 | /*.dp .dp-control .dp-progress .dp-progress-tooltip-text::after {*/
181 | /*content: '';*/
182 | /*display: block;*/
183 | /*position: absolute;*/
184 | /*top: 100%;*/
185 | /*left: 50%;*/
186 | /*transform: translateX(-50%);*/
187 | /*width: 0;*/
188 | /*height: 0;*/
189 | /*border-style: solid;*/
190 | /*border-width: 4px 5px 0 5px;*/
191 | /*border-color: black transparent transparent transparent;*/
192 | /*}*/
193 |
194 | .dp .dp-control .dp-progress:hover .dp-progress-tooltip-text.active {
195 | display: inline-block;
196 | }
197 |
198 | .dp .dp-control .dp-progress .dp-progress-tooltip-image {
199 | display: none;
200 | background: rgba(0, 0, 0, 0.6) no-repeat center;
201 | color: #fff;
202 | text-align: center;
203 | border: 1px solid #000;
204 | position: absolute;
205 | z-index: 1;
206 | top: calc(-58px + -1.8em);
207 | transform: translateX(-50%);
208 | width: 100px;
209 | height: 80px;
210 | background-size: cover;
211 | border-radius: 2px;
212 | }
213 |
214 | .dp .dp-control .dp-progress:hover .dp-progress-tooltip-image.active {
215 | display: inline-block;
216 | }
217 |
218 | /* ======================= CSS for button ========================== */
219 | .dp .dp-control .dp-button {
220 | height: 88%;
221 | /*background-color: rgba(0, 0, 0, 0.5);*/
222 | width: 100%;
223 | position: relative;
224 | }
225 |
226 | .dp .dp-control .dp-button > div {
227 | height: 100%;
228 | position: relative;
229 | transition: all 0.2s linear;
230 | width: 96%;
231 | margin: auto;
232 | }
233 |
234 | .dp .dp-control .dp-button > div:after,
235 | .dp .dp-control .dp-button .dp-group:after {
236 | clear: both;
237 | content: "";
238 | display: block;
239 | }
240 |
241 | .dp .dp-control .dp-button .dp-group {
242 | height: 100%;
243 | position: relative;
244 | float: left;
245 | display: inline-block;
246 | }
247 |
248 | .dp .dp-control .dp-button button {
249 | background-color: transparent;
250 | color: #fff;
251 | border: none;
252 | outline: 0;
253 | font-size: 1.3em;
254 | cursor: pointer;
255 | height: 100%;
256 | transition: opacity .1s cubic-bezier(0.4, 0.0, 1, 1);
257 | line-height: inherit;
258 | float: left;
259 | padding: 0;
260 | }
261 |
262 | .dp .dp-control .dp-button button path {
263 | fill: #ffffff;
264 | }
265 |
266 | .dp .dp-control .dp-button button.dp-btn-largescreen,
267 | .dp .dp-control .dp-button button.dp-btn-fullscreen {
268 | float: right;
269 | }
270 |
271 | .dp .dp-control .dp-button button.dp-timer {
272 | font-size: 0.8em;
273 | }
274 |
275 | .dp .dp-control .dp-button .dp-volume-tooltip {
276 | transition: all 0.2s linear;
277 | opacity: 0;
278 | width: 0;
279 | display: inline-block;
280 | padding-right: 5px;
281 | border-right: 1px solid #525252;
282 | height: 100%;
283 | overflow: hidden;
284 | }
285 |
286 | .dp .dp-control .dp-button .dp-group:hover .dp-volume-tooltip {
287 | width: 100px;
288 | opacity: 1;
289 | box-sizing: border-box;
290 | }
291 |
292 | /* Custom range */
293 | .dp .dp-control .dp-button .dp-group .dp-volume-range {
294 | width: 90px;
295 | top: 40%;
296 | position: absolute;
297 | -webkit-transform: translateY(-30%);
298 | -ms-transform: translateY(-30%);
299 | transform: translateY(-30%);
300 | opacity: 0.7;
301 | -webkit-transition: .2s;
302 | transition: opacity .2s;
303 | height: 7%;
304 | background: #fff;
305 | outline: none;
306 | -webkit-appearance: none;
307 | }
308 |
309 | .dp .dp-control .dp-button .dp-group .dp-volume-range:hover {
310 | opacity: 1;
311 | }
312 |
313 | .dp .dp-control .dp-button .dp-group .dp-volume-range::-webkit-slider-thumb {
314 | -webkit-appearance: none;
315 | appearance: none;
316 | width: 10px;
317 | height: 10px;
318 | background: #FF5722;
319 | cursor: pointer;
320 | border-radius: 50%;
321 | }
322 |
323 | .dp .dp-control .dp-button .dp-group .dp-volume-range::-moz-range-thumb {
324 | width: 10px;
325 | height: 10px;
326 | background: #FF5722;
327 | cursor: pointer;
328 | border-radius: 50%;
329 | }
330 |
331 | /* CSS for purdah */
332 | .dp .dp-modal {
333 | position: absolute;
334 | top: 0;
335 | left: 0;
336 | width: 100%;
337 | height: 100%;
338 | background-color: rgba(0, 0, 0, 0.5);
339 | z-index: 8;
340 | display: none;
341 | }
342 |
343 | .dp .dp-modal.active {
344 | display: block;
345 | }
346 |
347 | .dp .dp-modal .dp-modal-icon {
348 | text-align: center;
349 | position: relative;
350 | top: 45%;
351 | -webkit-transform: translateY(-50%);
352 | -ms-transform: translateY(-50%);
353 | transform: translateY(-50%);
354 | color: #fff;
355 | margin: auto;
356 | display: block;
357 | width: 100px;
358 | font-size: 2em;
359 | }
360 |
361 | .dp .dp-modal .dp-modal-player-icon > * {
362 | border: 2px solid #fff;
363 | border-radius: 50%;
364 | background-color: rgba(0, 0, 0, 0.3);
365 | padding: 2px 1px 2px 3px;
366 | width: 40%;
367 | color: #fff;
368 | }
369 |
370 | .dp .dp-modal path {
371 | fill: #ffffff;
372 | }
373 |
374 | /* ======================== CSS for ADS ============== */
375 | .dp .dp-ads {
376 | z-index: 9;
377 | display: none;
378 | transition: all .2s;
379 | }
380 |
381 | .dp .dp-ads.active {
382 | display: block;
383 | }
384 |
385 | .dp .dp-ads.line {
386 | height: 17%;
387 | min-height: 40px;
388 | max-height: 100px;
389 | position: absolute;
390 | bottom: 0;
391 | left: 0;
392 | width: 100%;
393 | }
394 |
395 | .dp .dp-ads.full,
396 | .dp .dp-ads.require{
397 | position: absolute;
398 | top: 0;
399 | left: 0;
400 | width: 100%;
401 | height: 100%;
402 | z-index: 9999;
403 | }
404 |
405 | .dp .dp-ads .dp-ads-item{
406 | margin: auto;
407 | position: relative;
408 | display: block;
409 | max-width: 100%;
410 | height: 100%;
411 | }
412 |
413 | .dp .dp-ads.line .dp-ads-item{
414 | width: fit-content;
415 | }
416 |
417 | .dp .dp-ads.full .dp-ads-item,
418 | .dp .dp-ads.require .dp-ads-item{
419 | width: 100%;
420 | }
421 |
422 | .dp .dp-ads .dp-ads-content {
423 | height: 100%;
424 | }
425 |
426 | .dp .dp-ads .dp-ads-close {
427 | position: absolute;
428 | top: 0;
429 | right: 0;
430 | background-color: #ffffff;
431 | outline: 0;
432 | cursor: pointer;
433 | border: none;
434 | color: #000;
435 | display: none;
436 | height: 17px;
437 | width: 17px;
438 | padding: 0;
439 | line-height: 0
440 | }
441 |
442 | .dp .dp-ads .dp-ads-close.active {
443 | display: inline-block;
444 | }
445 |
--------------------------------------------------------------------------------
/dilation-player.js:
--------------------------------------------------------------------------------
1 | let __dp = {
2 | pad: function (n, width, z) {
3 | z = z || '0';
4 | n = n + '';
5 | return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
6 | },
7 |
8 | parseTime: function (times) {
9 | if (times < 0) {
10 | times = 0;
11 | }
12 |
13 | let hours = Math.floor(times / 3600);
14 | let minutes = Math.floor((times - hours * 3600) / 60);
15 | let seconds = Math.floor(times - (minutes * 60 + hours * 3600));
16 | let format = (hours > 0 ? (this.pad(hours, 2) + ':') : '') + this.pad(minutes, 2) + ':' + this.pad(seconds, 2);
17 |
18 | return format;
19 | },
20 |
21 | node: function (element) {
22 | return new DPNode(element);
23 | },
24 |
25 | ready: function (call) {
26 | this.node(window).listen('load', call);
27 | }
28 | };
29 | __dp.defaultConfig = {
30 | elements: {
31 | object: null,
32 | container: '.dp',
33 | video: '.dp-video',
34 | audio: '.dp-audio',
35 | logo: '.dp-logo',
36 | progress: '.dp-progress',
37 | progressLoading: '.dp-progress .dp-loading',
38 | progressPlaying: '.dp-progress .dp-playing',
39 | progressHoverTooltipText: '.dp-progress-tooltip-text',
40 | progressHoverTooltipImage: '.dp-progress-tooltip-image',
41 | control: '.dp-control',
42 | button: '.dp-button',
43 | buttonIcon: '.dp-button button.dp-icon',
44 | controlPlayPause: '.dp-btn-play',
45 | controlFullScreen: '.dp-btn-fullscreen',
46 | controlLargeScreen: '.dp-btn-largescreen',
47 | controlVolume: '.dp-btn-volume',
48 | controlVolumeTooltip: '.dp-volume-tooltip',
49 | controlVolumeRange: '.dp-volume-range',
50 | controlTimer: '.dp-timer',
51 | modal: '.dp-modal',
52 | loaderModal: '.dp-modal-loader',
53 | loaderModalIcon: '.dp-modal-loader-icon',
54 | playerModal: '.dp-modal-player',
55 | playerModalIcon: '.dp-modal-player-icon',
56 | menu: '.dp-menu',
57 | menuList: '.dp-menu-list',
58 | menuItem: '.dp-menu-item',
59 | menuItemLoop: '.dp-menu-item-loop',
60 | menuItemCopyUrl: '.dp-menu-item-copy-url',
61 | ads: '.dp-ads',
62 | adsItem: '.dp-ads .dp-ads-item',
63 | adsContent: '.dp-ads .dp-ads-content',
64 | adsClose: '.dp-ads .dp-ads-close',
65 | },
66 | icons: {
67 | loaderModal: '',
68 | playerModal: '',
69 | fullScreen: '',
70 | actualScreen: '',
71 | largeScreen: '',
72 | smallScreen: '',
73 | pause: '',
74 | play: '',
75 | volumeMute: '',
76 | volume1: '',
77 | volume2: '',
78 | volume3: '',
79 | close: ''
80 | },
81 | volume: 100,
82 | view: {
83 | content: null,
84 | import: null
85 | },
86 | sources: {},
87 | logo: {
88 | height: '10%',
89 | rate: 1
90 | },
91 | size: {
92 | width: '100%',
93 | rate: 2 / 3
94 | },
95 | largeScreen: false,
96 | locale: 'en',
97 | menu: {},
98 | poster: null,
99 | schedules: [],
100 | type: 'video',
101 | plugins: {},
102 | startAt: 0,
103 | preview: {}
104 | };
105 | __dp.translateData = {
106 | en: {
107 | menu: {
108 | loop: 'Loop this video',
109 | copy_url: 'Copy video\'s url'
110 | },
111 |
112 | app: {
113 | loading: 'Loading...',
114 | not_support: 'This browser not support player'
115 | }
116 | },
117 | vi: {
118 | menu: {
119 | loop: 'Lặp video này',
120 | copy_url: 'Copy đường dẫn video'
121 | },
122 |
123 | app: {
124 | loading: 'Đang tải...',
125 | not_support: 'Trình duyệt không hỗ trợ player'
126 | }
127 | }
128 | };
129 |
130 | // ====================================================
131 | // Class {Base}
132 | // ====================================================
133 | class DPBase {
134 | /**
135 | * Check if value is undefined then return or
136 | * @param value
137 | * @param or
138 | * @return mixed
139 | */
140 | or(value, or) {
141 | return value === undefined ? or : value;
142 | }
143 | }
144 |
145 | // ====================================================
146 | // Class {DPNode}
147 | // ====================================================
148 | class DPNode extends DPBase {
149 | /**
150 | * Constructor
151 | * @param selector
152 | */
153 | constructor(selector) {
154 | super();
155 | this.setSelector(selector);
156 | }
157 |
158 | /**
159 | * Convert to array
160 | * @param selector
161 | * @return {string|Array|*[]}
162 | */
163 | convertToArray(selector) {
164 | if (selector instanceof NodeList) {
165 | for (var a = [], l = selector.length; l--; a[l] = selector[l]) ;
166 | selector = a;
167 | } else if (typeof selector !== 'string'
168 | && !(selector instanceof Array)) {
169 | selector = [selector];
170 | }
171 |
172 | return selector;
173 | }
174 |
175 | /**
176 | * Set selector
177 | * @param selector
178 | * @return {DPNode}
179 | */
180 | setSelector(selector) {
181 | this.selectors = this.convertToArray(selector);
182 |
183 | return this;
184 | }
185 |
186 | /**
187 | * Get selectors
188 | * @return {*[]|NodeListOf|*}
189 | */
190 | nodes() {
191 | if (typeof this.selectors === 'string') {
192 | let nodes = document.querySelectorAll(this.selectors);
193 | return this.convertToArray(nodes);
194 | }
195 |
196 | return this.selectors;
197 | }
198 |
199 | /**
200 | * Get selector
201 | * @return {*}
202 | */
203 | node() {
204 | if (typeof this.selectors === 'string') {
205 | return document.querySelector(this.selectors);
206 | }
207 |
208 | return this.selectors[0];
209 | }
210 |
211 | /**
212 | * Find elements
213 | * @param selector
214 | * @return {DPNode}
215 | */
216 | find(selector) {
217 | let children = this.node().querySelectorAll(selector);
218 | children = this.convertToArray(children);
219 |
220 | return new DPNode(children);
221 | }
222 |
223 | /**
224 | * Get parent
225 | * @return {DPNode}
226 | */
227 | parent() {
228 | return new DPNode(this.node().parentNode);
229 | }
230 |
231 | /**
232 | * Get/set height of element
233 | * @param value
234 | * @return {*}
235 | */
236 | height(value) {
237 | if (value === undefined) {
238 | let node = this.node();
239 |
240 | return node.getBoundingClientRect !== undefined ? node.getBoundingClientRect().height : (function () {
241 | var myHeight = 0;
242 |
243 | if (typeof(window.innerWidth) == 'number') {
244 | myHeight = window.innerHeight;
245 | } else if (document.documentElement && document.documentElement.clientHeight) {
246 | myHeight = document.documentElement.clientHeight;
247 | } else if (document.body && document.body.clientHeight) {
248 | myHeight = document.body.clientHeight;
249 | }
250 |
251 | return myHeight;
252 | })();
253 | }
254 |
255 | let selectors = this.nodes();
256 |
257 | for (var i = 0; i < selectors.length; ++i) {
258 | selectors[i].style.height = value;
259 | }
260 |
261 | return this;
262 | }
263 |
264 | /**
265 | * Get/set width of element
266 | * @return {number}
267 | * @return {*}
268 | */
269 | width(value) {
270 | if (value === undefined) {
271 | let node = this.node();
272 |
273 | return node.getBoundingClientRect !== undefined ? node.getBoundingClientRect().width : (function () {
274 | var myWidth = 0;
275 |
276 | if (typeof(window.innerWidth) == 'number') {
277 | myWidth = window.innerWidth;
278 | } else if (document.documentElement && document.documentElement.clientWidth) {
279 | myWidth = document.documentElement.clientWidth;
280 | } else if (document.body && document.body.clientWidth) {
281 | myWidth = document.body.clientWidth;
282 | }
283 |
284 | return myWidth;
285 | })();
286 | }
287 |
288 | let selectors = this.nodes();
289 |
290 | for (var i = 0; i < selectors.length; ++i) {
291 | selectors[i].style.width = value;
292 | }
293 |
294 | return this;
295 | }
296 |
297 | /**
298 | * Add class to element
299 | * @param name
300 | */
301 | addClass(name) {
302 | let selectors = this.nodes();
303 |
304 | for (var i = 0; i < selectors.length; ++i) {
305 | selectors[i].classList.add(name);
306 | }
307 |
308 | return this;
309 | }
310 |
311 | /**
312 | * Remove class
313 | * @param name
314 | */
315 | removeClass(name) {
316 | let selectors = this.nodes();
317 |
318 | for (var i = 0; i < selectors.length; ++i) {
319 | if (selectors[i].classList.contains(name)) {
320 | selectors[i].classList.remove(name);
321 | }
322 | }
323 |
324 | return this;
325 | }
326 |
327 | /**
328 | * CSS
329 | * @param key
330 | * @param value
331 | * @return {*}
332 | */
333 | css(key, value) {
334 | // Check if is get CSS
335 | if (typeof key === 'string' && value === undefined) {
336 | return this.node().style[key];
337 | }
338 |
339 | let selectors = this.nodes();
340 | let values = {};
341 |
342 | if (typeof key === 'string') {
343 | values[key] = value;
344 | } else {
345 | values = key;
346 | }
347 |
348 | for (let i = 0; i < selectors.length; i++) {
349 | for (let vKey in values) {
350 | selectors[i].style[vKey] = values[vKey];
351 | }
352 | }
353 |
354 | return this;
355 | }
356 |
357 | /**
358 | * Get attribute
359 | * @param key
360 | * @param value
361 | * @return {*}
362 | */
363 | attr(key, value) {
364 | // Check if is get value
365 | if (typeof key === "string" && value === undefined) {
366 | return this.node().getAttribute(key);
367 | }
368 |
369 | let selectors = this.nodes();
370 | let values = [];
371 |
372 | if (typeof key === 'string') {
373 | let val = {};
374 | val[key] = value;
375 | values.push(val);
376 | } else {
377 | values = key;
378 | }
379 |
380 | for (let i = 0; i < selectors.length; i++) {
381 | for (let vKey in values) {
382 | selectors[i].setAttribute(vKey, values[vKey]);
383 | }
384 | }
385 | }
386 |
387 | /***
388 | * Get/set html
389 | * @param value
390 | * @return *
391 | */
392 | html(value) {
393 | if (value === undefined) {
394 | return this.node().innerHTML;
395 | }
396 |
397 | let selectors = this.nodes();
398 |
399 | for (let i = 0; i < selectors.length; i++) {
400 | selectors[i].innerHTML = value;
401 | }
402 |
403 | return this;
404 | }
405 |
406 | /**
407 | * Has Class
408 | * @param name
409 | * @return {boolean}
410 | */
411 | hasClass(name) {
412 | return this.node().classList.contains(name);
413 | }
414 |
415 | /**
416 | * Active status
417 | * @param status
418 | * @return {DPNode}
419 | */
420 | active(status) {
421 | let selectors = this.nodes();
422 |
423 | for (let i = 0; i < selectors.length; i++) {
424 | if (status) {
425 | selectors[i].classList.add('active');
426 | } else if (selectors[i].classList.contains('active')) {
427 | selectors[i].classList.remove('active');
428 | }
429 | }
430 |
431 | return this;
432 | }
433 |
434 | /**
435 | * Is active
436 | * @return {boolean}
437 | */
438 | isActive() {
439 | return this.hasClass('active');
440 | }
441 |
442 | /**
443 | * Events
444 | * @param name
445 | * @param call
446 | */
447 | listen(key, call) {
448 | let keys = key.trim().replace(/\s/gi, ',').split(',');
449 | let selectors = this.nodes();
450 |
451 | for (let i = 0; i < selectors.length; i++) {
452 | for (let j = 0; j < keys.length; j++) {
453 | selectors[i].addEventListener(keys[j], call);
454 | }
455 | }
456 |
457 | return this;
458 | }
459 |
460 | /**
461 | * Get value
462 | * @param value
463 | * @return {DPNode}
464 | */
465 | val(value) {
466 | if (value === undefined) {
467 | return this.node().value;
468 | }
469 |
470 | let selectors = this.nodes();
471 |
472 | for (let i = 0; i < selectors.length; i++) {
473 | selectors[i].value = value;
474 | }
475 |
476 | return this;
477 | }
478 |
479 | /**
480 | * Get offset
481 | * @return {{}}
482 | */
483 | offset() {
484 | let bound = this.node().getBoundingClientRect();
485 |
486 | return {
487 | left: bound.left,
488 | top: bound.top,
489 | right: bound.right,
490 | bottom: bound.bottom
491 | };
492 | }
493 |
494 | /**
495 | * Has
496 | * @param selector
497 | * @return {boolean}
498 | */
499 | has(selector) {
500 | return this.node().contains(selector);
501 | }
502 |
503 | /**
504 | * is
505 | * @param selector
506 | */
507 | is(selector) {
508 | return this.node().isSameNode(selector);
509 | }
510 |
511 | /**
512 | * Closest
513 | * @param selector
514 | * @return {*|HTMLElementTagNameMap[keyof HTMLElementTagNameMap]|Element|SVGElementTagNameMap[keyof SVGElementTagNameMap]}
515 | */
516 | closest(selector) {
517 | return new DPNode(this.node().closest(selector));
518 | }
519 |
520 | /**
521 | * Append child
522 | * @param node
523 | * @return {DPNode}
524 | */
525 | append(node) {
526 | let selectors = this.nodes();
527 |
528 | for (let i = 0; i < selectors.length; i++) {
529 | selectors[i].appendChild(node);
530 | }
531 |
532 | return this;
533 | }
534 |
535 | /**
536 | * Text
537 | * @param value
538 | * @return {*}
539 | */
540 | text(value) {
541 | if (value === undefined) {
542 | return this.node().textContent;
543 | }
544 |
545 | let selectors = this.nodes();
546 |
547 | for (let i = 0; i < selectors.length; i++) {
548 | selectors[i].textContent = value;
549 | }
550 |
551 | return this;
552 | }
553 | }
554 |
555 | // ====================================================
556 | // Class {DPConfig}
557 | // ====================================================
558 | class DPConfig extends DPBase {
559 | /**
560 | * Constructor
561 | * @param config
562 | */
563 | constructor(config) {
564 | super();
565 |
566 | // Set default
567 | config.logo = this.or(config.logo, {});
568 | config.size = this.or(config.size, {});
569 |
570 | // Config for elements
571 | this.config = {
572 | elements: this.mergeElements(config),
573 | // Config for icon
574 | icons: this.mergeIcons(config),
575 | // Config default
576 | volume: this.or(config.volume, __dp.defaultConfig.volume),
577 | view: this.mergeView(config),
578 | sources: this.or(config.sources, __dp.defaultConfig.sources),
579 | logo: this.mergeLogo(config),
580 | size: this.mergeSize(config),
581 | largeScreen: this.or(config.largeScreen, __dp.defaultConfig.largeScreen),
582 | locale: this.or(config.locale, __dp.defaultConfig.locale),
583 | menu: this.mergeMenu(config),
584 | poster: this.or(config.poster, __dp.defaultConfig.poster),
585 | schedules: this.mergeSchedules(config),
586 | type: this.or(config.type, __dp.defaultConfig.type), // audio or video
587 | plugins: this.mergePlugins(config),
588 | startAt: this.or(config.startAt, __dp.defaultConfig.startAt),
589 | preview: this.or(config.preview, __dp.defaultConfig.preview)
590 | };
591 |
592 | // Function
593 |
594 | // Init cache
595 | this.cache = {
596 | node: {},
597 | config: {}
598 | };
599 | }
600 |
601 | /**
602 | * Merge menu
603 | * @return {object}
604 | */
605 | mergeMenu(config) {
606 | if (config.menu === false) {
607 | return false;
608 | }
609 |
610 | let rs = this.or(config.menu, __dp.defaultConfig.menu);
611 |
612 | rs.loop = this.or(rs.loop, {
613 | text: 'menu.loop',
614 | element: 'menuItemLoop',
615 | execute: function (item, menu, config) {
616 | menu.execLoop(item, config);
617 | }
618 | });
619 |
620 | rs.copyUrl = this.or(rs.copyUrl, {
621 | text: 'menu.copy_url',
622 | element: 'menuItemCopyUrl',
623 | execute: function (item, menu, config) {
624 | menu.execCopyUrl(item, config);
625 | }
626 | });
627 |
628 | return rs;
629 | }
630 |
631 | /**
632 | * Merge Elements
633 | * @return {object}
634 | */
635 | mergeElements(config) {
636 | config.elements = this.or(config.elements, {});
637 |
638 | return {
639 | object: this.or(config.elements.object, __dp.defaultConfig.elements.object),
640 | container: this.or(config.elements.container, __dp.defaultConfig.elements.container),
641 | video: this.or(config.elements.video, __dp.defaultConfig.elements.video),
642 | audio: this.or(config.elements.audio, __dp.defaultConfig.elements.audio),
643 | logo: this.or(config.elements.logo, __dp.defaultConfig.elements.logo),
644 | progress: this.or(config.elements.progress, __dp.defaultConfig.elements.progress),
645 | progressLoading: this.or(config.elements.progressLoading, __dp.defaultConfig.elements.progressLoading),
646 | progressPlaying: this.or(config.elements.progressPlaying, __dp.defaultConfig.elements.progressPlaying),
647 | progressHoverTooltipText: this.or(config.elements.progressHoverTooltipText, __dp.defaultConfig.elements.progressHoverTooltipText),
648 | progressHoverTooltipImage: this.or(config.elements.progressHoverTooltipImage, __dp.defaultConfig.elements.progressHoverTooltipImage),
649 | control: this.or(config.elements.control, __dp.defaultConfig.elements.control),
650 | button: this.or(config.elements.button, __dp.defaultConfig.elements.button),
651 | buttonIcon: this.or(config.elements.buttonIcon, __dp.defaultConfig.elements.buttonIcon),
652 | controlPlayPause: this.or(config.elements.controlPlayPause, __dp.defaultConfig.elements.controlPlayPause),
653 | controlFullScreen: this.or(config.elements.controlFullScreen, __dp.defaultConfig.elements.controlFullScreen),
654 | controlLargeScreen: this.or(config.elements.controlLargeScreen, __dp.defaultConfig.elements.controlLargeScreen),
655 | controlVolume: this.or(config.elements.controlVolume, __dp.defaultConfig.elements.controlVolume),
656 | controlVolumeTooltip: this.or(config.elements.controlVolumeTooltip, __dp.defaultConfig.elements.controlVolumeTooltip),
657 | controlVolumeRange: this.or(config.elements.controlVolumeRange, __dp.defaultConfig.elements.controlVolumeRange),
658 | controlTimer: this.or(config.elements.controlTimer, __dp.defaultConfig.elements.controlTimer),
659 | modal: this.or(config.elements.modal, __dp.defaultConfig.elements.modal),
660 | loaderModal: this.or(config.elements.loaderModal, __dp.defaultConfig.elements.loaderModal),
661 | loaderModalIcon: this.or(config.elements.loaderModalIcon, __dp.defaultConfig.elements.loaderModalIcon),
662 | playerModal: this.or(config.elements.playerModal, __dp.defaultConfig.elements.playerModal),
663 | playerModalIcon: this.or(config.elements.playerModalIcon, __dp.defaultConfig.elements.playerModalIcon),
664 | menu: this.or(config.elements.menu, __dp.defaultConfig.elements.menu),
665 | menuList: this.or(config.elements.menuList, __dp.defaultConfig.elements.menuList),
666 | menuItem: this.or(config.elements.menuItem, __dp.defaultConfig.elements.menuItem),
667 | menuItemLoop: this.or(config.elements.menuItemLoop, __dp.defaultConfig.elements.menuItemLoop),
668 | menuItemCopyUrl: this.or(config.elements.menuItemCopyUrl, __dp.defaultConfig.elements.menuItemCopyUrl),
669 | ads: this.or(config.elements.ads, __dp.defaultConfig.elements.ads),
670 | adsItem: this.or(config.elements.adsItem, __dp.defaultConfig.elements.adsItem),
671 | adsContent: this.or(config.elements.adsContent, __dp.defaultConfig.elements.adsContent),
672 | adsClose: this.or(config.elements.adsClose, __dp.defaultConfig.elements.adsClose),
673 | };
674 | }
675 |
676 | /**
677 | * Merge Icons
678 | * @return {object}
679 | */
680 | mergeIcons(config) {
681 | config.icons = this.or(config.icons, {});
682 |
683 | return {
684 | loaderModal: this.or(config.icons.loaderModal, __dp.defaultConfig.icons.loaderModal),
685 | playerModal: this.or(config.icons.loaderModal, __dp.defaultConfig.icons.playerModal),
686 | fullScreen: this.or(config.icons.fullScreen, __dp.defaultConfig.icons.fullScreen),
687 | actualScreen: this.or(config.icons.actualScreen, __dp.defaultConfig.icons.actualScreen),
688 | largeScreen: this.or(config.icons.largeScreen, __dp.defaultConfig.icons.largeScreen),
689 | smallScreen: this.or(config.icons.smallScreen, __dp.defaultConfig.icons.smallScreen),
690 | pause: this.or(config.icons.pause, __dp.defaultConfig.icons.pause),
691 | play: this.or(config.icons.play, __dp.defaultConfig.icons.play),
692 | volumeMute: this.or(config.icons.volumeMute, __dp.defaultConfig.icons.volumeMute),
693 | volume1: this.or(config.icons.volume1, __dp.defaultConfig.icons.volume1),
694 | volume2: this.or(config.icons.volume2, __dp.defaultConfig.icons.volume2),
695 | volume3: this.or(config.icons.volume3, __dp.defaultConfig.icons.volume3),
696 | close: this.or(config.icons.close, __dp.defaultConfig.icons.close)
697 | };
698 | }
699 |
700 | /**
701 | * Merge logo
702 | * @return {object}
703 | */
704 | mergeLogo(config) {
705 | // Check if logo is false, its mean is not show
706 | if (config.logo === false) {
707 | return config.logo;
708 | }
709 |
710 | // Check if logo is undefined then get default value
711 | config.logo = this.or(config.logo, {});
712 |
713 | let rs = {};
714 |
715 | if (config.logo.height !== undefined) {
716 | rs.height = config.logo.height;
717 |
718 | if (config.logo.width !== undefined) {
719 | rs.width = config.logo.width;
720 | } else {
721 | rs.rate = this.or(config.logo.rate, __dp.defaultConfig.logo.rate);
722 | }
723 | } else if (config.logo.width !== undefined) {
724 | rs.width = config.logo.width;
725 |
726 | if (config.logo.height !== undefined) {
727 | rs.height = config.logo.height;
728 | } else {
729 | rs.rate = this.or(config.logo.rate, __dp.defaultConfig.logo.rate);
730 | }
731 | } else {
732 | rs.height = __dp.defaultConfig.logo.height;
733 | rs.rate = __dp.defaultConfig.logo.rate;
734 | }
735 |
736 | rs.url = this.or(config.logo.url, null);
737 |
738 | return rs;
739 | }
740 |
741 | /**
742 | * Merge size
743 | * @return {object}
744 | */
745 | mergeSize(config) {
746 | config.size = this.or(config.size, {});
747 | let rs = {};
748 |
749 | if (config.size.height !== undefined) {
750 | rs.height = config.size.height;
751 |
752 | if (config.size.width !== undefined) {
753 | rs.width = config.size.width;
754 | } else {
755 | rs.rate = this.or(config.size.rate, __dp.defaultConfig.size.rate);
756 | }
757 | } else if (config.size.width !== undefined) {
758 | rs.width = config.size.width;
759 |
760 | if (config.size.height !== undefined) {
761 | rs.height = config.size.height;
762 | } else {
763 | rs.rate = this.or(config.size.rate, __dp.defaultConfig.size.rate);
764 | }
765 | } else {
766 | rs.width = __dp.defaultConfig.size.width;
767 | rs.rate = __dp.defaultConfig.size.rate;
768 | }
769 |
770 | return rs;
771 | }
772 |
773 | /**
774 | * Merge view
775 | * @return {object}
776 | */
777 | mergeView(config) {
778 | if (config.view == false
779 | || config.view == undefined) {
780 | config.view = {};
781 | }
782 |
783 | return {
784 | content: this.or(config.view.content, __dp.defaultConfig.view.content),
785 | import: this.or(config.view.import, __dp.defaultConfig.view.import)
786 | };
787 | }
788 |
789 | /**
790 | * Merge schedules
791 | * @param config
792 | * @return {object}
793 | */
794 | mergeSchedules(config) {
795 | if (!config.schedules) {
796 | return [];
797 | }
798 |
799 | let rs = this.or(config.schedules, __dp.defaultConfig.schedules);
800 |
801 | return rs;
802 | }
803 |
804 | /**
805 | * Merge plugins
806 | * @param config
807 | * @return {object}
808 | */
809 | mergePlugins(config) {
810 | return this.or(config.plugins, __dp.defaultConfig.plugins);
811 | }
812 |
813 | /**
814 | * Access array
815 | * @param key
816 | * @return {*}
817 | */
818 | access(key) {
819 | let config = this.config;
820 | let keys = key.split('.');
821 |
822 | for (let i in keys) {
823 | if (config[keys[i]] === undefined) {
824 | config = undefined;
825 | break;
826 | }
827 |
828 | config = config[keys[i]];
829 | }
830 |
831 | return config;
832 | }
833 |
834 | /**
835 | * Get config
836 | * @param key
837 | * @return mixed
838 | */
839 | get(key, cache) {
840 | cache = cache !== undefined ? cache : true;
841 |
842 | // Get config cache
843 | if (!(this.cache.config[key] !== undefined && cache)) {
844 | this.cache.config[key] = this.access(key);
845 | }
846 |
847 | return this.cache.config[key];
848 | }
849 |
850 | /**
851 | * Get node
852 | * @param key
853 | * @param cache
854 | * @return {*|undefined}
855 | */
856 | el(key, cache){
857 | cache = cache !== undefined ? cache : true;
858 | let config = this.get(key, cache);
859 |
860 | // Check if is object elements
861 | if (key === 'elements.object' && (this.cache.node[key] === undefined || !cache)) {
862 | this.cache.node[key] = new DPNode(config);
863 | }
864 | // Check get dom is true and dom is created
865 | // Then return dom in cache
866 | else if (typeof config === 'string') {
867 | if (this.cache.node[key] === undefined || !cache) {
868 | this.cache.node[key] = this.cache.node['elements.object'].find(config);
869 | }
870 | }
871 |
872 | return this.cache.node[key];
873 | }
874 |
875 | /**
876 | * Get runner
877 | * @param isDom
878 | * @return {mixed}
879 | */
880 | runner(isDom, cache) {
881 | let type = this.get('type');
882 |
883 | if (isDom) {
884 | return this.el('elements.' + type, cache);
885 | }
886 |
887 | return this.get('elements.' + type, cache);
888 | }
889 | }
890 |
891 | // ====================================================
892 | // Class {DPEvent}
893 | // ====================================================
894 | class DPEvent extends DPBase {
895 | /**
896 | * constructor
897 | */
898 | constructor(app) {
899 | super();
900 | this.app = app;
901 | }
902 |
903 | /**
904 | * Init
905 | */
906 | init() {
907 | this.events = {};
908 | this.viewEvents()
909 | .logoEvents()
910 | .menuEvents()
911 | .controlEvents()
912 | .screenEvents()
913 | .modalEvents()
914 | .sourceEvents();
915 | }
916 |
917 | /**
918 | * View events
919 | * @return {DPEvent}
920 | */
921 | viewEvents() {
922 | let instance = this;
923 |
924 | this.events['dp.view.rendering'] = function (parameters) {
925 | return instance.createEvent('dp.view.rendering', parameters);
926 | };
927 |
928 | this.events['dp.view.rendered'] = function (parameters) {
929 | return instance.createEvent('dp.view.rendered', parameters);
930 | };
931 |
932 | return this;
933 | }
934 |
935 | /**
936 | * Logo events
937 | * @return {DPEvent}
938 | */
939 | logoEvents() {
940 | let instance = this;
941 |
942 | this.events['dp.logo.resize'] = function (parameters) {
943 | return instance.createEvent('dp.logo.resize', parameters);
944 | };
945 |
946 | return this;
947 | }
948 |
949 | /**
950 | * Menu events
951 | * @return {DPEvent}
952 | */
953 | menuEvents() {
954 | let instance = this;
955 |
956 | this.events['dp.menu.open'] = function (parameters) {
957 | return instance.createEvent('dp.menu.open', parameters);
958 | };
959 |
960 | this.events['dp.menu.close'] = function (parameters) {
961 | return instance.createEvent('dp.menu.close', parameters);
962 | };
963 |
964 | return this;
965 | }
966 |
967 | /**
968 | * Control events
969 | * @return {DPEvent}
970 | */
971 | controlEvents() {
972 | let instance = this;
973 |
974 | this.events['dp.control.show'] = function (parameters) {
975 | return instance.createEvent('dp.control.show', parameters);
976 | };
977 |
978 | this.events['dp.control.hide'] = function (parameters) {
979 | return instance.createEvent('dp.control.hide', parameters);
980 | };
981 |
982 | return this;
983 | }
984 |
985 | /**
986 | * Logo events
987 | * @return {DPEvent}
988 | */
989 | modalEvents() {
990 | let instance = this;
991 |
992 | // Event for loader
993 | this.events['dp.modal.loader.show'] = function (parameters) {
994 | return instance.createEvent('dp.modal.loader.show', parameters);
995 | };
996 |
997 | this.events['dp.modal.loader.hide'] = function (parameters) {
998 | return instance.createEvent('dp.modal.loader.hide', parameters);
999 | };
1000 |
1001 | // Event for player
1002 | this.events['dp.modal.player.show'] = function (parameters) {
1003 | return instance.createEvent('dp.modal.player.show', parameters);
1004 | };
1005 |
1006 | this.events['dp.modal.player.hide'] = function (parameters) {
1007 | return instance.createEvent('dp.modal.player.hide', parameters);
1008 | };
1009 |
1010 | return this;
1011 | }
1012 |
1013 | /**
1014 | * Screen events
1015 | * @return {DPEvent}
1016 | */
1017 | screenEvents() {
1018 | let instance = this;
1019 |
1020 | // Event for large screen
1021 | this.events['dp.screen.large.active'] = function (parameters) {
1022 | return [
1023 | instance.createEvent('dp.screen.large.change', parameters),
1024 | instance.createEvent('dp.screen.large.active', parameters)
1025 | ];
1026 | };
1027 |
1028 | this.events['dp.screen.large.inactive'] = function (parameters) {
1029 | return [
1030 | instance.createEvent('dp.screen.large.change', parameters),
1031 | instance.createEvent('dp.screen.large.inactive', parameters)
1032 | ];
1033 | };
1034 |
1035 | // Event for full screen
1036 | this.events['dp.screen.full.active'] = function (parameters) {
1037 | return [
1038 | instance.createEvent('dp.screen.full.change', parameters),
1039 | instance.createEvent('dp.screen.full.active', parameters)
1040 | ];
1041 | };
1042 |
1043 | this.events['dp.screen.full.inactive'] = function (parameters) {
1044 | return [
1045 | instance.createEvent('dp.screen.full.change', parameters),
1046 | instance.createEvent('dp.screen.full.inactive', parameters)
1047 | ];
1048 | };
1049 |
1050 | this.events['dp.screen.change'] = function (parameters) {
1051 | return instance.createEvent('dp.screen.change', parameters);
1052 | };
1053 |
1054 | return this;
1055 | }
1056 |
1057 | /**
1058 | * sourceEvents
1059 | * @return {DPEvent}
1060 | */
1061 | sourceEvents() {
1062 | let instance = this;
1063 |
1064 | this.events['dp.source.play'] = function (parameters) {
1065 | return instance.createEvent('dp.source.play', parameters);
1066 | };
1067 |
1068 | this.events['dp.source.pause'] = function (parameters) {
1069 | return instance.createEvent('dp.source.pause', parameters);
1070 | };
1071 |
1072 | this.events['dp.source.ended'] = function (parameters) {
1073 | return instance.createEvent('dp.source.ended', parameters);
1074 | };
1075 |
1076 | return this;
1077 | }
1078 |
1079 | /**
1080 | * Create event
1081 | * @param name
1082 | * @param parameters
1083 | */
1084 | createEvent(name, parameters) {
1085 | return new CustomEvent(name, parameters);
1086 | }
1087 |
1088 | /**
1089 | * Trigger event
1090 | * @param name
1091 | * @param parameters
1092 | */
1093 | trigger(name, parameters) {
1094 | let events = null;
1095 |
1096 | if (this.events[name] !== undefined) {
1097 | events = this.events[name](this.or(parameters, {}));
1098 | } else {
1099 | events = this.createEvent(name, this.or(parameters, {}));
1100 | }
1101 |
1102 | let ob = this.app.config.el('elements.object');
1103 | let dom = ob.node();
1104 |
1105 | if (events instanceof Array) {
1106 | events.forEach(function (item, index) {
1107 | dom.dispatchEvent(item);
1108 | });
1109 | } else {
1110 | dom.dispatchEvent(events);
1111 | }
1112 |
1113 | return this;
1114 | }
1115 |
1116 | /**
1117 | * Trigger event
1118 | * @param name
1119 | * @param parameters
1120 | */
1121 | listen(name, call) {
1122 | let ob = this.app.config.el('elements.object');
1123 | let dom = ob.node();
1124 |
1125 | dom.addEventListener(name, call);
1126 |
1127 | return this;
1128 | }
1129 | }
1130 |
1131 | // ====================================================
1132 | // Class {DPView}
1133 | // ====================================================
1134 | class DPView extends DPBase {
1135 | /**
1136 | * Constructor
1137 | * @param config
1138 | */
1139 | constructor(app) {
1140 | super();
1141 | this.app = app;
1142 | }
1143 |
1144 | /**
1145 | * Init
1146 | * @return {DPView}
1147 | */
1148 | init() {
1149 | return this;
1150 | }
1151 |
1152 | /**
1153 | * Render view
1154 | * @return {DPView}
1155 | */
1156 | async render() {
1157 | let elObject = this.app.config.el('elements.object');
1158 | let viewConfig = this.app.config.get('view');
1159 | let posterUrl = this.app.config.get('poster');
1160 | let sizeConfig = this.app.config.get('size');
1161 |
1162 | this.app.event.trigger('dp.view.rendering');
1163 |
1164 | // Render size
1165 | elObject.css({maxWidth: '100%'});
1166 |
1167 | if (sizeConfig.height !== undefined) {
1168 | elObject.css({height: sizeConfig.height});
1169 |
1170 | if (sizeConfig.width !== undefined) {
1171 | elObject.css({width: sizeConfig.width});
1172 | } else {
1173 | elObject.css({width: (elObject.height() / sizeConfig.rate) + 'px'});
1174 | }
1175 | } else {
1176 | elObject.css({width: sizeConfig.width});
1177 |
1178 | if (sizeConfig.height !== undefined) {
1179 | elObject.css({height: sizeConfig.height});
1180 | } else {
1181 | elObject.css({height: (elObject.width() * sizeConfig.rate) + 'px'});
1182 | }
1183 | }
1184 |
1185 | // Read content in template
1186 | if (!viewConfig.content) {
1187 | if (viewConfig.import) {
1188 | elObject.html(this.app.translate.get('app.loading'));
1189 | let response = await this.loadTemplate();
1190 | let content = this.replace(response);
1191 | elObject.html(content);
1192 | }
1193 | } else {
1194 | let content = this.replace(viewConfig.content);
1195 | elObject.html(content);
1196 | }
1197 |
1198 | // Render the poster for video
1199 | if (this.poster) {
1200 | let runner = this.app.config.runner(true);
1201 | runner.node().poster = posterUrl;
1202 | }
1203 |
1204 | this.app.event.trigger('dp.view.rendered');
1205 |
1206 | return true;
1207 | }
1208 |
1209 | /**
1210 | * Load template
1211 | * @return {Promise}
1212 | */
1213 | async loadTemplate() {
1214 | let viewConfig = this.app.config.get('view');
1215 |
1216 | return new Promise(function (resolve, reject) {
1217 | let xhr = new XMLHttpRequest();
1218 | xhr.open('GET', viewConfig.import);
1219 | xhr.onload = function () {
1220 | if (this.status >= 200 && this.status < 300) {
1221 | resolve(xhr.response);
1222 | } else {
1223 | reject({
1224 | status: this.status,
1225 | statusText: xhr.statusText
1226 | });
1227 | }
1228 | };
1229 | xhr.onerror = function () {
1230 | reject({
1231 | status: this.status,
1232 | statusText: xhr.statusText
1233 | });
1234 | };
1235 | xhr.send();
1236 | });
1237 | }
1238 |
1239 | /**
1240 | * replace
1241 | * @return string
1242 | */
1243 | replace(content) {
1244 | return content;
1245 | }
1246 | }
1247 |
1248 | // ====================================================
1249 | // Class {DPTranslator}
1250 | // ====================================================
1251 | class DPTranslator extends DPBase {
1252 | /**
1253 | * Constructor
1254 | * @param config
1255 | */
1256 | constructor(app) {
1257 | super();
1258 | this.app = app;
1259 |
1260 | // Get local config
1261 | let locale = this.app.config.get('locale');
1262 | this.languages = this.or(__dp.translateData[locale], {});
1263 | }
1264 |
1265 | /**
1266 | * Get translate
1267 | * @param key
1268 | * @param attributes
1269 | * @return mixed
1270 | */
1271 | get(key, attributes) {
1272 | if (attributes == undefined) {
1273 | attributes = {};
1274 | }
1275 |
1276 | var keys = key.split('.');
1277 | var messages = this.languages;
1278 | let message = messages;
1279 |
1280 | // Get message format
1281 | for (var i in keys) {
1282 | if (message[keys[i]] == undefined) {
1283 | return key;
1284 | }
1285 |
1286 | message = message[keys[i]];
1287 | }
1288 |
1289 | // Get attribute in message format
1290 | for (var attrKey in attributes) {
1291 | if (messages[keys[0]].attributes == undefined) {
1292 | return message;
1293 | }
1294 |
1295 | if (messages[keys[0]].attributes[attrKey] == undefined) {
1296 | return message;
1297 | }
1298 |
1299 | var fields = messages[keys[0]].attributes[attrKey];
1300 | var attr = (fields[attributes[attrKey]] != undefined ? fields[attributes[attrKey]] : attributes[attrKey]);
1301 | var regex = new RegExp(':' + attrKey, 'g');
1302 | message = message.replace(regex, attr);
1303 | }
1304 |
1305 | return message;
1306 | }
1307 | }
1308 |
1309 | // ====================================================
1310 | // Class {DPMenu}
1311 | // ====================================================
1312 | class DPMenu extends DPBase {
1313 | /**
1314 | * Constructor
1315 | * @param config
1316 | */
1317 | constructor(app) {
1318 | super();
1319 | this.app = app;
1320 | }
1321 |
1322 | /**
1323 | * Render menu
1324 | * @param config
1325 | * @return {DPMenu}
1326 | */
1327 | init() {
1328 | this.status = true;
1329 |
1330 | let menuList = this.app.config.get('menu');
1331 | let elMenuList = this.app.config.el('elements.menuList');
1332 |
1333 | if (menuList === false) {
1334 | this.status = false;
1335 | return this;
1336 | }
1337 |
1338 | let menuItemClass = this.app.config.get('elements.menuItem').replace('.', '');
1339 |
1340 | for (var name in menuList) {
1341 | let div = document.createElement('div');
1342 | div.classList.add(menuItemClass);
1343 | div.setAttribute('dp-menu:name', name);
1344 | div.innerHTML = this.app.translate.get(menuList[name].text);
1345 | elMenuList.append(div);
1346 | }
1347 |
1348 | this.events();
1349 |
1350 | return this;
1351 | }
1352 |
1353 | /**
1354 | * Open menu
1355 | * @param config
1356 | * @return {DPMenu}
1357 | */
1358 | openMenu(event) {
1359 | if (!this.status) {
1360 | return this;
1361 | }
1362 |
1363 | let elMenu = this.app.config.el('elements.menu');
1364 | let elMenuList = this.app.config.el('elements.menuList');
1365 |
1366 | elMenu.active(true);
1367 |
1368 | let height = elMenuList.height();
1369 | let width = elMenuList.width();
1370 |
1371 | let cHeight = window.innerHeight;
1372 | let cWidth = window.innerWidth;
1373 |
1374 | let left = event.clientX;
1375 | let top = event.clientY;
1376 |
1377 | if ((cHeight - top) < height) {
1378 | top = cHeight - height;
1379 | }
1380 |
1381 | if ((cWidth - left) < width) {
1382 | left = cWidth - width;
1383 | }
1384 |
1385 | elMenuList.css({left: left + 'px', top: top + 'px'});
1386 |
1387 | this.app.event.trigger('dp.menu.open');
1388 |
1389 | return this;
1390 | }
1391 |
1392 | /**
1393 | * Close menu
1394 | * @param config
1395 | * @return {DPMenu}
1396 | */
1397 | closeMenu() {
1398 | let elMenu = this.app.config.el('elements.menu');
1399 |
1400 | if (!this.status) {
1401 | return this;
1402 | }
1403 |
1404 | elMenu.active(false);
1405 |
1406 | this.app.event.trigger('dp.menu.close');
1407 |
1408 | return this;
1409 | }
1410 |
1411 | /**
1412 | * Event menu
1413 | * @param config
1414 | * @return {DPMenu}
1415 | */
1416 | events() {
1417 | let instance = this;
1418 | let elMenuList = this.app.config.el('elements.menuList');
1419 | let elMenuItem = this.app.config.el('elements.menuItem');
1420 | let elContainer = this.app.config.el('elements.container');
1421 |
1422 | // Event when open context menu
1423 | elContainer.listen('contextmenu', function (e) {
1424 | if (instance.status) {
1425 | instance.openMenu(e);
1426 | }
1427 |
1428 | e.preventDefault();
1429 | });
1430 |
1431 | // Event when click out menu
1432 | __dp.node(window).listen('click', function (event) {
1433 | if (!elMenuList.has(event.target)
1434 | && !elMenuList.is(event.target)) {
1435 | instance.closeMenu();
1436 | }
1437 | });
1438 |
1439 | // Event when click menu item
1440 | elMenuItem.listen('click', function () {
1441 | let name = __dp.node(this).attr('dp-menu:name');
1442 | instance.execute(this, name);
1443 | });
1444 |
1445 | return this;
1446 | }
1447 |
1448 | /**
1449 | * execute
1450 | * @param name
1451 | * @return {DPMenu}
1452 | */
1453 | execute(item, name) {
1454 | if (!this.status) {
1455 | return this;
1456 | }
1457 |
1458 | let config = this.app.config.get('menu.' + name);
1459 |
1460 | if (config.execute !== undefined) {
1461 | config.execute(item, this, config);
1462 | }
1463 |
1464 | return this;
1465 | }
1466 |
1467 | /**
1468 | * Exec Loop
1469 | * @return {DPMenu}
1470 | */
1471 | execLoop(item, config) {
1472 | if (!this.status) {
1473 | return this;
1474 | }
1475 |
1476 | let elRunner = this.app.config.runner(true);
1477 | let runner = elRunner.node();
1478 |
1479 | if (runner.loop) {
1480 | runner.loop = false;
1481 | __dp.node(item).active(false);
1482 | } else {
1483 | runner.loop = true;
1484 | __dp.node(item).active(true);
1485 | }
1486 |
1487 | this.closeMenu();
1488 |
1489 | return this;
1490 | }
1491 |
1492 | /**
1493 | * Exec Copy Video Url
1494 | * @return {DPMenu}
1495 | */
1496 | execCopyUrl(item, config) {
1497 | if (!this.status) {
1498 | return this;
1499 | }
1500 |
1501 | let elRunner = this.app.config.runner(true);
1502 | let runner = elRunner.node();
1503 |
1504 | this.closeMenu();
1505 |
1506 | return this;
1507 | }
1508 | }
1509 |
1510 | // ====================================================
1511 | // Class {DPLogo}
1512 | // ====================================================
1513 | class DPLogo extends DPBase {
1514 | /**
1515 | * Constructor
1516 | * @param config
1517 | */
1518 | constructor(app) {
1519 | super();
1520 | this.app = app;
1521 | }
1522 |
1523 | /**
1524 | * resizeLogo
1525 | * @return {DPLogo}
1526 | */
1527 | resize() {
1528 | if (!this.status) {
1529 | return this;
1530 | }
1531 |
1532 | let elLogo = this.app.config.el('elements.logo');
1533 | let logoConfig = this.app.config.get('logo');
1534 |
1535 | if (logoConfig.height !== undefined) {
1536 | elLogo.css({height: logoConfig.height});
1537 |
1538 | if (logoConfig.width !== undefined) {
1539 | elLogo.css({width: logoConfig.width});
1540 | } else {
1541 | elLogo.css({width: (elLogo.height() / logoConfig.rate) + 'px'});
1542 | }
1543 | } else {
1544 | elLogo.css({width: logoConfig.width});
1545 |
1546 | if (logoConfig.height !== undefined) {
1547 | elLogo.css({height: logoConfig.height});
1548 | } else {
1549 | elLogo.css({height: (elLogo.width() * logoConfig.rate) + 'px'});
1550 | }
1551 | }
1552 |
1553 | this.app.event.trigger('dp.logo.resize');
1554 |
1555 | return this;
1556 | }
1557 |
1558 | /**
1559 | * render
1560 | * @return {DPLogo}
1561 | */
1562 | init() {
1563 | this.status = true;
1564 |
1565 | let elLogo = this.app.config.el('elements.logo');
1566 | let logoConfig = this.app.config.get('logo');
1567 | let instance = this;
1568 |
1569 | // Check if logo is hidden
1570 | if (logoConfig === false) {
1571 | this.status = false;
1572 | elLogo.active(false);
1573 | return this;
1574 | }
1575 |
1576 | elLogo.active(true);
1577 | elLogo.css({backgroundImage: 'url(\'' + logoConfig.url + '\')'});
1578 |
1579 | // Event when screen change
1580 | this.app.event.listen('dp.screen.change', function () {
1581 | instance.resize();
1582 | });
1583 |
1584 | // Default
1585 | instance.resize();
1586 |
1587 | return this;
1588 | }
1589 | }
1590 |
1591 | // ====================================================
1592 | // Class {DPModal}
1593 | // ====================================================
1594 | class DPModal extends DPBase {
1595 | /**
1596 | * Constructor
1597 | * @param config
1598 | */
1599 | constructor(app) {
1600 | super();
1601 | this.app = app;
1602 | }
1603 |
1604 | /**
1605 | * Render
1606 | */
1607 | init() {
1608 | let instance = this;
1609 | let icons = this.app.config.get('icons');
1610 | let elLoaderIcon = this.app.config.el('elements.loaderModalIcon');
1611 | let elPlayerIcon = this.app.config.el('elements.playerModalIcon');
1612 | let runner = this.app.config.runner(true);
1613 |
1614 | // default
1615 | elPlayerIcon.html(icons.playerModal);
1616 | elLoaderIcon.html(icons.loaderModal);
1617 |
1618 | this.toggle({loader: false, player: false});
1619 |
1620 | // Event when start load data
1621 | runner.listen('loadstart', function (e) {
1622 | instance.toggle({loader: true, player: false});
1623 | });
1624 |
1625 | // Event when runner play
1626 | runner.listen('play', function () {
1627 | instance.toggle({loader: isNaN(runner.node().duration), player: false});
1628 | });
1629 |
1630 | // Event when runner pause or ended
1631 | runner.listen('pause ended', function () {
1632 | instance.toggle({loader: isNaN(runner.node().duration), player: true});
1633 | });
1634 |
1635 | // Event when timeupdate
1636 | runner.listen('timeupdate ', function (e) {
1637 | instance.toggle({loader: false, player: runner.node().paused});
1638 | });
1639 |
1640 | // Event when loaded data
1641 | // Then call display information on screen
1642 | runner.listen('loadeddata', function (e) {
1643 | instance.toggle({loader: false, player: runner.node().paused});
1644 | });
1645 |
1646 | // Event when loading
1647 | runner.listen('waiting', function () {
1648 | instance.toggle({loader: true, player: false});
1649 | });
1650 |
1651 | runner.listen('seeking', function () {
1652 | instance.toggle({loader: true, player: false});
1653 | });
1654 |
1655 | runner.listen('seeked', function () {
1656 | instance.toggle({loader: false, player: runner.node().paused});
1657 | });
1658 |
1659 | return this;
1660 | }
1661 |
1662 | /**
1663 | * Show
1664 | * @param config
1665 | */
1666 | toggle(config) {
1667 | let elLoaderModal = this.app.config.el('elements.loaderModal');
1668 | let elPlayerModal = this.app.config.el('elements.playerModal');
1669 | let elModal = this.app.config.el('elements.modal');
1670 | let isLoaderActive = elLoaderModal.isActive();
1671 | let isPlayerActive = elPlayerModal.isActive();
1672 |
1673 | elModal.active(false);
1674 | elLoaderModal.active(config.loader === true);
1675 | elPlayerModal.active(config.player === true);
1676 |
1677 | // Check event
1678 | if (elLoaderModal.isActive() !== isLoaderActive) {
1679 | !isLoaderActive ? this.app.event.trigger('dp.modal.loader.show') : this.app.event.trigger('dp.modal.loader.hide');
1680 | }
1681 |
1682 | if (elPlayerModal.isActive() !== isPlayerActive) {
1683 | !isPlayerActive ? this.app.event.trigger('dp.modal.player.show') : this.app.event.trigger('dp.modal.player.hide');
1684 | }
1685 |
1686 | return this;
1687 | }
1688 | }
1689 |
1690 | // ====================================================
1691 | // Class {DPControl}
1692 | // ====================================================
1693 | class DPControl extends DPBase {
1694 | constructor(app) {
1695 | super();
1696 | this.app = app;
1697 | }
1698 |
1699 | /**
1700 | * Render
1701 | */
1702 | init() {
1703 | this.isMouseIn = false;
1704 | this.controlTime = null;
1705 |
1706 | let elRunner = this.app.config.runner(true);
1707 | let instance = this;
1708 | let runnerDom = elRunner.node();
1709 |
1710 | // Event when hover on runner/container/control
1711 | __dp.node(this.app.config.get('elements.container')
1712 | + ',' + this.app.config.get('elements.control')
1713 | + ',' + this.app.config.runner()).listen('mousemove', function () {
1714 | instance.openControl();
1715 | instance.isMouseIn = true;
1716 | });
1717 |
1718 | __dp.node(window).listen('scroll', function () {
1719 | instance.openControl();
1720 | });
1721 |
1722 | // Event when out on runner/container/control
1723 | __dp.node(this.app.config.get('elements.container')
1724 | + ',' + this.app.config.get('elements.control')
1725 | + ',' + this.app.config.runner()).listen('mouseleave', function () {
1726 | instance.closeControl();
1727 | instance.isMouseIn = false;
1728 | });
1729 |
1730 | // Event when runner pause or ended
1731 | elRunner.listen('pause ended', function () {
1732 | instance.openControl();
1733 | });
1734 |
1735 | // Event when runner pause or ended
1736 | elRunner.listen('play', function () {
1737 | if (!instance.isMouseIn) {
1738 | instance.closeControl();
1739 | }
1740 | });
1741 |
1742 | // Default
1743 | runnerDom.controls = false;
1744 |
1745 | // Set size for button
1746 | let buttonIcon = this.app.config.el('elements.buttonIcon');
1747 | let btnH = buttonIcon.height();
1748 | buttonIcon.width(btnH + 'px');
1749 |
1750 | return this;
1751 | }
1752 |
1753 | /**
1754 | * Hidden
1755 | */
1756 | closeControl() {
1757 | let elRunner = this.app.config.runner(true);
1758 | let elControl = this.app.config.el('elements.control');
1759 | let elContainer = this.app.config.el('elements.container');
1760 |
1761 | let runner = elRunner.node();
1762 |
1763 | if (!runner.paused) {
1764 | elControl.active(false);
1765 | this.app.event.trigger('dp.control.hide');
1766 |
1767 | if (this.isMouseIn) {
1768 | elContainer.node().style.cursor = "none";
1769 | //elContainer.addClass('hidden-cursor');
1770 | } else {
1771 | elContainer.node().style.cursor = "default";
1772 | //elContainer.removeClass('hidden-cursor');
1773 | }
1774 | }
1775 | }
1776 |
1777 | /**
1778 | * open
1779 | */
1780 | openControl() {
1781 | let instance = this;
1782 |
1783 | let elControl = this.app.config.el('elements.control');
1784 | let elContainer = this.app.config.el('elements.container');
1785 |
1786 | window.clearTimeout(this.controlTime);
1787 | elControl.active(true);
1788 | elContainer.node().style.cursor = "default";
1789 | // elContainer.removeClass('hidden-cursor');
1790 | this.app.event.trigger('dp.control.show');
1791 |
1792 | this.controlTime = window.setTimeout(function () {
1793 | instance.closeControl();
1794 | }, 2000);
1795 | }
1796 | }
1797 |
1798 | // ====================================================
1799 | // Class {DPScreen}
1800 | // ====================================================
1801 | class DPScreen extends DPBase {
1802 | /**
1803 | * Constructor
1804 | * @param app
1805 | */
1806 | constructor(app) {
1807 | super();
1808 | this.app = app;
1809 | }
1810 |
1811 | /**
1812 | * Default screen
1813 | */
1814 | defaultScreen() {
1815 | let sizeConfig = this.app.config.get('size');
1816 | let elObject = this.app.config.el('elements.object');
1817 |
1818 | if (sizeConfig.height !== undefined) {
1819 | elObject.css({height: sizeConfig.height});
1820 |
1821 | if (sizeConfig.width !== undefined) {
1822 | elObject.css({width: sizeConfig.width});
1823 | } else {
1824 | elObject.css({width: (elObject.height() / sizeConfig.rate) + 'px'});
1825 | }
1826 | } else {
1827 | elObject.css({width: sizeConfig.width});
1828 |
1829 | if (sizeConfig.height !== undefined) {
1830 | elObject.css({height: sizeConfig.height});
1831 | } else {
1832 | elObject.css({height: (elObject.width() * sizeConfig.rate) + 'px'});
1833 | }
1834 | }
1835 |
1836 | if (!this.defaultSize) {
1837 | this.defaultSize = {
1838 | width: elObject.width(),
1839 | height: elObject.height()
1840 | };
1841 | }
1842 |
1843 | elObject.css({maxWidth: '100%'});
1844 | this.rateScreenSize();
1845 |
1846 | return this;
1847 | }
1848 |
1849 | /**
1850 | * Rate screen size
1851 | */
1852 | rateScreenSize() {
1853 | let elObject = this.app.config.el('elements.object');
1854 | let runnerSize = 0;
1855 | let h = 0;
1856 |
1857 | if (this.isLarge) {
1858 | runnerSize = elObject.parent().width();
1859 | elObject.css({width: runnerSize + 'px'})
1860 |
1861 | h = (runnerSize * this.defaultSize.height / this.defaultSize.width);
1862 | let windowH = __dp.node(window).height() * 85 / 100;
1863 |
1864 | if (h > windowH) {
1865 | h = windowH;
1866 | }
1867 | } else {
1868 | runnerSize = elObject.width();
1869 | h = (runnerSize * this.defaultSize.height / this.defaultSize.width);
1870 | }
1871 |
1872 | elObject.css({height: h + 'px'});
1873 | this.app.event.trigger('dp.screen.change');
1874 |
1875 | return this;
1876 | }
1877 |
1878 | /**
1879 | * Make icon
1880 | * @param isFull
1881 | */
1882 | makeIconForFullScreen(isFull) {
1883 | let icons = this.app.config.get('icons');
1884 | let elBtnFullScreen = this.app.config.el('elements.controlFullScreen');
1885 |
1886 | if (isFull === undefined) {
1887 | isFull = document.fullscreenElement
1888 | || document.mozFullScreenElement
1889 | || document.webkitFullscreenElement;
1890 | }
1891 |
1892 | if (isFull) {
1893 | elBtnFullScreen.html(icons.actualScreen);
1894 | } else {
1895 | elBtnFullScreen.html(icons.fullScreen);
1896 | }
1897 |
1898 | return this;
1899 | }
1900 |
1901 | /**
1902 | * Toggle
1903 | * @param event
1904 | */
1905 | toggleFullScreen() {
1906 | let elContainer = this.app.config.el('elements.container');
1907 | let isFullScreen = document.webkitIsFullScreen || document.mozFullScreen || false;
1908 | let container = elContainer.node();
1909 | let instance = this;
1910 |
1911 | container.requestFullScreen = container.requestFullScreen || container.webkitRequestFullScreen || container.mozRequestFullScreen || function () {
1912 | return false;
1913 | };
1914 |
1915 | document.cancelFullScreen = document.cancelFullScreen || document.webkitCancelFullScreen || document.mozCancelFullScreen || function () {
1916 | return false;
1917 | };
1918 |
1919 | isFullScreen ? (function () {
1920 | instance.app.event.trigger('dp.screen.full.inactive');
1921 | document.cancelFullScreen();
1922 | })() : (function () {
1923 | instance.app.event.trigger('dp.screen.full.active');
1924 | container.requestFullScreen();
1925 | })();
1926 |
1927 | return this;
1928 | }
1929 |
1930 | /**
1931 | * Make icon
1932 | * @param isFull
1933 | */
1934 | makeIconForLargeScreen(isLg) {
1935 | let icons = this.app.config.get('icons');
1936 | let elBtnLargeScreen = this.app.config.el('elements.controlLargeScreen');
1937 |
1938 | if (isLg === undefined) {
1939 | isLg = this.isLarge;
1940 | }
1941 |
1942 | if (isLg) {
1943 | elBtnLargeScreen.html(icons.smallScreen);
1944 | } else {
1945 | elBtnLargeScreen.html(icons.largeScreen);
1946 | }
1947 |
1948 | return this;
1949 | }
1950 |
1951 | /**
1952 | * Toggle
1953 | * @param event
1954 | */
1955 | toggleLargeScreen() {
1956 | if (this.isLarge) {
1957 | this.isLarge = false;
1958 | this.app.event.trigger('dp.screen.large.inactive');
1959 | this.defaultScreen();
1960 | } else {
1961 | this.isLarge = true;
1962 | this.app.event.trigger('dp.screen.large.active');
1963 | this.rateScreenSize();
1964 | }
1965 |
1966 | return this;
1967 | }
1968 |
1969 | /**
1970 | * Init
1971 | * @return {DPScreen}
1972 | */
1973 | init() {
1974 | // Defined the common variable for object
1975 | this.isLarge = false;
1976 | this.defaultSize = null;
1977 |
1978 | let elBtnFullScreen = this.app.config.el('elements.controlFullScreen');
1979 | let elBtnLargeScreen = this.app.config.el('elements.controlLargeScreen');
1980 | let largeScreen = this.app.config.get('largeScreen');
1981 | let instance = this;
1982 |
1983 | // Event when click on button fullscreen
1984 | // Then call to check full or cancel
1985 | elBtnFullScreen.listen('click', function (event) {
1986 | instance.toggleFullScreen();
1987 | });
1988 |
1989 | // Event when click on button large
1990 | // Then call to check large or cancel
1991 | elBtnLargeScreen.listen('click', function (event) {
1992 | instance.toggleLargeScreen();
1993 | instance.makeIconForLargeScreen();
1994 | });
1995 |
1996 | // Event when change screen
1997 | // Then get status and change icon
1998 | __dp.node(document).listen("fullscreenchange webkitfullscreenchange mozfullscreenchange", function () {
1999 | instance.makeIconForFullScreen();
2000 | });
2001 |
2002 | // Event when window resize
2003 | __dp.node(window).listen('resize', function () {
2004 | instance.rateScreenSize();
2005 | });
2006 |
2007 | // Call when init screen
2008 | this.defaultScreen();
2009 | this.makeIconForFullScreen(false);
2010 |
2011 | // Check if config is setting true large as default
2012 | if (largeScreen) {
2013 | instance.toggleLargeScreen();
2014 | }
2015 |
2016 | this.makeIconForLargeScreen();
2017 |
2018 | return this;
2019 | }
2020 | }
2021 |
2022 | // ====================================================
2023 | // Class {DPSchedule}
2024 | // ====================================================
2025 | class DPSchedule extends DPBase {
2026 | constructor(app) {
2027 | super();
2028 | this.app = app;
2029 | }
2030 |
2031 | /**
2032 | * Run
2033 | */
2034 | init() {
2035 | // Common variable
2036 | this.helper = this.app.helper;
2037 | this.schedules = {};
2038 | this.alias = {};
2039 | this.lastTime = null;
2040 |
2041 | let schedules = this.app.config.get('schedules');
2042 | let instance = this;
2043 | let runner = this.app.config.runner(true);
2044 | let runnerDom = runner.node();
2045 |
2046 | for (var i in schedules) {
2047 | // Add schedule to progress bar
2048 | if (this.schedules[schedules[i].at] === undefined) {
2049 | this.schedules[schedules[i].at] = [];
2050 | }
2051 |
2052 | schedules[i].name = schedules[i].name || Math.random().toString(36).substring(10);
2053 | this.alias[schedules[i].name] = schedules[i];
2054 | this.schedules[schedules[i].at].push(schedules[i]);
2055 | }
2056 |
2057 | // Event when timeupdate
2058 | runner.listen('timeupdate ', function (e) {
2059 | let current = runnerDom.currentTime;
2060 | let time = __dp.parseTime(current);
2061 |
2062 | if (this.lastTime === time) {
2063 | return;
2064 | }
2065 |
2066 | this.lastTime = time;
2067 |
2068 | let list = instance.or(instance.schedules[time], []);
2069 |
2070 | for (let i in list) {
2071 | instance.execute(list[i].name);
2072 |
2073 | if (list[i].loop !== true) {
2074 | delete instance.schedules[time][i];
2075 | }
2076 | }
2077 | });
2078 | }
2079 |
2080 | /**
2081 | * Execute schedule
2082 | * @param name
2083 | */
2084 | execute(name) {
2085 | let schedule = this.alias[name];
2086 | schedule.execute(this.app);
2087 | }
2088 | }
2089 |
2090 | // ====================================================
2091 | // Class {DPPlugin}
2092 | // ====================================================
2093 | class DPPlugin extends DPBase {
2094 | constructor(app) {
2095 | super();
2096 | this.app = app;
2097 | }
2098 |
2099 | /**
2100 | * Init
2101 | * @return {Promise}
2102 | */
2103 | async init() {
2104 | let list = this.app.config.get('plugins');
2105 |
2106 | for (let name in list) {
2107 | this.app[name] = await eval('new ' + list[name].className + '(this.app)');
2108 | this.app[name].init();
2109 | }
2110 |
2111 | return this;
2112 | }
2113 | }
2114 |
2115 | // ====================================================
2116 | // Class {DPSource}
2117 | // ====================================================
2118 | class DPSource extends DPBase {
2119 | /**
2120 | * Constructor
2121 | */
2122 | constructor(app) {
2123 | super();
2124 | this.app = app;
2125 | }
2126 |
2127 | /**
2128 | * Load
2129 | * @param sources
2130 | */
2131 | load(sources) {
2132 | if (this.app.rendered && sources !== undefined) {
2133 | let runner = this.app.config.runner(true);
2134 |
2135 | runner.html(this.app.translate.get('app.not_support'));
2136 |
2137 | // Generate video from resources
2138 | if (typeof sources === 'string') {
2139 | runner.node().src = sources;
2140 | } else if (sources.length == 1) {
2141 | runner.node().src = sources[0].src;
2142 | } else {
2143 | for (var i in sources) {
2144 | let source = document.createElement('source');
2145 | __dp.node(source).attr({src: sources[i].src, type: sources[i].type});
2146 | runner.append(source);
2147 | }
2148 | }
2149 |
2150 | runner.node().load();
2151 | }
2152 |
2153 | return this;
2154 | }
2155 |
2156 | /**
2157 | * Play
2158 | * @return {DPSource}
2159 | */
2160 | play() {
2161 | if (this.app.rendered) {
2162 | let runner = this.app.config.runner(true).node();
2163 | runner.play();
2164 | }
2165 |
2166 | return this;
2167 | }
2168 |
2169 | /**
2170 | * Pause
2171 | * @return {DPSource}
2172 | */
2173 | pause() {
2174 | if (this.app.rendered) {
2175 | let runner = this.app.config.runner(true).node();
2176 | runner.pause();
2177 | }
2178 |
2179 | return this;
2180 | }
2181 |
2182 | /**
2183 | * Start At
2184 | * @param time
2185 | * @return {DPSource}
2186 | */
2187 | to(time) {
2188 | let runner = this.app.config.runner(true).node();
2189 |
2190 | if (isNaN(time)) {
2191 | time = time.split(':');
2192 |
2193 | if (time.length === 3) {
2194 | time = time[2] * 1 + time[1] * 60 + time[0] * 3600;
2195 | } else if (time.length === 2) {
2196 | time = time[1] * 1 + time[0] * 60;
2197 | } else {
2198 | time = time[0] * 1;
2199 | }
2200 | }
2201 |
2202 | runner.currentTime = time;
2203 |
2204 | return this;
2205 | }
2206 |
2207 | /**
2208 | * Init
2209 | * @return {DPSource}
2210 | */
2211 | init() {
2212 | // Get list of source
2213 | let sources = this.app.config.get('sources');
2214 | let runner = this.app.config.runner(true);
2215 | let event = this.app.event;
2216 | let startAt = this.app.config.get('startAt');
2217 |
2218 | this.load(sources);
2219 |
2220 | // Event when video play
2221 | // Event when runner play
2222 | runner.listen('play', function () {
2223 | event.trigger('dp.source.play');
2224 | });
2225 |
2226 | // Event when runner pause or ended
2227 | runner.listen('pause', function () {
2228 | event.trigger('dp.source.pause');
2229 | });
2230 |
2231 | // Event when runner pause or ended
2232 | runner.listen('ended', function () {
2233 | event.trigger('dp.source.ended');
2234 | });
2235 |
2236 | // Start
2237 | this.to(startAt);
2238 |
2239 | return this;
2240 | }
2241 | }
2242 |
2243 | // ====================================================
2244 | // Class {DilationPlayer}
2245 | // ====================================================
2246 | class DilationPlayer extends DPBase {
2247 | /**
2248 | * Constructor
2249 | * @param config
2250 | */
2251 | constructor(object, config) {
2252 | super();
2253 |
2254 | if (config == undefined) {
2255 | config = {};
2256 | }
2257 |
2258 | config.elements = this.or(config.elements, {});
2259 | config.elements.object = object;
2260 |
2261 | this.rendered = false;
2262 | this.config = new DPConfig(config);
2263 | this.event = new DPEvent(this);
2264 | this.contextEvent();
2265 |
2266 | this.translate = new DPTranslator(this);
2267 | this.view = new DPView(this);
2268 |
2269 | this.source = new DPSource(this);
2270 | this.control = new DPControl(this);
2271 | this.screen = new DPScreen(this);
2272 | this.menu = new DPMenu(this);
2273 | this.logo = new DPLogo(this);
2274 | this.modal = new DPModal(this);
2275 | this.plugin = new DPPlugin(this);
2276 | this.schedule = new DPSchedule(this);
2277 |
2278 | this.apply();
2279 | }
2280 |
2281 | /**
2282 | * Apply
2283 | */
2284 | async apply() {
2285 | await this.render();
2286 |
2287 | // Regist events
2288 | this.contextSource()
2289 | .contextModal()
2290 | .contextLogo()
2291 | .contextControl()
2292 | .contextScreen()
2293 | .playPause()
2294 | .progress()
2295 | .sound()
2296 | .contextMenu()
2297 | .contextPlugin()
2298 | .contextSchedule();
2299 | }
2300 |
2301 | /**
2302 | * Render view
2303 | * @return {Promise}
2304 | */
2305 | async render() {
2306 | let rendered = await this.view.init().render();
2307 | this.rendered = rendered;
2308 |
2309 | return rendered;
2310 | }
2311 |
2312 | /**
2313 | * Toggle play pause
2314 | * @return {DilationPlayer}
2315 | */
2316 | playPause() {
2317 | // Defined elements
2318 | let runner = this.config.runner(true);
2319 | let player = this.config.el('elements.playerModal');
2320 | let btn = this.config.el('elements.controlPlayPause');
2321 | let icons = this.config.get('icons');
2322 | let runnerDom = runner.node();
2323 | let instance = this;
2324 |
2325 | /**
2326 | * Helper
2327 | * @type {{toggle: toggle, makeIcon: makeIcon}}
2328 | */
2329 | let helper = {
2330 | /**
2331 | * Toggle play or pause
2332 | */
2333 | toggle: function () {
2334 | if (!isNaN(runnerDom.duration)) {
2335 | if (runnerDom.paused) {
2336 | runnerDom.play();
2337 | } else {
2338 | runnerDom.pause();
2339 | }
2340 | }
2341 | },
2342 |
2343 | /**
2344 | * Make icon
2345 | */
2346 | makeIcon: function () {
2347 | if (runnerDom.paused) {
2348 | btn.html(icons.play);
2349 | } else {
2350 | btn.html(icons.pause);
2351 | }
2352 | }
2353 | };
2354 |
2355 | // Event when loader show/hide
2356 | this.event.listen('dp.modal.loader.show', function(){
2357 | btn.html(icons.play);
2358 | });
2359 |
2360 | this.event.listen('dp.modal.loader.hide', function(){
2361 | helper.makeIcon();
2362 | });
2363 |
2364 | // Event when click on button play/pause
2365 | btn.listen('click', function () {
2366 | helper.toggle();
2367 | });
2368 |
2369 | player.listen('click', function () {
2370 | helper.toggle();
2371 | });
2372 |
2373 | // Event when click on runner
2374 | runner.listen('click', function () {
2375 | helper.toggle();
2376 | });
2377 |
2378 | // Event when runner play
2379 | runner.listen('play', function () {
2380 | helper.makeIcon();
2381 | });
2382 |
2383 | // Event when runner pause or ended
2384 | runner.listen('pause ended', function () {
2385 | helper.makeIcon();
2386 | });
2387 |
2388 | // Init display icon in button play/pause
2389 | helper.makeIcon();
2390 |
2391 | return this;
2392 | }
2393 |
2394 | /**
2395 | * Progress
2396 | * @return {DilationPlayer}
2397 | */
2398 | progress() {
2399 | let instance = this;
2400 | let runner = this.config.runner(true);
2401 | let runnerDom = runner.node();
2402 | let progressBar = this.config.el('elements.progress');
2403 | let playing = this.config.el('elements.progressPlaying');
2404 | let timer = this.config.el('elements.controlTimer');
2405 | let progressTimerTooltipText = this.config.el('elements.progressHoverTooltipText');
2406 | let progressTimerTooltipImage = this.config.el('elements.progressHoverTooltipImage');
2407 | let tooltipCanvas = progressTimerTooltipImage.find('canvas').node();
2408 | tooltipCanvas.width = 90;
2409 | tooltipCanvas.height = 70;
2410 |
2411 | // Create preview elements
2412 | // let runnerPreview = document.createElement('video');
2413 |
2414 | // runner.find('source').each(function (num, val) {
2415 | // var source = document.createElement('source');
2416 | // source.src = __dp.node(this).attr('src');
2417 | // runnerPreview.append(source);
2418 | // });
2419 |
2420 | // runnerPreview.load();
2421 |
2422 | /**
2423 | * Helper object
2424 | * @type {{pad: (function(*, *, *=): *), setLoaded: setLoaded, setTimer: setTimer, display: display}}
2425 | */
2426 | let helper = {
2427 | isShowImage: this.config.get('preview'),
2428 |
2429 | /**
2430 | * Set loaded data
2431 | * @param current
2432 | * @param duration
2433 | */
2434 | setLoaded: function (current, duration) {
2435 | playing.width((current / duration * 100) + '%');
2436 | },
2437 |
2438 | /**
2439 | * Set timer
2440 | * @param current
2441 | * @param duration
2442 | */
2443 | setTimer: function (current, duration) {
2444 | current = __dp.parseTime(current);
2445 | duration = __dp.parseTime(duration);
2446 | timer.html(current + ' / ' + duration);
2447 | },
2448 |
2449 | showImage: function(left){
2450 | if (this.isShowImage !== false && this.isShowImage !== undefined) {
2451 | let totalWidth = progressBar.width();
2452 | let width = progressTimerTooltipImage.width() / 2;
2453 | let iLeft = left;
2454 | if (left > (totalWidth - width)) {
2455 | iLeft = totalWidth - width;
2456 | } else if (left < width) {
2457 | iLeft = width;
2458 | }
2459 |
2460 | progressTimerTooltipImage.css('left', iLeft + 'px');
2461 | progressTimerTooltipImage.active(true);
2462 | } else {
2463 | progressTimerTooltipImage.active(false);
2464 | }
2465 | },
2466 |
2467 | showTime: function(left, time) {
2468 | progressTimerTooltipText.active(true);
2469 | let totalWidth = progressBar.width();
2470 | let width = progressTimerTooltipText.width() / 2;
2471 | let tLeft = left;
2472 |
2473 | if (left > (totalWidth - width - 2)) {
2474 | tLeft = totalWidth - width - 2;
2475 | } else if (left < (width + 2)) {
2476 | tLeft = width + 2;
2477 | }
2478 |
2479 | let parseTime = __dp.parseTime(time);
2480 | progressTimerTooltipText.css('left', tLeft + 'px').text(parseTime);
2481 | },
2482 |
2483 | /**
2484 | * Display
2485 | */
2486 | display: function () {
2487 | if (!isNaN(runnerDom.duration)) {
2488 | let current = runnerDom.currentTime;
2489 | let duration = runnerDom.duration;
2490 |
2491 | helper.setLoaded(current, duration);
2492 | helper.setTimer(current, duration);
2493 | }
2494 | }
2495 | };
2496 |
2497 | // Event when timeupdate
2498 | runner.listen('timeupdate ', function (e) {
2499 | helper.display();
2500 | });
2501 |
2502 | // Event when click on progress bar
2503 | // Then get position of mouse and count the time go to
2504 | progressBar.listen("click", function (e) {
2505 | if (!isNaN(runnerDom.duration)) {
2506 | let offset = __dp.node(this).offset();
2507 | let left = (e.pageX - offset.left);
2508 | let totalWidth = progressBar.width();
2509 | let percentage = (left / totalWidth);
2510 | let vidTime = runnerDom.duration * percentage;
2511 | instance.source.to(vidTime);
2512 | helper.setLoaded(left, totalWidth);
2513 | }
2514 | });
2515 |
2516 | // Event when move on progress
2517 | // Then get position of mouse, count the time go to and get information
2518 | progressBar.listen("mousemove", function (e) {
2519 | if (!isNaN(runnerDom.duration)) {
2520 | let offset = __dp.node(this).offset();
2521 | let left = (e.pageX - offset.left);
2522 | let totalWidth = progressBar.width();
2523 | let percentage = (left / totalWidth);
2524 | let current = runnerDom.duration * percentage;
2525 |
2526 | // Set position for image
2527 | helper.showImage(left, current);
2528 | helper.showTime(left, current);
2529 | } else {
2530 | progressTimerTooltipText.active(false);
2531 | progressTimerTooltipImage.active(false);
2532 | }
2533 | });
2534 |
2535 | // Event when loaded data
2536 | // Then call display information on screen
2537 | runner.listen('loadeddata', function (e) {
2538 | helper.display();
2539 | });
2540 |
2541 | return this;
2542 | }
2543 |
2544 | /**
2545 | * Sound
2546 | * @return {DilationPlayer}
2547 | */
2548 | sound() {
2549 | // Defined elements
2550 | let runner = this.config.runner(true);
2551 | let runnerDom = runner.node();
2552 | let volume = this.config.el('elements.controlVolume');
2553 | let volumeRange = this.config.el('elements.controlVolumeRange');
2554 | let range = this.config.get('volume');
2555 | let icons = this.config.get('icons');
2556 | // let instance = this;
2557 |
2558 | /**
2559 | * Helper
2560 | * @type {{makeIcon: makeIcon, setVolume: setVolume, toggleMute: toggleMute}}
2561 | */
2562 | let helper = {
2563 | /**
2564 | * Make icon for button
2565 | */
2566 | makeIcon: function () {
2567 | if (runnerDom.muted == true || runnerDom.volume == 0) {
2568 | volume.html(icons.volumeMute);
2569 | } else if (runnerDom.volume <= 0.5) {
2570 | volume.html(icons.volume1);
2571 | } else {
2572 | volume.html(icons.volume2);
2573 | }
2574 | },
2575 |
2576 | /**
2577 | * Set volume for runner
2578 | * @param number
2579 | */
2580 | setVolume: function (number) {
2581 | runnerDom.volume = number / 100;
2582 |
2583 | if (runnerDom.volume > 0) {
2584 | runnerDom.muted = false;
2585 | }
2586 | },
2587 |
2588 | /**
2589 | * Toggle mute runner
2590 | */
2591 | toggleMute: function () {
2592 | if (runnerDom.muted == true) {
2593 | runnerDom.muted = false;
2594 | } else if (runnerDom.volume > 0) {
2595 | runnerDom.muted = true;
2596 | }
2597 | }
2598 | };
2599 |
2600 |
2601 | // Event click on button
2602 | volume.listen('click', function () {
2603 | helper.toggleMute();
2604 | });
2605 |
2606 | // Event when change input of range
2607 | // Then call change volume and icon
2608 | volumeRange.listen('change', function () {
2609 | let range = __dp.node(this).val();
2610 | helper.setVolume(range);
2611 | });
2612 |
2613 | // Event when volume change
2614 | runner.listen('volumechange', function () {
2615 | helper.makeIcon();
2616 | });
2617 |
2618 | // Set volume default
2619 | helper.setVolume(range);
2620 | volumeRange.val(range);
2621 | helper.makeIcon();
2622 |
2623 | return this;
2624 | }
2625 |
2626 | /**
2627 | * Logo
2628 | * return {DilationPlayer}
2629 | */
2630 | contextLogo() {
2631 | this.logo.init();
2632 | return this;
2633 | }
2634 |
2635 | /**
2636 | * Toggle control
2637 | * @return {DilationPlayer}
2638 | */
2639 | contextControl() {
2640 | this.control.init();
2641 | return this;
2642 | }
2643 |
2644 | /**
2645 | * Context modal
2646 | * @return {DilationPlayer}
2647 | */
2648 | contextModal() {
2649 | this.modal.init();
2650 |
2651 | return this;
2652 | }
2653 |
2654 | /**
2655 | * Menu
2656 | * @return {DilationPlayer}
2657 | */
2658 | contextMenu() {
2659 | this.menu.init();
2660 | return this;
2661 | }
2662 |
2663 | /**
2664 | * Alarm
2665 | * @return {DilationPlayer}
2666 | */
2667 | contextSchedule() {
2668 | this.schedule.init();
2669 | return this;
2670 | }
2671 |
2672 | /**
2673 | * Plugin
2674 | * @return {DilationPlayer}
2675 | */
2676 | contextPlugin() {
2677 | this.plugin.init();
2678 | return this;
2679 | }
2680 |
2681 | /**
2682 | * Event
2683 | * @return {DilationPlayer}
2684 | */
2685 | contextEvent() {
2686 | this.event.init();
2687 | return this;
2688 | }
2689 |
2690 | /**
2691 | * Screen
2692 | * @return {DilationPlayer}
2693 | */
2694 | contextScreen() {
2695 | this.screen.init();
2696 | return this;
2697 | }
2698 |
2699 | /**
2700 | * Source
2701 | * @return {DilationPlayer}
2702 | */
2703 | contextSource() {
2704 | this.source.init();
2705 | return this;
2706 | }
2707 | }
--------------------------------------------------------------------------------