videojs-mobile-ui 0.8.0 → 1.0.0

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 +4 -2
  2. package/dist/lang/de.js +3 -0
  3. package/dist/lang/en.js +1 -1
  4. package/dist/lang/it.js +3 -0
  5. package/dist/videojs-mobile-ui.cjs.js +110 -185
  6. package/dist/videojs-mobile-ui.css +2 -2
  7. package/dist/videojs-mobile-ui.es.js +110 -184
  8. package/dist/videojs-mobile-ui.js +117 -231
  9. package/dist/videojs-mobile-ui.min.js +2 -2
  10. package/index.html +1 -7
  11. package/package.json +10 -10
  12. package/src/plugin.css +13 -1
  13. package/src/plugin.js +5 -33
  14. package/src/touchOverlay.js +46 -56
  15. package/CHANGELOG.md +0 -95
  16. package/docs/api/TouchOverlay.html +0 -964
  17. package/docs/api/fonts/OpenSans-Bold-webfont.eot +0 -0
  18. package/docs/api/fonts/OpenSans-Bold-webfont.svg +0 -1830
  19. package/docs/api/fonts/OpenSans-Bold-webfont.woff +0 -0
  20. package/docs/api/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
  21. package/docs/api/fonts/OpenSans-BoldItalic-webfont.svg +0 -1830
  22. package/docs/api/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
  23. package/docs/api/fonts/OpenSans-Italic-webfont.eot +0 -0
  24. package/docs/api/fonts/OpenSans-Italic-webfont.svg +0 -1830
  25. package/docs/api/fonts/OpenSans-Italic-webfont.woff +0 -0
  26. package/docs/api/fonts/OpenSans-Light-webfont.eot +0 -0
  27. package/docs/api/fonts/OpenSans-Light-webfont.svg +0 -1831
  28. package/docs/api/fonts/OpenSans-Light-webfont.woff +0 -0
  29. package/docs/api/fonts/OpenSans-LightItalic-webfont.eot +0 -0
  30. package/docs/api/fonts/OpenSans-LightItalic-webfont.svg +0 -1835
  31. package/docs/api/fonts/OpenSans-LightItalic-webfont.woff +0 -0
  32. package/docs/api/fonts/OpenSans-Regular-webfont.eot +0 -0
  33. package/docs/api/fonts/OpenSans-Regular-webfont.svg +0 -1831
  34. package/docs/api/fonts/OpenSans-Regular-webfont.woff +0 -0
  35. package/docs/api/global.html +0 -957
  36. package/docs/api/index.html +0 -159
  37. package/docs/api/plugin.js.html +0 -221
  38. package/docs/api/scripts/linenumber.js +0 -25
  39. package/docs/api/scripts/prettify/Apache-License-2.0.txt +0 -202
  40. package/docs/api/scripts/prettify/lang-css.js +0 -2
  41. package/docs/api/scripts/prettify/prettify.js +0 -28
  42. package/docs/api/styles/jsdoc-default.css +0 -358
  43. package/docs/api/styles/prettify-jsdoc.css +0 -111
  44. package/docs/api/styles/prettify-tomorrow.css +0 -132
  45. package/docs/api/touchOverlay.js.html +0 -211
@@ -1,68 +1,29 @@
1
- /*! @name videojs-mobile-ui @version 0.8.0 @license MIT */
1
+ /*! @name videojs-mobile-ui @version 1.0.0 @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.8.0";
12
+ var version = "1.0.0";
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
- }
50
-
51
- module.exports = _inheritsLoose;
52
- module.exports["default"] = module.exports, module.exports.__esModule = true;
53
- });
14
+ /**
15
+ * @file touchOverlay.js
16
+ * Touch UI component
17
+ */
18
+ const Component = videojs__default['default'].getComponent('Component');
19
+ const dom = videojs__default['default'].dom || videojs__default['default'];
54
20
 
55
- var Component = videojs__default['default'].getComponent('Component');
56
- var dom = videojs__default['default'].dom || videojs__default['default'];
57
21
  /**
58
22
  * The `TouchOverlay` is an overlay to capture tap events.
59
23
  *
60
24
  * @extends Component
61
25
  */
62
-
63
- var TouchOverlay = /*#__PURE__*/function (_Component) {
64
- inheritsLoose(TouchOverlay, _Component);
65
-
26
+ class TouchOverlay extends Component {
66
27
  /**
67
28
  * Creates an instance of the this class.
68
29
  *
@@ -72,46 +33,80 @@
72
33
  * @param {Object} [options]
73
34
  * The key/value store of player options.
74
35
  */
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
36
+ constructor(player, options) {
37
+ super(player, options);
38
+ this.seekSeconds = options.seekSeconds;
39
+ this.tapTimeout = options.tapTimeout;
40
+ this.taps = 0;
41
+
42
+ // Add play toggle overlay
43
+ this.addChild('playToggle', {});
44
+
45
+ // Clear overlay when playback starts or with control fade
46
+ player.on(['playing', 'userinactive'], e => {
47
+ this.removeClass('show-play-toggle');
48
+ });
88
49
 
89
- if (_this.player_.options_.inactivityTimeout === 0) {
90
- _this.player_.options_.inactivityTimeout = 5000;
50
+ // A 0 inactivity timeout won't work here
51
+ if (this.player_.options_.inactivityTimeout === 0) {
52
+ this.player_.options_.inactivityTimeout = 5000;
91
53
  }
92
54
 
93
- _this.enable();
55
+ /**
56
+ * Debounced tap handler.
57
+ * Seeks number of (taps - 1) * configured seconds to skip.
58
+ * One tap is a non-op
59
+ *
60
+ * @param {Event} event
61
+ */
62
+ this.handleTaps_ = videojs__default['default'].fn.debounce(event => {
63
+ const increment = (this.taps - 1) * this.seekSeconds;
64
+ this.taps = 0;
65
+ if (increment < 1) {
66
+ return;
67
+ }
68
+ const rect = this.el_.getBoundingClientRect();
69
+ const x = event.changedTouches[0].clientX - rect.left;
70
+
71
+ // Check if double tap is in left or right area
72
+ if (x < rect.width * 0.4) {
73
+ this.player_.currentTime(Math.max(0, this.player_.currentTime() - increment));
74
+ this.addClass('reverse');
75
+ } else if (x > rect.width - rect.width * 0.4) {
76
+ this.player_.currentTime(Math.min(this.player_.duration(), this.player_.currentTime() + increment));
77
+ this.removeClass('reverse');
78
+ } else {
79
+ return;
80
+ }
81
+
82
+ // Remove play toggle if showing
83
+ this.removeClass('show-play-toggle');
94
84
 
95
- return _this;
85
+ // Remove and readd class to trigger animation
86
+ this.setAttribute('data-skip-text', `${increment} ${this.localize('seconds')}`);
87
+ this.removeClass('skip');
88
+ window.requestAnimationFrame(() => {
89
+ this.addClass('skip');
90
+ });
91
+ }, this.tapTimeout);
92
+ this.enable();
96
93
  }
94
+
97
95
  /**
98
96
  * Builds the DOM element.
99
97
  *
100
98
  * @return {Element}
101
99
  * The DOM element.
102
100
  */
103
-
104
-
105
- var _proto = TouchOverlay.prototype;
106
-
107
- _proto.createEl = function createEl() {
108
- var el = dom.createEl('div', {
101
+ createEl() {
102
+ const el = dom.createEl('div', {
109
103
  className: 'vjs-touch-overlay',
110
104
  // Touch overlay is not tabbable.
111
105
  tabIndex: -1
112
106
  });
113
107
  return el;
114
108
  }
109
+
115
110
  /**
116
111
  * Debounces to either handle a delayed single tap, or a double tap
117
112
  *
@@ -119,111 +114,44 @@
119
114
  * The touch event
120
115
  *
121
116
  */
122
- ;
123
-
124
- _proto.handleTap = function handleTap(event) {
125
- var _this2 = this;
126
-
117
+ handleTap(event) {
127
118
  // Don't handle taps on the play button
128
119
  if (event.target !== this.el_) {
129
120
  return;
130
121
  }
131
-
132
122
  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);
123
+ this.taps += 1;
124
+ if (this.taps === 1) {
125
+ this.removeClass('skip');
126
+ this.toggleClass('show-play-toggle');
149
127
  }
128
+ this.handleTaps_(event);
150
129
  }
151
- /**
152
- * Toggles display of play toggle
153
- *
154
- * @param {Event} event
155
- * The touch event
156
- *
157
- */
158
- ;
159
130
 
160
- _proto.handleSingleTap = function handleSingleTap(event) {
161
- this.removeClass('skip');
162
- this.toggleClass('show-play-toggle');
163
- }
164
- /**
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
- *
170
- */
171
- ;
172
-
173
- _proto.handleDoubleTap = function handleDoubleTap(event) {
174
- var _this3 = this;
175
-
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
178
-
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 {
186
- return;
187
- } // Remove play toggle if showing
188
-
189
-
190
- this.removeClass('show-play-toggle'); // Remove and readd class to trigger animation
191
-
192
- this.removeClass('skip');
193
- window__default['default'].requestAnimationFrame(function () {
194
- _this3.addClass('skip');
195
- });
196
- }
197
131
  /**
198
132
  * Enables touch handler
199
133
  */
200
- ;
201
-
202
- _proto.enable = function enable() {
134
+ enable() {
203
135
  this.firstTapCaptured = false;
204
136
  this.on('touchend', this.handleTap);
205
137
  }
138
+
206
139
  /**
207
140
  * Disables touch handler
208
141
  */
209
- ;
210
-
211
- _proto.disable = function disable() {
142
+ disable() {
212
143
  this.off('touchend', this.handleTap);
213
- };
214
-
215
- return TouchOverlay;
216
- }(Component);
217
-
144
+ }
145
+ }
218
146
  Component.registerComponent('TouchOverlay', TouchOverlay);
219
147
 
220
- var defaults = {
148
+ // Default options for the plugin.
149
+ const defaults = {
221
150
  fullscreen: {
222
151
  enterOnRotate: true,
223
152
  exitOnRotate: true,
224
153
  lockOnRotate: true,
225
154
  lockToLandscapeOnEnter: false,
226
- iOS: false,
227
155
  disabled: false
228
156
  },
229
157
  touchControls: {
@@ -233,37 +161,32 @@
233
161
  disabled: false
234
162
  }
235
163
  };
236
- var screen = window__default['default'].screen;
164
+ const screen = window.screen;
165
+
237
166
  /**
238
167
  * Gets 'portrait' or 'lanscape' from the two orientation APIs
239
168
  *
240
169
  * @return {string} orientation
241
170
  */
242
-
243
- var getOrientation = function getOrientation() {
244
- if (screen) {
171
+ const getOrientation = () => {
172
+ if (window.screen) {
245
173
  // Prefer the string over angle, as 0° can be landscape on some tablets
246
- var orientationString = ((screen.orientation || {}).type || screen.mozOrientation || screen.msOrientation || '').split('-')[0];
247
-
174
+ const orientationString = ((window.screen.orientation || {}).type || window.screen.mozOrientation || window.screen.msOrientation || '').split('-')[0];
248
175
  if (orientationString === 'landscape' || orientationString === 'portrait') {
249
176
  return orientationString;
250
177
  }
251
- } // iOS only supports window.orientation
252
-
178
+ }
253
179
 
254
- if (typeof window__default['default'].orientation === 'number') {
255
- if (window__default['default'].orientation === 0 || window__default['default'].orientation === 180) {
180
+ // iOS only supports window.orientation
181
+ if (typeof window.orientation === 'number') {
182
+ if (window.orientation === 0 || window.orientation === 180) {
256
183
  return 'portrait';
257
184
  }
258
-
259
185
  return 'landscape';
260
186
  }
261
-
262
187
  return 'portrait';
263
- }; // Cross-compatibility for Video.js 5 and 6.
264
-
188
+ };
265
189
 
266
- var registerPlugin = videojs__default['default'].registerPlugin || videojs__default['default'].plugin;
267
190
  /**
268
191
  * Add UI and event listeners
269
192
  *
@@ -274,59 +197,30 @@
274
197
  * @param {Object} [options={}]
275
198
  * A plain object containing options for the plugin.
276
199
  */
277
-
278
- var onPlayerReady = function onPlayerReady(player, options) {
200
+ const onPlayerReady = (player, options) => {
279
201
  player.addClass('vjs-mobile-ui');
280
-
281
- if (options.fullscreen.iOS) {
282
- videojs__default['default'].log.warn('videojs-mobile-ui: `fullscreen.iOS` is deprecated. Use Video.js option `preferFullWindow` instead.');
283
-
284
- if (videojs__default['default'].browser.IS_IOS && videojs__default['default'].browser.IOS_VERSION > 9 && !player.el_.ownerDocument.querySelector('.bc-iframe')) {
285
- player.tech_.el_.setAttribute('playsinline', 'playsinline');
286
-
287
- player.tech_.supportsFullScreen = function () {
288
- return false;
289
- };
290
- }
291
- }
292
-
293
202
  if (!options.touchControls.disabled) {
294
203
  if (options.touchControls.disableOnEnd || typeof player.endscreen === 'function') {
295
204
  player.addClass('vjs-mobile-ui-disable-end');
296
- } // Insert before the control bar
297
-
298
-
299
- var controlBarIdx;
300
- var versionParts = videojs__default['default'].VERSION.split('.');
301
- var major = parseInt(versionParts[0], 10);
302
- var minor = parseInt(versionParts[1], 10); // Video.js < 7.7.0 doesn't account for precedding components that don't have elements
303
-
304
- if (major < 7 || major === 7 && minor < 7) {
305
- controlBarIdx = Array.prototype.indexOf.call(player.el_.children, player.getChild('ControlBar').el_);
306
- } else {
307
- controlBarIdx = player.children_.indexOf(player.getChild('ControlBar'));
308
205
  }
309
206
 
207
+ // Insert before the control bar
208
+ const controlBarIdx = player.children_.indexOf(player.getChild('ControlBar'));
310
209
  player.touchOverlay = player.addChild('TouchOverlay', options.touchControls, controlBarIdx);
311
210
  }
312
-
313
211
  if (options.fullscreen.disabled) {
314
212
  return;
315
213
  }
316
-
317
- var locked = false;
318
-
319
- var rotationHandler = function rotationHandler() {
320
- var currentOrientation = getOrientation();
321
-
214
+ let locked = false;
215
+ const rotationHandler = () => {
216
+ const currentOrientation = getOrientation();
322
217
  if (currentOrientation === 'landscape' && options.fullscreen.enterOnRotate) {
323
218
  if (player.paused() === false) {
324
219
  player.requestFullscreen();
325
-
326
220
  if ((options.fullscreen.lockOnRotate || options.fullscreen.lockToLandscapeOnEnter) && screen.orientation && screen.orientation.lock) {
327
- screen.orientation.lock('landscape').then(function () {
221
+ screen.orientation.lock('landscape').then(() => {
328
222
  locked = true;
329
- }).catch(function (e) {
223
+ }).catch(e => {
330
224
  videojs__default['default'].log('Browser refused orientation lock:', e);
331
225
  });
332
226
  }
@@ -337,27 +231,25 @@
337
231
  }
338
232
  }
339
233
  };
340
-
341
234
  if (options.fullscreen.enterOnRotate || options.fullscreen.exitOnRotate) {
342
235
  if (videojs__default['default'].browser.IS_IOS) {
343
- window__default['default'].addEventListener('orientationchange', rotationHandler);
344
- player.on('dispose', function () {
345
- window__default['default'].removeEventListener('orientationchange', rotationHandler);
236
+ window.addEventListener('orientationchange', rotationHandler);
237
+ player.on('dispose', () => {
238
+ window.removeEventListener('orientationchange', rotationHandler);
346
239
  });
347
240
  } else if (screen.orientation) {
348
241
  // addEventListener('orientationchange') is not a user interaction on Android
349
242
  screen.orientation.onchange = rotationHandler;
350
- player.on('dispose', function () {
243
+ player.on('dispose', () => {
351
244
  screen.orientation.onchange = null;
352
245
  });
353
246
  }
354
247
  }
355
-
356
- player.on('fullscreenchange', function (_) {
248
+ player.on('fullscreenchange', _ => {
357
249
  if (player.isFullscreen() && options.fullscreen.lockToLandscapeOnEnter && getOrientation() === 'portrait') {
358
- screen.orientation.lock('landscape').then(function () {
250
+ screen.orientation.lock('landscape').then(() => {
359
251
  locked = true;
360
- }).catch(function (e) {
252
+ }).catch(e => {
361
253
  videojs__default['default'].log('Browser refused orientation lock:', e);
362
254
  });
363
255
  } else if (!player.isFullscreen() && locked) {
@@ -365,13 +257,14 @@
365
257
  locked = false;
366
258
  }
367
259
  });
368
- player.on('ended', function (_) {
260
+ player.on('ended', _ => {
369
261
  if (locked === true) {
370
262
  screen.orientation.unlock();
371
263
  locked = false;
372
264
  }
373
265
  });
374
266
  };
267
+
375
268
  /**
376
269
  * A video.js plugin.
377
270
  *
@@ -410,25 +303,18 @@
410
303
  * Whether to disable when the video ends (e.g., if there is an endscreen)
411
304
  * Never shows if the endscreen plugin is present
412
305
  */
413
-
414
-
415
- var mobileUi = function mobileUi(options) {
416
- var _this = this;
417
-
418
- if (options === void 0) {
419
- options = {};
420
- }
421
-
306
+ const mobileUi = function (options = {}) {
422
307
  if (options.forceForTesting || videojs__default['default'].browser.IS_ANDROID || videojs__default['default'].browser.IS_IOS) {
423
- this.ready(function () {
424
- onPlayerReady(_this, videojs__default['default'].mergeOptions(defaults, options));
308
+ this.ready(() => {
309
+ onPlayerReady(this, videojs__default['default'].obj.merge(defaults, options));
425
310
  });
426
311
  }
427
- }; // Register the plugin with video.js.
428
-
312
+ };
429
313
 
430
- registerPlugin('mobileUi', mobileUi); // Include the version number.
314
+ // Register the plugin with video.js.
315
+ videojs__default['default'].registerPlugin('mobileUi', mobileUi);
431
316
 
317
+ // Include the version number.
432
318
  mobileUi.VERSION = version;
433
319
 
434
320
  return mobileUi;
@@ -1,2 +1,2 @@
1
- /*! @name videojs-mobile-ui @version 0.8.0 @license MIT */
2
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("video.js"),require("global/window")):"function"==typeof define&&define.amd?define(["video.js","global/window"],t):(e="undefined"!=typeof globalThis?globalThis:e||self).videojsMobileUi=t(e.videojs,e.window)}(this,(function(e,t){"use strict";function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var o=n(e),i=n(t);function r(e,t,n){return e(n={path:t,exports:{},require:function(e,t){return function(){throw new Error("Dynamic requires are not currently supported by @rollup/plugin-commonjs")}(null==t&&n.path)}},n.exports),n.exports}var a=r((function(e){function t(n,o){return e.exports=t=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},e.exports.default=e.exports,e.exports.__esModule=!0,t(n,o)}e.exports=t,e.exports.default=e.exports,e.exports.__esModule=!0})),l=r((function(e){e.exports=function(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,a(e,t)},e.exports.default=e.exports,e.exports.__esModule=!0})),s=o.default.getComponent("Component"),u=o.default.dom||o.default,c=function(e){function t(t,n){var o;return(o=e.call(this,t,n)||this).seekSeconds=n.seekSeconds,o.tapTimeout=n.tapTimeout,o.addChild("playToggle",{}),t.on(["playing","userinactive"],(function(e){o.removeClass("show-play-toggle")})),0===o.player_.options_.inactivityTimeout&&(o.player_.options_.inactivityTimeout=5e3),o.enable(),o}l(t,e);var n=t.prototype;return n.createEl=function(){return u.createEl("div",{className:"vjs-touch-overlay",tabIndex:-1})},n.handleTap=function(e){var t=this;e.target===this.el_&&(e.preventDefault(),this.firstTapCaptured?(this.firstTapCaptured=!1,this.timeout&&i.default.clearTimeout(this.timeout),this.handleDoubleTap(e)):(this.firstTapCaptured=!0,this.timeout=i.default.setTimeout((function(){t.firstTapCaptured=!1,t.handleSingleTap(e)}),this.tapTimeout)))},n.handleSingleTap=function(e){this.removeClass("skip"),this.toggleClass("show-play-toggle")},n.handleDoubleTap=function(e){var t=this,n=this.el_.getBoundingClientRect(),o=e.changedTouches[0].clientX-n.left;if(o<.4*n.width)this.player_.currentTime(Math.max(0,this.player_.currentTime()-this.seekSeconds)),this.addClass("reverse");else{if(!(o>n.width-.4*n.width))return;this.player_.currentTime(Math.min(this.player_.duration(),this.player_.currentTime()+this.seekSeconds)),this.removeClass("reverse")}this.removeClass("show-play-toggle"),this.removeClass("skip"),i.default.requestAnimationFrame((function(){t.addClass("skip")}))},n.enable=function(){this.firstTapCaptured=!1,this.on("touchend",this.handleTap)},n.disable=function(){this.off("touchend",this.handleTap)},t}(s);s.registerComponent("TouchOverlay",c);var d={fullscreen:{enterOnRotate:!0,exitOnRotate:!0,lockOnRotate:!0,lockToLandscapeOnEnter:!1,iOS:!1,disabled:!1},touchControls:{seekSeconds:10,tapTimeout:300,disableOnEnd:!1,disabled:!1}},f=i.default.screen,p=function(){if(f){var e=((f.orientation||{}).type||f.mozOrientation||f.msOrientation||"").split("-")[0];if("landscape"===e||"portrait"===e)return e}return"number"==typeof i.default.orientation?0===i.default.orientation||180===i.default.orientation?"portrait":"landscape":"portrait"},h=o.default.registerPlugin||o.default.plugin,m=function(e){var t=this;void 0===e&&(e={}),(e.forceForTesting||o.default.browser.IS_ANDROID||o.default.browser.IS_IOS)&&this.ready((function(){!function(e,t){if(e.addClass("vjs-mobile-ui"),t.fullscreen.iOS&&(o.default.log.warn("videojs-mobile-ui: `fullscreen.iOS` is deprecated. Use Video.js option `preferFullWindow` instead."),o.default.browser.IS_IOS&&o.default.browser.IOS_VERSION>9&&!e.el_.ownerDocument.querySelector(".bc-iframe")&&(e.tech_.el_.setAttribute("playsinline","playsinline"),e.tech_.supportsFullScreen=function(){return!1})),!t.touchControls.disabled){var n;(t.touchControls.disableOnEnd||"function"==typeof e.endscreen)&&e.addClass("vjs-mobile-ui-disable-end");var r=o.default.VERSION.split("."),a=parseInt(r[0],10),l=parseInt(r[1],10);n=a<7||7===a&&l<7?Array.prototype.indexOf.call(e.el_.children,e.getChild("ControlBar").el_):e.children_.indexOf(e.getChild("ControlBar")),e.touchOverlay=e.addChild("TouchOverlay",t.touchControls,n)}if(!t.fullscreen.disabled){var s=!1,u=function(){var n=p();"landscape"===n&&t.fullscreen.enterOnRotate?!1===e.paused()&&(e.requestFullscreen(),(t.fullscreen.lockOnRotate||t.fullscreen.lockToLandscapeOnEnter)&&f.orientation&&f.orientation.lock&&f.orientation.lock("landscape").then((function(){s=!0})).catch((function(e){o.default.log("Browser refused orientation lock:",e)}))):"portrait"===n&&t.fullscreen.exitOnRotate&&!s&&e.isFullscreen()&&e.exitFullscreen()};(t.fullscreen.enterOnRotate||t.fullscreen.exitOnRotate)&&(o.default.browser.IS_IOS?(i.default.addEventListener("orientationchange",u),e.on("dispose",(function(){i.default.removeEventListener("orientationchange",u)}))):f.orientation&&(f.orientation.onchange=u,e.on("dispose",(function(){f.orientation.onchange=null})))),e.on("fullscreenchange",(function(n){e.isFullscreen()&&t.fullscreen.lockToLandscapeOnEnter&&"portrait"===p()?f.orientation.lock("landscape").then((function(){s=!0})).catch((function(e){o.default.log("Browser refused orientation lock:",e)})):!e.isFullscreen()&&s&&(f.orientation.unlock(),s=!1)})),e.on("ended",(function(e){!0===s&&(f.orientation.unlock(),s=!1)}))}}(t,o.default.mergeOptions(d,e))}))};return h("mobileUi",m),m.VERSION="0.8.0",m}));
1
+ /*! @name videojs-mobile-ui @version 1.0.0 @license MIT */
2
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("video.js")):"function"==typeof define&&define.amd?define(["video.js"],t):(e="undefined"!=typeof globalThis?globalThis:e||self).videojsMobileUi=t(e.videojs)}(this,(function(e){"use strict";function t(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var n=t(e);const o=n.default.getComponent("Component"),i=n.default.dom||n.default;o.registerComponent("TouchOverlay",class extends o{constructor(e,t){super(e,t),this.seekSeconds=t.seekSeconds,this.tapTimeout=t.tapTimeout,this.taps=0,this.addChild("playToggle",{}),e.on(["playing","userinactive"],(e=>{this.removeClass("show-play-toggle")})),0===this.player_.options_.inactivityTimeout&&(this.player_.options_.inactivityTimeout=5e3),this.handleTaps_=n.default.fn.debounce((e=>{const t=(this.taps-1)*this.seekSeconds;if(this.taps=0,t<1)return;const n=this.el_.getBoundingClientRect(),o=e.changedTouches[0].clientX-n.left;if(o<.4*n.width)this.player_.currentTime(Math.max(0,this.player_.currentTime()-t)),this.addClass("reverse");else{if(!(o>n.width-.4*n.width))return;this.player_.currentTime(Math.min(this.player_.duration(),this.player_.currentTime()+t)),this.removeClass("reverse")}this.removeClass("show-play-toggle"),this.setAttribute("data-skip-text",`${t} ${this.localize("seconds")}`),this.removeClass("skip"),window.requestAnimationFrame((()=>{this.addClass("skip")}))}),this.tapTimeout),this.enable()}createEl(){return i.createEl("div",{className:"vjs-touch-overlay",tabIndex:-1})}handleTap(e){e.target===this.el_&&(e.preventDefault(),this.taps+=1,1===this.taps&&(this.removeClass("skip"),this.toggleClass("show-play-toggle")),this.handleTaps_(e))}enable(){this.firstTapCaptured=!1,this.on("touchend",this.handleTap)}disable(){this.off("touchend",this.handleTap)}});const s={fullscreen:{enterOnRotate:!0,exitOnRotate:!0,lockOnRotate:!0,lockToLandscapeOnEnter:!1,disabled:!1},touchControls:{seekSeconds:10,tapTimeout:300,disableOnEnd:!1,disabled:!1}},a=window.screen,r=()=>{if(window.screen){const e=((window.screen.orientation||{}).type||window.screen.mozOrientation||window.screen.msOrientation||"").split("-")[0];if("landscape"===e||"portrait"===e)return e}return"number"==typeof window.orientation?0===window.orientation||180===window.orientation?"portrait":"landscape":"portrait"},l=function(e={}){(e.forceForTesting||n.default.browser.IS_ANDROID||n.default.browser.IS_IOS)&&this.ready((()=>{((e,t)=>{if(e.addClass("vjs-mobile-ui"),!t.touchControls.disabled){(t.touchControls.disableOnEnd||"function"==typeof e.endscreen)&&e.addClass("vjs-mobile-ui-disable-end");const n=e.children_.indexOf(e.getChild("ControlBar"));e.touchOverlay=e.addChild("TouchOverlay",t.touchControls,n)}if(t.fullscreen.disabled)return;let o=!1;const i=()=>{const i=r();"landscape"===i&&t.fullscreen.enterOnRotate?!1===e.paused()&&(e.requestFullscreen(),(t.fullscreen.lockOnRotate||t.fullscreen.lockToLandscapeOnEnter)&&a.orientation&&a.orientation.lock&&a.orientation.lock("landscape").then((()=>{o=!0})).catch((e=>{n.default.log("Browser refused orientation lock:",e)}))):"portrait"===i&&t.fullscreen.exitOnRotate&&!o&&e.isFullscreen()&&e.exitFullscreen()};(t.fullscreen.enterOnRotate||t.fullscreen.exitOnRotate)&&(n.default.browser.IS_IOS?(window.addEventListener("orientationchange",i),e.on("dispose",(()=>{window.removeEventListener("orientationchange",i)}))):a.orientation&&(a.orientation.onchange=i,e.on("dispose",(()=>{a.orientation.onchange=null})))),e.on("fullscreenchange",(i=>{e.isFullscreen()&&t.fullscreen.lockToLandscapeOnEnter&&"portrait"===r()?a.orientation.lock("landscape").then((()=>{o=!0})).catch((e=>{n.default.log("Browser refused orientation lock:",e)})):!e.isFullscreen()&&o&&(a.orientation.unlock(),o=!1)})),e.on("ended",(e=>{!0===o&&(a.orientation.unlock(),o=!1)}))})(this,n.default.obj.merge(s,e))}))};return n.default.registerPlugin("mobileUi",l),l.VERSION="1.0.0",l}));
package/index.html CHANGED
@@ -24,8 +24,7 @@
24
24
  controls
25
25
  playsinline
26
26
  >
27
- <source src="//vjs.zencdn.net/v/oceans.mp4" type="video/mp4" />
28
- <source src="//vjs.zencdn.net/v/oceans.webm" type="video/webm" />
27
+ <source src="https://d2zihajmogu5jn.cloudfront.net/bipbop-advanced/bipbop_16x9_variant.m3u8" type="application/x-mpegurl" />
29
28
  </video-js>
30
29
  <ul>
31
30
  <li><a href="test/">Run unit tests in browser.</a></li>
@@ -63,10 +62,6 @@
63
62
  id="alwaysLockToLandscape"
64
63
  />alwaysLockToLandscape
65
64
  </li>
66
- <li>
67
- <input type="checkbox" data-section="fullscreen" id="iOS" />iOS
68
- <b>Deprecated</b>
69
- </li>
70
65
  <li>
71
66
  <input
72
67
  type="checkbox"
@@ -119,7 +114,6 @@
119
114
  exitOnRotate: true,
120
115
  lockOnRotate: true,
121
116
  alwaysLockToLandscape: false,
122
- iOS: false,
123
117
  disabled: false,
124
118
  },
125
119
  touchControls: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "videojs-mobile-ui",
3
- "version": "0.8.0",
3
+ "version": "1.0.0",
4
4
  "description": "Mobile tap controls and fullscreen on rotate for Video.js",
5
5
  "main": "dist/videojs-mobile-ui.cjs.js",
6
6
  "module": "dist/videojs-mobile-ui.es.js",
@@ -31,7 +31,7 @@
31
31
  "watch": "npm-run-all -p watch:*",
32
32
  "watch:css": "npm run build:css -- -w",
33
33
  "watch:js": "npm run build:js -- -w",
34
- "prepublishOnly": "npm-run-all build-prod && vjsverify --verbose"
34
+ "prepublishOnly": "npm-run-all build-prod && vjsverify --verbose --skip-es-check"
35
35
  },
36
36
  "engines": {
37
37
  "node": ">=14",
@@ -71,24 +71,24 @@
71
71
  "global": "^4.4.0"
72
72
  },
73
73
  "peerDependencies": {
74
- "video.js": "^6 || ^7"
74
+ "video.js": "^8"
75
75
  },
76
76
  "devDependencies": {
77
77
  "@babel/runtime": "^7.14.0",
78
- "@videojs/generator-helpers": "~2.0.2",
79
- "husky": "^6.0.0",
80
- "jsdoc": "^3.6.7",
78
+ "@videojs/generator-helpers": "~3.2.0",
79
+ "husky": "^8.0.1",
80
+ "jsdoc": "^4.0.0",
81
81
  "karma": "^6.3.2",
82
82
  "postcss": "^8.2.13",
83
83
  "postcss-cli": "^8.3.1",
84
84
  "rollup": "^2.46.0",
85
- "sinon": "^9.1.0",
86
- "video.js": "^6 || ^7",
85
+ "sinon": "^14.0.1",
86
+ "video.js": "^8.0.0",
87
87
  "videojs-generate-karma-config": "~8.0.0",
88
88
  "videojs-generate-postcss-config": "~3.0.0",
89
- "videojs-generate-rollup-config": "~6.2.0",
89
+ "videojs-generate-rollup-config": "^7.0.0",
90
90
  "videojs-generator-verify": "^4.1.0",
91
91
  "videojs-languages": "^2.0.0",
92
- "videojs-standard": "^8.0.4"
92
+ "videojs-standard": "^9.0.1"
93
93
  }
94
94
  }
package/src/plugin.css CHANGED
@@ -30,16 +30,28 @@
30
30
 
31
31
  &.skip {
32
32
  opacity: 0;
33
- animation: fadeAndScale 0.6s linear;
33
+ animation: fadeAndScale 0.8s linear;
34
34
  background-repeat: no-repeat;
35
35
  background-position: 80% center;
36
36
  background-size: 10%;
37
37
  background-image: url('data:image/svg+xml;utf8,<svg fill="%23FFFFFF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z"/><path d="M0 0h24v24H0z" fill="none"/></svg>');
38
+
39
+ &:after {
40
+ content: attr(data-skip-text);
41
+ position: absolute;
42
+ top: 60%;
43
+ left: 70%;
44
+ }
38
45
  }
39
46
 
40
47
  &.skip.reverse {
41
48
  background-position: 20% center;
42
49
  background-image: url('data:image/svg+xml;utf8,<svg fill="%23FFFFFF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M11 18V6l-8.5 6 8.5 6zm.5-6l8.5 6V6l-8.5 6z"/><path d="M0 0h24v24H0z" fill="none"/></svg>');
50
+
51
+ &:after {
52
+ right: 70%;
53
+ left: unset;
54
+ }
43
55
  }
44
56
 
45
57
  .vjs-play-control {