videojs-mobile-ui 0.7.0 → 0.9.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +114 -46
  2. package/dist/videojs-mobile-ui.cjs.js +275 -223
  3. package/dist/videojs-mobile-ui.css +2 -2
  4. package/dist/videojs-mobile-ui.es.js +270 -217
  5. package/dist/videojs-mobile-ui.js +278 -265
  6. package/dist/videojs-mobile-ui.min.js +2 -2
  7. package/docs/api/TouchOverlay.html +964 -0
  8. package/docs/api/fonts/OpenSans-Bold-webfont.eot +0 -0
  9. package/docs/api/fonts/OpenSans-Bold-webfont.svg +1830 -0
  10. package/docs/api/fonts/OpenSans-Bold-webfont.woff +0 -0
  11. package/docs/api/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
  12. package/docs/api/fonts/OpenSans-BoldItalic-webfont.svg +1830 -0
  13. package/docs/api/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
  14. package/docs/api/fonts/OpenSans-Italic-webfont.eot +0 -0
  15. package/docs/api/fonts/OpenSans-Italic-webfont.svg +1830 -0
  16. package/docs/api/fonts/OpenSans-Italic-webfont.woff +0 -0
  17. package/docs/api/fonts/OpenSans-Light-webfont.eot +0 -0
  18. package/docs/api/fonts/OpenSans-Light-webfont.svg +1831 -0
  19. package/docs/api/fonts/OpenSans-Light-webfont.woff +0 -0
  20. package/docs/api/fonts/OpenSans-LightItalic-webfont.eot +0 -0
  21. package/docs/api/fonts/OpenSans-LightItalic-webfont.svg +1835 -0
  22. package/docs/api/fonts/OpenSans-LightItalic-webfont.woff +0 -0
  23. package/docs/api/fonts/OpenSans-Regular-webfont.eot +0 -0
  24. package/docs/api/fonts/OpenSans-Regular-webfont.svg +1831 -0
  25. package/docs/api/fonts/OpenSans-Regular-webfont.woff +0 -0
  26. package/docs/api/global.html +957 -0
  27. package/docs/api/index.html +159 -0
  28. package/docs/api/plugin.js.html +221 -0
  29. package/docs/api/scripts/linenumber.js +25 -0
  30. package/docs/api/scripts/prettify/Apache-License-2.0.txt +202 -0
  31. package/docs/api/scripts/prettify/lang-css.js +2 -0
  32. package/docs/api/scripts/prettify/prettify.js +28 -0
  33. package/docs/api/styles/jsdoc-default.css +358 -0
  34. package/docs/api/styles/prettify-jsdoc.css +111 -0
  35. package/docs/api/styles/prettify-tomorrow.css +132 -0
  36. package/docs/api/swipeFullscreen.js.html +173 -0
  37. package/docs/api/touchOverlay.js.html +211 -0
  38. package/index.html +206 -65
  39. package/package.json +19 -16
  40. package/src/plugin.css +21 -3
  41. package/src/plugin.js +32 -59
  42. package/src/swipeFullscreen.js +117 -0
  43. package/src/touchOverlay.js +62 -56
  44. package/test/plugin.test.js +128 -20
  45. package/test/swipeFullscreen.test.js +365 -0
@@ -1,68 +1,41 @@
1
- /*! @name videojs-mobile-ui @version 0.7.0 @license MIT */
1
+ /*! @name videojs-mobile-ui @version 0.9.0-beta.3 @license MIT */
2
2
  (function (global, factory) {
3
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('video.js'), require('global/window')) :
4
- typeof define === 'function' && define.amd ? define(['video.js', 'global/window'], factory) :
5
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.videojsMobileUi = factory(global.videojs, global.window));
6
- }(this, (function (videojs, window) { 'use strict';
3
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('video.js')) :
4
+ typeof define === 'function' && define.amd ? define(['video.js'], factory) :
5
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.videojsMobileUi = factory(global.videojs));
6
+ })(this, (function (videojs) { 'use strict';
7
7
 
8
8
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
9
9
 
10
10
  var videojs__default = /*#__PURE__*/_interopDefaultLegacy(videojs);
11
- var window__default = /*#__PURE__*/_interopDefaultLegacy(window);
12
11
 
13
- var version = "0.7.0";
12
+ var version = "0.9.0-beta.3";
14
13
 
15
- function createCommonjsModule(fn, basedir, module) {
16
- return module = {
17
- path: basedir,
18
- exports: {},
19
- require: function (path, base) {
20
- return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
21
- }
22
- }, fn(module, module.exports), module.exports;
23
- }
24
-
25
- function commonjsRequire () {
26
- throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
27
- }
28
-
29
- var setPrototypeOf = createCommonjsModule(function (module) {
30
- function _setPrototypeOf(o, p) {
31
- module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
32
- o.__proto__ = p;
33
- return o;
34
- };
35
-
36
- module.exports["default"] = module.exports, module.exports.__esModule = true;
37
- return _setPrototypeOf(o, p);
38
- }
39
-
40
- module.exports = _setPrototypeOf;
41
- module.exports["default"] = module.exports, module.exports.__esModule = true;
42
- });
43
-
44
- var inheritsLoose = createCommonjsModule(function (module) {
45
- function _inheritsLoose(subClass, superClass) {
46
- subClass.prototype = Object.create(superClass.prototype);
47
- subClass.prototype.constructor = subClass;
48
- setPrototypeOf(subClass, superClass);
49
- }
14
+ /**
15
+ * @file touchOverlay.js
16
+ * Touch UI component
17
+ */
50
18
 
51
- module.exports = _inheritsLoose;
52
- module.exports["default"] = module.exports, module.exports.__esModule = true;
53
- });
19
+ /** @import Player from 'video.js/dist/types/player' */
20
+
21
+ const Component = videojs__default["default"].getComponent('Component');
22
+ const dom = videojs__default["default"].dom || videojs__default["default"];
23
+ const debounce = (callback, wait) => {
24
+ let timeoutId = null;
25
+ return (...args) => {
26
+ window.clearTimeout(timeoutId);
27
+ timeoutId = window.setTimeout(() => {
28
+ callback.apply(null, args);
29
+ }, wait);
30
+ };
31
+ };
54
32
 
55
- var Component = videojs__default['default'].getComponent('Component');
56
- var dom = videojs__default['default'].dom || videojs__default['default'];
57
33
  /**
58
34
  * The `TouchOverlay` is an overlay to capture tap events.
59
35
  *
60
36
  * @extends Component
61
37
  */
62
-
63
- var TouchOverlay = /*#__PURE__*/function (_Component) {
64
- inheritsLoose(TouchOverlay, _Component);
65
-
38
+ class TouchOverlay extends Component {
66
39
  /**
67
40
  * Creates an instance of the this class.
68
41
  *
@@ -72,46 +45,80 @@
72
45
  * @param {Object} [options]
73
46
  * The key/value store of player options.
74
47
  */
75
- function TouchOverlay(player, options) {
76
- var _this;
77
-
78
- _this = _Component.call(this, player, options) || this;
79
- _this.seekSeconds = options.seekSeconds;
80
- _this.tapTimeout = options.tapTimeout; // Add play toggle overlay
81
-
82
- _this.addChild('playToggle', {}); // Clear overlay when playback starts or with control fade
83
-
84
-
85
- player.on(['playing', 'userinactive'], function (e) {
86
- _this.removeClass('show-play-toggle');
87
- }); // A 0 inactivity timeout won't work here
48
+ constructor(player, options) {
49
+ super(player, options);
50
+ this.seekSeconds = options.seekSeconds;
51
+ this.tapTimeout = options.tapTimeout;
52
+ this.taps = 0;
53
+
54
+ // Add play toggle overlay
55
+ this.addChild('playToggle', {});
56
+
57
+ // Clear overlay when playback starts or with control fade
58
+ player.on(['playing', 'userinactive'], e => {
59
+ this.removeClass('show-play-toggle');
60
+ });
88
61
 
89
- if (_this.player_.options_.inactivityTimeout === 0) {
90
- _this.player_.options_.inactivityTimeout = 5000;
62
+ // A 0 inactivity timeout won't work here
63
+ if (this.player_.options_.inactivityTimeout === 0) {
64
+ this.player_.options_.inactivityTimeout = 5000;
91
65
  }
92
66
 
93
- _this.enable();
67
+ /**
68
+ * Debounced tap handler.
69
+ * Seeks number of (taps - 1) * configured seconds to skip.
70
+ * One tap is a non-op
71
+ *
72
+ * @param {Event} event
73
+ */
74
+ this.handleTaps_ = debounce(event => {
75
+ const increment = (this.taps - 1) * this.seekSeconds;
76
+ this.taps = 0;
77
+ if (increment < 1) {
78
+ return;
79
+ }
80
+ const rect = this.el_.getBoundingClientRect();
81
+ const x = event.changedTouches[0].clientX - rect.left;
82
+
83
+ // Check if double tap is in left or right area
84
+ if (x < rect.width * 0.4) {
85
+ this.player_.currentTime(Math.max(0, this.player_.currentTime() - increment));
86
+ this.addClass('reverse');
87
+ } else if (x > rect.width - rect.width * 0.4) {
88
+ this.player_.currentTime(Math.min(this.player_.duration(), this.player_.currentTime() + increment));
89
+ this.removeClass('reverse');
90
+ } else {
91
+ return;
92
+ }
93
+
94
+ // Remove play toggle if showing
95
+ this.removeClass('show-play-toggle');
94
96
 
95
- return _this;
97
+ // Remove and readd class to trigger animation
98
+ this.setAttribute('data-skip-text', `${increment} ${this.localize('seconds')}`);
99
+ this.removeClass('skip');
100
+ window.requestAnimationFrame(() => {
101
+ this.addClass('skip');
102
+ });
103
+ }, this.tapTimeout);
104
+ this.enable();
96
105
  }
106
+
97
107
  /**
98
108
  * Builds the DOM element.
99
109
  *
100
110
  * @return {Element}
101
111
  * The DOM element.
102
112
  */
103
-
104
-
105
- var _proto = TouchOverlay.prototype;
106
-
107
- _proto.createEl = function createEl() {
108
- var el = dom.createEl('div', {
113
+ createEl() {
114
+ const el = dom.createEl('div', {
109
115
  className: 'vjs-touch-overlay',
110
116
  // Touch overlay is not tabbable.
111
117
  tabIndex: -1
112
118
  });
113
119
  return el;
114
120
  }
121
+
115
122
  /**
116
123
  * Debounces to either handle a delayed single tap, or a double tap
117
124
  *
@@ -119,110 +126,166 @@
119
126
  * The touch event
120
127
  *
121
128
  */
122
- ;
123
-
124
- _proto.handleTap = function handleTap(event) {
125
- var _this2 = this;
126
-
129
+ handleTap(event) {
127
130
  // Don't handle taps on the play button
128
131
  if (event.target !== this.el_) {
129
132
  return;
130
133
  }
131
-
132
- event.preventDefault();
133
-
134
- if (this.firstTapCaptured) {
135
- this.firstTapCaptured = false;
136
-
137
- if (this.timeout) {
138
- window__default['default'].clearTimeout(this.timeout);
139
- }
140
-
141
- this.handleDoubleTap(event);
142
- } else {
143
- this.firstTapCaptured = true;
144
- this.timeout = window__default['default'].setTimeout(function () {
145
- _this2.firstTapCaptured = false;
146
-
147
- _this2.handleSingleTap(event);
148
- }, this.tapTimeout);
134
+ if (event.cancelable) {
135
+ event.preventDefault();
136
+ }
137
+ this.taps += 1;
138
+ if (this.taps === 1) {
139
+ this.removeClass('skip');
140
+ this.toggleClass('show-play-toggle');
149
141
  }
142
+ this.handleTaps_(event);
150
143
  }
144
+
151
145
  /**
152
- * Toggles display of play toggle
153
- *
154
- * @param {Event} event
155
- * The touch event
156
- *
146
+ * Enables touch handler
157
147
  */
158
- ;
159
-
160
- _proto.handleSingleTap = function handleSingleTap(event) {
161
- this.removeClass('skip');
162
- this.toggleClass('show-play-toggle');
148
+ enable() {
149
+ this.firstTapCaptured = false;
150
+ this.on('touchend', this.handleTap);
163
151
  }
152
+
164
153
  /**
165
- * Seeks by configured number of seconds if left or right part of video double tapped
166
- *
167
- * @param {Event} event
168
- * The touch event
169
- *
154
+ * Disables touch handler
170
155
  */
171
- ;
172
-
173
- _proto.handleDoubleTap = function handleDoubleTap(event) {
174
- var _this3 = this;
156
+ disable() {
157
+ this.off('touchend', this.handleTap);
158
+ }
159
+ }
160
+ Component.registerComponent('TouchOverlay', TouchOverlay);
175
161
 
176
- var rect = this.el_.getBoundingClientRect();
177
- var x = event.changedTouches[0].clientX - rect.left; // Check if double tap is in left or right area
162
+ /**
163
+ * Sets up swiping to enter and exit fullscreen.
164
+ *
165
+ * @param {Object} player
166
+ * The player to initialise on.
167
+ * @param {Object} pluginOptions
168
+ * The options used by the mobile ui plugin.
169
+ */
170
+ const initSwipe = (player, pluginOptions) => {
171
+ const {
172
+ swipeToFullscreen,
173
+ swipeFromFullscreen
174
+ } = pluginOptions.fullscreen;
175
+ if (swipeToFullscreen) {
176
+ player.addClass('using-fs-swipe-up');
177
+ }
178
+ if (swipeFromFullscreen) {
179
+ player.addClass('using-fs-swipe-down');
180
+ }
181
+ let touchStartY = 0;
182
+ let couldBeSwiping = false;
183
+ const swipeThreshold = 30;
178
184
 
179
- if (x < rect.width * 0.4) {
180
- this.player_.currentTime(Math.max(0, this.player_.currentTime() - this.seekSeconds));
181
- this.addClass('reverse');
182
- } else if (x > rect.width - rect.width * 0.4) {
183
- this.player_.currentTime(Math.min(this.player_.duration(), this.player_.currentTime() + this.seekSeconds));
184
- this.removeClass('reverse');
185
- } else {
185
+ /**
186
+ * Monitor the possible start of a swipe
187
+ *
188
+ * @param {TouchEvent} e Triggering touch event
189
+ */
190
+ const onStart = e => {
191
+ const isFullscreen = player.isFullscreen();
192
+ if (!isFullscreen && !swipeToFullscreen || isFullscreen && !swipeFromFullscreen) {
193
+ couldBeSwiping = false;
186
194
  return;
187
- } // Remove play toggle if showing
188
-
189
-
190
- this.removeClass('show-play-toggle'); // Remove and readd class to trigger animation
195
+ }
196
+ touchStartY = e.changedTouches[0].clientY;
197
+ couldBeSwiping = true;
198
+ player.tech_.el().style.transition = '';
199
+ };
191
200
 
192
- this.removeClass('skip');
193
- window__default['default'].requestAnimationFrame(function () {
194
- _this3.addClass('skip');
195
- });
196
- }
197
201
  /**
198
- * Enables touch handler
202
+ * Monitor the movement of a swipe
203
+ *
204
+ * @param {TouchEvent} e Triggering touch event
199
205
  */
200
- ;
206
+ const onMove = e => {
207
+ if (!couldBeSwiping) {
208
+ return;
209
+ }
210
+ const currentY = e.touches[0].clientY;
211
+ const deltaY = touchStartY - currentY;
212
+ const isFullscreen = player.isFullscreen();
213
+ let scale = 1;
214
+ if (!isFullscreen && deltaY > 0) {
215
+ // Swiping up to enter fullscreen: Zoom in (Max 1.1)
216
+ scale = 1 + Math.min(0.1, deltaY / 500);
217
+ player.tech_.el().style.transform = `scale(${scale})`;
218
+ } else if (isFullscreen && deltaY < 0) {
219
+ // Swiping down to exit fullscreen: Zoom out (Min 0.9)
220
+ scale = 1 - Math.min(0.1, Math.abs(deltaY) / 500);
221
+ player.tech_.el().style.transform = `scale(${scale})`;
222
+ }
223
+ };
201
224
 
202
- _proto.enable = function enable() {
203
- this.firstTapCaptured = false;
204
- this.on('touchend', this.handleTap);
205
- }
206
225
  /**
207
- * Disables touch handler
226
+ * Monitor the touch end to determine a valid swipe
227
+ *
228
+ * @param {TouchEvent} e Triggering touch event
208
229
  */
209
- ;
210
-
211
- _proto.disable = function disable() {
212
- this.off('touchend', this.handleTap);
230
+ const onEnd = e => {
231
+ if (!couldBeSwiping) {
232
+ return;
233
+ }
234
+ couldBeSwiping = false;
235
+ player.tech_.el().style.transition = 'transform 0.3s ease-out';
236
+ player.tech_.el().style.transform = 'scale(1)';
237
+ if (e.type === 'touchcancel') {
238
+ return;
239
+ }
240
+ const touchEndY = e.changedTouches[0].clientY;
241
+ const deltaY = touchStartY - touchEndY;
242
+ if (deltaY > swipeThreshold && !player.isFullscreen()) {
243
+ player.requestFullscreen().catch(err => {
244
+ player.log.warn('Browser refused fullscreen', err);
245
+ });
246
+ } else if (deltaY < -swipeThreshold && player.isFullscreen()) {
247
+ player.exitFullscreen();
248
+ }
213
249
  };
250
+ player.el().addEventListener('touchstart', onStart, {
251
+ passive: true
252
+ });
253
+ player.el().addEventListener('touchmove', onMove, {
254
+ passive: true
255
+ });
256
+ player.el().addEventListener('touchend', onEnd, {
257
+ passive: true
258
+ });
259
+ player.el().addEventListener('touchcancel', onEnd, {
260
+ passive: true
261
+ });
262
+ player.on('dispose', () => {
263
+ player.el().removeEventListener('touchstart', onStart, {
264
+ passive: true
265
+ });
266
+ player.el().removeEventListener('touchmove', onMove, {
267
+ passive: true
268
+ });
269
+ player.el().removeEventListener('touchend', onEnd, {
270
+ passive: true
271
+ });
272
+ player.el().removeEventListener('touchcancel', onEnd, {
273
+ passive: true
274
+ });
275
+ player.tech_.el().style.transform = '';
276
+ player.tech_.el().style.transition = '';
277
+ });
278
+ };
214
279
 
215
- return TouchOverlay;
216
- }(Component);
217
-
218
- Component.registerComponent('TouchOverlay', TouchOverlay);
219
-
220
- var defaults = {
280
+ // Default options for the plugin.
281
+ const defaults = {
221
282
  fullscreen: {
222
283
  enterOnRotate: true,
223
284
  exitOnRotate: true,
224
285
  lockOnRotate: true,
225
- iOS: false,
286
+ lockToLandscapeOnEnter: false,
287
+ swipeToFullscreen: false,
288
+ swipeFromFullscreen: false,
226
289
  disabled: false
227
290
  },
228
291
  touchControls: {
@@ -232,37 +295,33 @@
232
295
  disabled: false
233
296
  }
234
297
  };
235
- var screen = window__default['default'].screen;
298
+ const screen = window.screen;
299
+ const registerPlugin = videojs__default["default"].registerPlugin || videojs__default["default"].plugin;
300
+
236
301
  /**
237
302
  * Gets 'portrait' or 'lanscape' from the two orientation APIs
238
303
  *
239
304
  * @return {string} orientation
240
305
  */
241
-
242
- var getOrientation = function getOrientation() {
306
+ const getOrientation = () => {
243
307
  if (screen) {
244
308
  // Prefer the string over angle, as 0° can be landscape on some tablets
245
- var orientationString = ((screen.orientation || {}).type || screen.mozOrientation || screen.msOrientation || '').split('-')[0];
246
-
309
+ const orientationString = ((screen.orientation || {}).type || screen.mozOrientation || screen.msOrientation || '').split('-')[0];
247
310
  if (orientationString === 'landscape' || orientationString === 'portrait') {
248
311
  return orientationString;
249
312
  }
250
- } // iOS only supports window.orientation
251
-
313
+ }
252
314
 
253
- if (typeof window__default['default'].orientation === 'number') {
254
- if (window__default['default'].orientation === 0 || window__default['default'].orientation === 180) {
315
+ // iOS only supports window.orientation
316
+ if (typeof window.orientation === 'number') {
317
+ if (window.orientation === 0 || window.orientation === 180) {
255
318
  return 'portrait';
256
319
  }
257
-
258
320
  return 'landscape';
259
321
  }
260
-
261
322
  return 'portrait';
262
- }; // Cross-compatibility for Video.js 5 and 6.
263
-
323
+ };
264
324
 
265
- var registerPlugin = videojs__default['default'].registerPlugin || videojs__default['default'].plugin;
266
325
  /**
267
326
  * Add UI and event listeners
268
327
  *
@@ -270,63 +329,49 @@
270
329
  * @param {Player} player
271
330
  * A Video.js player object.
272
331
  *
273
- * @param {Object} [options={}]
332
+ * @param {MobileUiOptions} [options={}]
274
333
  * A plain object containing options for the plugin.
275
334
  */
276
-
277
- var onPlayerReady = function onPlayerReady(player, options) {
335
+ const onPlayerReady = (player, options) => {
278
336
  player.addClass('vjs-mobile-ui');
279
-
280
- if (options.fullscreen.iOS) {
281
- videojs__default['default'].log.warn('videojs-mobile-ui: `fullscreen.iOS` is deprecated. Use Video.js option `preferFullWindow` instead.');
282
-
283
- if (videojs__default['default'].browser.IS_IOS && videojs__default['default'].browser.IOS_VERSION > 9 && !player.el_.ownerDocument.querySelector('.bc-iframe')) {
284
- player.tech_.el_.setAttribute('playsinline', 'playsinline');
285
-
286
- player.tech_.supportsFullScreen = function () {
287
- return false;
288
- };
289
- }
290
- }
291
-
292
337
  if (!options.touchControls.disabled) {
293
338
  if (options.touchControls.disableOnEnd || typeof player.endscreen === 'function') {
294
339
  player.addClass('vjs-mobile-ui-disable-end');
295
- } // Insert before the control bar
296
-
340
+ }
297
341
 
298
- var controlBarIdx;
299
- var versionParts = videojs__default['default'].VERSION.split('.');
300
- var major = parseInt(versionParts[0], 10);
301
- var minor = parseInt(versionParts[1], 10); // Video.js < 7.7.0 doesn't account for precedding components that don't have elements
342
+ // Insert before the control bar
343
+ let controlBarIdx;
344
+ const versionParts = videojs__default["default"].VERSION.split('.');
345
+ const major = parseInt(versionParts[0], 10);
346
+ const minor = parseInt(versionParts[1], 10);
302
347
 
348
+ // Video.js < 7.7.0 doesn't account for precedding components that don't have elements
303
349
  if (major < 7 || major === 7 && minor < 7) {
304
350
  controlBarIdx = Array.prototype.indexOf.call(player.el_.children, player.getChild('ControlBar').el_);
305
351
  } else {
306
352
  controlBarIdx = player.children_.indexOf(player.getChild('ControlBar'));
307
353
  }
308
-
309
354
  player.touchOverlay = player.addChild('TouchOverlay', options.touchControls, controlBarIdx);
310
355
  }
311
-
312
356
  if (options.fullscreen.disabled) {
313
357
  return;
314
358
  }
315
-
316
- var locked = false;
317
-
318
- var rotationHandler = function rotationHandler() {
319
- var currentOrientation = getOrientation();
320
-
359
+ if (options.fullscreen.swipeToFullscreen || options.fullscreen.swipeFromFullscreen) {
360
+ initSwipe(player, options);
361
+ }
362
+ let locked = false;
363
+ const rotationHandler = () => {
364
+ const currentOrientation = getOrientation();
321
365
  if (currentOrientation === 'landscape' && options.fullscreen.enterOnRotate) {
322
- if (player.paused() === false) {
323
- player.requestFullscreen();
324
-
325
- if (options.fullscreen.lockOnRotate && screen.orientation && screen.orientation.lock) {
326
- screen.orientation.lock('landscape').then(function () {
366
+ if (!player.paused() && !player.isFullscreen()) {
367
+ player.requestFullscreen().catch(err => {
368
+ player.log.warn('Browser refused fullscreen request:', err);
369
+ });
370
+ if ((options.fullscreen.lockOnRotate || options.fullscreen.lockToLandscapeOnEnter) && screen.orientation && screen.orientation.lock) {
371
+ screen.orientation.lock('landscape').then(() => {
327
372
  locked = true;
328
- }).catch(function (e) {
329
- videojs__default['default'].log('Browser refused orientation lock:', e);
373
+ }).catch(err => {
374
+ videojs__default["default"].log.warn('Browser refused orientation lock:', err);
330
375
  });
331
376
  }
332
377
  }
@@ -336,92 +381,60 @@
336
381
  }
337
382
  }
338
383
  };
339
-
340
384
  if (options.fullscreen.enterOnRotate || options.fullscreen.exitOnRotate) {
341
- if (videojs__default['default'].browser.IS_IOS) {
342
- window__default['default'].addEventListener('orientationchange', rotationHandler);
343
- player.on('dispose', function () {
344
- window__default['default'].removeEventListener('orientationchange', rotationHandler);
385
+ if (videojs__default["default"].browser.IS_IOS) {
386
+ window.addEventListener('orientationchange', rotationHandler);
387
+ player.on('dispose', () => {
388
+ window.removeEventListener('orientationchange', rotationHandler);
345
389
  });
346
390
  } else if (screen.orientation) {
347
391
  // addEventListener('orientationchange') is not a user interaction on Android
348
392
  screen.orientation.onchange = rotationHandler;
349
- player.on('dispose', function () {
393
+ player.on('dispose', () => {
350
394
  screen.orientation.onchange = null;
351
395
  });
352
396
  }
353
-
354
- player.on('fullscreenchange', function (_) {
355
- if (!player.isFullscreen() && locked) {
356
- screen.orientation.unlock();
357
- locked = false;
358
- }
359
- });
360
397
  }
361
-
362
- player.on('ended', function (_) {
398
+ player.on('fullscreenchange', _ => {
399
+ if (player.isFullscreen() && options.fullscreen.lockToLandscapeOnEnter && getOrientation() === 'portrait') {
400
+ screen.orientation.lock('landscape').then(() => {
401
+ locked = true;
402
+ }).catch(e => {
403
+ videojs__default["default"].log('Browser refused orientation lock:', e);
404
+ });
405
+ } else if (!player.isFullscreen() && locked) {
406
+ screen.orientation.unlock();
407
+ locked = false;
408
+ }
409
+ });
410
+ player.on('ended', _ => {
363
411
  if (locked === true) {
364
412
  screen.orientation.unlock();
365
413
  locked = false;
366
414
  }
367
415
  });
368
416
  };
417
+
369
418
  /**
370
- * A video.js plugin.
371
- *
372
- * Adds a monile UI for player control, and fullscreen orientation control
419
+ * Adds a mobile UI for player control, and fullscreen orientation control
373
420
  *
374
421
  * @function mobileUi
375
- * @param {Object} [options={}]
376
- * Plugin options.
377
- * @param {boolean} [options.forceForTesting=false]
378
- * Enables the display regardless of user agent, for testing purposes
379
- * @param {Object} [options.fullscreen={}]
380
- * Fullscreen options.
381
- * @param {boolean} [options.fullscreen.disabled=false]
382
- * If true no fullscreen handling except the *deprecated* iOS fullwindow hack
383
- * @param {boolean} [options.fullscreen.enterOnRotate=true]
384
- * Whether to go fullscreen when rotating to landscape
385
- * @param {boolean} [options.fullscreen.exitOnRotate=true]
386
- * Whether to leave fullscreen when rotating to portrait (if not locked)
387
- * @param {boolean} [options.fullscreen.lockOnRotate=true]
388
- * Whether to lock orientation when rotating to landscape
389
- * Unlocked when exiting fullscreen or on 'ended'
390
- * @param {boolean} [options.fullscreen.iOS=false]
391
- * Deprecated: Whether to disable iOS's native fullscreen so controls can work
392
- * @param {Object} [options.touchControls={}]
393
- * Touch UI options.
394
- * @param {boolean} [options.touchControls.disabled=false]
395
- * If true no touch controls are added.
396
- * @param {int} [options.touchControls.seekSeconds=10]
397
- * Number of seconds to seek on double-tap
398
- * @param {int} [options.touchControls.tapTimeout=300]
399
- * Interval in ms to be considered a doubletap
400
- * @param {boolean} [options.touchControls.disableOnEnd=false]
401
- * Whether to disable when the video ends (e.g., if there is an endscreen)
402
- * Never shows if the endscreen plugin is present
422
+ * @param {Object} [options={}] Plugin options
403
423
  */
404
-
405
-
406
- var mobileUi = function mobileUi(options) {
407
- var _this = this;
408
-
409
- if (options === void 0) {
410
- options = {};
411
- }
412
-
413
- if (options.forceForTesting || videojs__default['default'].browser.IS_ANDROID || videojs__default['default'].browser.IS_IOS) {
414
- this.ready(function () {
415
- onPlayerReady(_this, videojs__default['default'].mergeOptions(defaults, options));
424
+ const mobileUi = function (options = {}) {
425
+ if (options.forceForTesting || videojs__default["default"].browser.IS_ANDROID || videojs__default["default"].browser.IS_IOS) {
426
+ this.ready(() => {
427
+ onPlayerReady(this, videojs__default["default"].mergeOptions(defaults, options));
416
428
  });
417
429
  }
418
- }; // Register the plugin with video.js.
419
-
430
+ };
420
431
 
421
- registerPlugin('mobileUi', mobileUi); // Include the version number.
432
+ // Register the plugin with video.js.
433
+ registerPlugin('mobileUi', mobileUi);
422
434
 
435
+ // Include the version number.
423
436
  mobileUi.VERSION = version;
424
437
 
425
438
  return mobileUi;
426
439
 
427
- })));
440
+ }));