videojs-mobile-ui 0.7.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.
package/README.md CHANGED
@@ -12,6 +12,7 @@ Fullscreen control:
12
12
 
13
13
  - Rotate to landscape to enter Fullscreen
14
14
  - Lock to fullscreen on rotate
15
+ - Always lock to landscape when entering fullscreen (works even when device rotation is disabled/non-functional)
15
16
 
16
17
  ## Table of Contents
17
18
 
@@ -33,9 +34,12 @@ Fullscreen control:
33
34
  ## Installation
34
35
 
35
36
  ```sh
36
- npm install --save videojs-mobile-ui
37
+ npm install video.js
38
+ npm install videojs-mobile-ui
37
39
  ```
38
40
 
41
+ Version 1.x requires video.js 8.x as a peer dependency. Lowever video.js versions are not supported. 0.7.0 supports video.js 7.x.
42
+
39
43
  ## Plugin Options
40
44
 
41
45
  ### Default options
@@ -45,12 +49,16 @@ npm install --save videojs-mobile-ui
45
49
  fullscreen: {
46
50
  enterOnRotate: true,
47
51
  exitOnRotate: true,
48
- lockOnRotate: true
52
+ lockOnRotate: true,
53
+ lockToLandscapeOnEnter: false,
54
+ iOS: false,
55
+ disabled: false
49
56
  },
50
57
  touchControls: {
51
58
  seekSeconds: 10,
52
59
  tapTimeout: 300,
53
- disableOnEnd: false
60
+ disableOnEnd: false,
61
+ disabled: false,
54
62
  }
55
63
  };
56
64
  ```
@@ -60,10 +68,12 @@ npm install --save videojs-mobile-ui
60
68
  - *fullscreen.enterOnRotate* `boolean` Whether to go fullscreen when rotating to landscape
61
69
  - *fullscreen.exitOnRotate* `boolean` Whether to leave fullscreen when rotating to portrait (if not locked)
62
70
  - *fullscreen.lockOnRotate* `boolean` Whether to lock to fullscreen when rotating to landscape
63
- - *fullscreen.iOS* `boolean` Whether to use fake fullscreen on iOS (needed for controls to work)
71
+ - *fullscreen.lockToLandscapeOnEnter* `boolean` Whether to lock to landscape when entering fullscreen (works even when device rotation is disabled/non-functional)
72
+ - *fullscreen.disabled* `boolean` If true no fullscreen handling except the *deprecated* iOS fullwindow hack
64
73
  - *touchControls.seekSeconds* `int` Seconds to seek when double-tapping
65
74
  - *touchControls.tapTimeout* `int` Milliseconds to consider a double-tap
66
75
  - *touchControls.disableOnEnd* `boolean` Whether to disable touch controls when the video has ended, e.g. if an endscreen is used. Automatically disables if the endscreen plugin is present when this plugin initialises
76
+ - *touchControls.disableOnEnd* `boolean` If true no touch controls are added.
67
77
 
68
78
  ## Usage
69
79
 
@@ -0,0 +1,3 @@
1
+ videojs.addLanguage('de', {
2
+ "seconds": "Sekunden"
3
+ });
package/dist/lang/en.js CHANGED
@@ -1,3 +1,3 @@
1
1
  videojs.addLanguage('en', {
2
- "Include your own strings in JSON files.": "Include your own strings in JSON files."
2
+ "seconds": "seconds"
3
3
  });
@@ -0,0 +1,3 @@
1
+ videojs.addLanguage('it', {
2
+ "seconds": "secondi"
3
+ });
@@ -1,29 +1,29 @@
1
- /*! @name videojs-mobile-ui @version 0.7.0 @license MIT */
1
+ /*! @name videojs-mobile-ui @version 1.0.0 @license MIT */
2
2
  'use strict';
3
3
 
4
4
  var videojs = require('video.js');
5
- var _inheritsLoose = require('@babel/runtime/helpers/inheritsLoose');
6
5
  var window = require('global/window');
7
6
 
8
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
9
8
 
10
9
  var videojs__default = /*#__PURE__*/_interopDefaultLegacy(videojs);
11
- var _inheritsLoose__default = /*#__PURE__*/_interopDefaultLegacy(_inheritsLoose);
12
10
  var window__default = /*#__PURE__*/_interopDefaultLegacy(window);
13
11
 
14
- var version = "0.7.0";
12
+ var version = "1.0.0";
13
+
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'];
15
20
 
16
- var Component = videojs__default['default'].getComponent('Component');
17
- var dom = videojs__default['default'].dom || videojs__default['default'];
18
21
  /**
19
22
  * The `TouchOverlay` is an overlay to capture tap events.
20
23
  *
21
24
  * @extends Component
22
25
  */
23
-
24
- var TouchOverlay = /*#__PURE__*/function (_Component) {
25
- _inheritsLoose__default['default'](TouchOverlay, _Component);
26
-
26
+ class TouchOverlay extends Component {
27
27
  /**
28
28
  * Creates an instance of the this class.
29
29
  *
@@ -33,46 +33,80 @@ var TouchOverlay = /*#__PURE__*/function (_Component) {
33
33
  * @param {Object} [options]
34
34
  * The key/value store of player options.
35
35
  */
36
- function TouchOverlay(player, options) {
37
- var _this;
38
-
39
- _this = _Component.call(this, player, options) || this;
40
- _this.seekSeconds = options.seekSeconds;
41
- _this.tapTimeout = options.tapTimeout; // Add play toggle overlay
42
-
43
- _this.addChild('playToggle', {}); // Clear overlay when playback starts or with control fade
44
-
45
-
46
- player.on(['playing', 'userinactive'], function (e) {
47
- _this.removeClass('show-play-toggle');
48
- }); // 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
+ });
49
49
 
50
- if (_this.player_.options_.inactivityTimeout === 0) {
51
- _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;
52
53
  }
53
54
 
54
- _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');
55
84
 
56
- 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__default['default'].requestAnimationFrame(() => {
89
+ this.addClass('skip');
90
+ });
91
+ }, this.tapTimeout);
92
+ this.enable();
57
93
  }
94
+
58
95
  /**
59
96
  * Builds the DOM element.
60
97
  *
61
98
  * @return {Element}
62
99
  * The DOM element.
63
100
  */
64
-
65
-
66
- var _proto = TouchOverlay.prototype;
67
-
68
- _proto.createEl = function createEl() {
69
- var el = dom.createEl('div', {
101
+ createEl() {
102
+ const el = dom.createEl('div', {
70
103
  className: 'vjs-touch-overlay',
71
104
  // Touch overlay is not tabbable.
72
105
  tabIndex: -1
73
106
  });
74
107
  return el;
75
108
  }
109
+
76
110
  /**
77
111
  * Debounces to either handle a delayed single tap, or a double tap
78
112
  *
@@ -80,110 +114,44 @@ var TouchOverlay = /*#__PURE__*/function (_Component) {
80
114
  * The touch event
81
115
  *
82
116
  */
83
- ;
84
-
85
- _proto.handleTap = function handleTap(event) {
86
- var _this2 = this;
87
-
117
+ handleTap(event) {
88
118
  // Don't handle taps on the play button
89
119
  if (event.target !== this.el_) {
90
120
  return;
91
121
  }
92
-
93
122
  event.preventDefault();
94
-
95
- if (this.firstTapCaptured) {
96
- this.firstTapCaptured = false;
97
-
98
- if (this.timeout) {
99
- window__default['default'].clearTimeout(this.timeout);
100
- }
101
-
102
- this.handleDoubleTap(event);
103
- } else {
104
- this.firstTapCaptured = true;
105
- this.timeout = window__default['default'].setTimeout(function () {
106
- _this2.firstTapCaptured = false;
107
-
108
- _this2.handleSingleTap(event);
109
- }, this.tapTimeout);
123
+ this.taps += 1;
124
+ if (this.taps === 1) {
125
+ this.removeClass('skip');
126
+ this.toggleClass('show-play-toggle');
110
127
  }
128
+ this.handleTaps_(event);
111
129
  }
112
- /**
113
- * Toggles display of play toggle
114
- *
115
- * @param {Event} event
116
- * The touch event
117
- *
118
- */
119
- ;
120
-
121
- _proto.handleSingleTap = function handleSingleTap(event) {
122
- this.removeClass('skip');
123
- this.toggleClass('show-play-toggle');
124
- }
125
- /**
126
- * Seeks by configured number of seconds if left or right part of video double tapped
127
- *
128
- * @param {Event} event
129
- * The touch event
130
- *
131
- */
132
- ;
133
-
134
- _proto.handleDoubleTap = function handleDoubleTap(event) {
135
- var _this3 = this;
136
-
137
- var rect = this.el_.getBoundingClientRect();
138
- var x = event.changedTouches[0].clientX - rect.left; // Check if double tap is in left or right area
139
130
 
140
- if (x < rect.width * 0.4) {
141
- this.player_.currentTime(Math.max(0, this.player_.currentTime() - this.seekSeconds));
142
- this.addClass('reverse');
143
- } else if (x > rect.width - rect.width * 0.4) {
144
- this.player_.currentTime(Math.min(this.player_.duration(), this.player_.currentTime() + this.seekSeconds));
145
- this.removeClass('reverse');
146
- } else {
147
- return;
148
- } // Remove play toggle if showing
149
-
150
-
151
- this.removeClass('show-play-toggle'); // Remove and readd class to trigger animation
152
-
153
- this.removeClass('skip');
154
- window__default['default'].requestAnimationFrame(function () {
155
- _this3.addClass('skip');
156
- });
157
- }
158
131
  /**
159
132
  * Enables touch handler
160
133
  */
161
- ;
162
-
163
- _proto.enable = function enable() {
134
+ enable() {
164
135
  this.firstTapCaptured = false;
165
136
  this.on('touchend', this.handleTap);
166
137
  }
138
+
167
139
  /**
168
140
  * Disables touch handler
169
141
  */
170
- ;
171
-
172
- _proto.disable = function disable() {
142
+ disable() {
173
143
  this.off('touchend', this.handleTap);
174
- };
175
-
176
- return TouchOverlay;
177
- }(Component);
178
-
144
+ }
145
+ }
179
146
  Component.registerComponent('TouchOverlay', TouchOverlay);
180
147
 
181
- var defaults = {
148
+ // Default options for the plugin.
149
+ const defaults = {
182
150
  fullscreen: {
183
151
  enterOnRotate: true,
184
152
  exitOnRotate: true,
185
153
  lockOnRotate: true,
186
- iOS: false,
154
+ lockToLandscapeOnEnter: false,
187
155
  disabled: false
188
156
  },
189
157
  touchControls: {
@@ -193,37 +161,32 @@ var defaults = {
193
161
  disabled: false
194
162
  }
195
163
  };
196
- var screen = window__default['default'].screen;
164
+ const screen = window__default['default'].screen;
165
+
197
166
  /**
198
167
  * Gets 'portrait' or 'lanscape' from the two orientation APIs
199
168
  *
200
169
  * @return {string} orientation
201
170
  */
202
-
203
- var getOrientation = function getOrientation() {
204
- if (screen) {
171
+ const getOrientation = () => {
172
+ if (window__default['default'].screen) {
205
173
  // Prefer the string over angle, as 0° can be landscape on some tablets
206
- var orientationString = ((screen.orientation || {}).type || screen.mozOrientation || screen.msOrientation || '').split('-')[0];
207
-
174
+ const orientationString = ((window__default['default'].screen.orientation || {}).type || window__default['default'].screen.mozOrientation || window__default['default'].screen.msOrientation || '').split('-')[0];
208
175
  if (orientationString === 'landscape' || orientationString === 'portrait') {
209
176
  return orientationString;
210
177
  }
211
- } // iOS only supports window.orientation
212
-
178
+ }
213
179
 
180
+ // iOS only supports window.orientation
214
181
  if (typeof window__default['default'].orientation === 'number') {
215
182
  if (window__default['default'].orientation === 0 || window__default['default'].orientation === 180) {
216
183
  return 'portrait';
217
184
  }
218
-
219
185
  return 'landscape';
220
186
  }
221
-
222
187
  return 'portrait';
223
- }; // Cross-compatibility for Video.js 5 and 6.
224
-
188
+ };
225
189
 
226
- var registerPlugin = videojs__default['default'].registerPlugin || videojs__default['default'].plugin;
227
190
  /**
228
191
  * Add UI and event listeners
229
192
  *
@@ -234,59 +197,30 @@ var registerPlugin = videojs__default['default'].registerPlugin || videojs__defa
234
197
  * @param {Object} [options={}]
235
198
  * A plain object containing options for the plugin.
236
199
  */
237
-
238
- var onPlayerReady = function onPlayerReady(player, options) {
200
+ const onPlayerReady = (player, options) => {
239
201
  player.addClass('vjs-mobile-ui');
240
-
241
- if (options.fullscreen.iOS) {
242
- videojs__default['default'].log.warn('videojs-mobile-ui: `fullscreen.iOS` is deprecated. Use Video.js option `preferFullWindow` instead.');
243
-
244
- if (videojs__default['default'].browser.IS_IOS && videojs__default['default'].browser.IOS_VERSION > 9 && !player.el_.ownerDocument.querySelector('.bc-iframe')) {
245
- player.tech_.el_.setAttribute('playsinline', 'playsinline');
246
-
247
- player.tech_.supportsFullScreen = function () {
248
- return false;
249
- };
250
- }
251
- }
252
-
253
202
  if (!options.touchControls.disabled) {
254
203
  if (options.touchControls.disableOnEnd || typeof player.endscreen === 'function') {
255
204
  player.addClass('vjs-mobile-ui-disable-end');
256
- } // Insert before the control bar
257
-
258
-
259
- var controlBarIdx;
260
- var versionParts = videojs__default['default'].VERSION.split('.');
261
- var major = parseInt(versionParts[0], 10);
262
- var minor = parseInt(versionParts[1], 10); // Video.js < 7.7.0 doesn't account for precedding components that don't have elements
263
-
264
- if (major < 7 || major === 7 && minor < 7) {
265
- controlBarIdx = Array.prototype.indexOf.call(player.el_.children, player.getChild('ControlBar').el_);
266
- } else {
267
- controlBarIdx = player.children_.indexOf(player.getChild('ControlBar'));
268
205
  }
269
206
 
207
+ // Insert before the control bar
208
+ const controlBarIdx = player.children_.indexOf(player.getChild('ControlBar'));
270
209
  player.touchOverlay = player.addChild('TouchOverlay', options.touchControls, controlBarIdx);
271
210
  }
272
-
273
211
  if (options.fullscreen.disabled) {
274
212
  return;
275
213
  }
276
-
277
- var locked = false;
278
-
279
- var rotationHandler = function rotationHandler() {
280
- var currentOrientation = getOrientation();
281
-
214
+ let locked = false;
215
+ const rotationHandler = () => {
216
+ const currentOrientation = getOrientation();
282
217
  if (currentOrientation === 'landscape' && options.fullscreen.enterOnRotate) {
283
218
  if (player.paused() === false) {
284
219
  player.requestFullscreen();
285
-
286
- if (options.fullscreen.lockOnRotate && screen.orientation && screen.orientation.lock) {
287
- screen.orientation.lock('landscape').then(function () {
220
+ if ((options.fullscreen.lockOnRotate || options.fullscreen.lockToLandscapeOnEnter) && screen.orientation && screen.orientation.lock) {
221
+ screen.orientation.lock('landscape').then(() => {
288
222
  locked = true;
289
- }).catch(function (e) {
223
+ }).catch(e => {
290
224
  videojs__default['default'].log('Browser refused orientation lock:', e);
291
225
  });
292
226
  }
@@ -297,36 +231,40 @@ var onPlayerReady = function onPlayerReady(player, options) {
297
231
  }
298
232
  }
299
233
  };
300
-
301
234
  if (options.fullscreen.enterOnRotate || options.fullscreen.exitOnRotate) {
302
235
  if (videojs__default['default'].browser.IS_IOS) {
303
236
  window__default['default'].addEventListener('orientationchange', rotationHandler);
304
- player.on('dispose', function () {
237
+ player.on('dispose', () => {
305
238
  window__default['default'].removeEventListener('orientationchange', rotationHandler);
306
239
  });
307
240
  } else if (screen.orientation) {
308
241
  // addEventListener('orientationchange') is not a user interaction on Android
309
242
  screen.orientation.onchange = rotationHandler;
310
- player.on('dispose', function () {
243
+ player.on('dispose', () => {
311
244
  screen.orientation.onchange = null;
312
245
  });
313
246
  }
314
-
315
- player.on('fullscreenchange', function (_) {
316
- if (!player.isFullscreen() && locked) {
317
- screen.orientation.unlock();
318
- locked = false;
319
- }
320
- });
321
247
  }
322
-
323
- player.on('ended', function (_) {
248
+ player.on('fullscreenchange', _ => {
249
+ if (player.isFullscreen() && options.fullscreen.lockToLandscapeOnEnter && getOrientation() === 'portrait') {
250
+ screen.orientation.lock('landscape').then(() => {
251
+ locked = true;
252
+ }).catch(e => {
253
+ videojs__default['default'].log('Browser refused orientation lock:', e);
254
+ });
255
+ } else if (!player.isFullscreen() && locked) {
256
+ screen.orientation.unlock();
257
+ locked = false;
258
+ }
259
+ });
260
+ player.on('ended', _ => {
324
261
  if (locked === true) {
325
262
  screen.orientation.unlock();
326
263
  locked = false;
327
264
  }
328
265
  });
329
266
  };
267
+
330
268
  /**
331
269
  * A video.js plugin.
332
270
  *
@@ -347,6 +285,9 @@ var onPlayerReady = function onPlayerReady(player, options) {
347
285
  * Whether to leave fullscreen when rotating to portrait (if not locked)
348
286
  * @param {boolean} [options.fullscreen.lockOnRotate=true]
349
287
  * Whether to lock orientation when rotating to landscape
288
+ * Unlocked when exiting fullscreen or on 'ended
289
+ * @param {boolean} [options.fullscreen.lockToLandscapeOnEnter=false]
290
+ * Whether to always lock orientation to landscape on fullscreen mode
350
291
  * Unlocked when exiting fullscreen or on 'ended'
351
292
  * @param {boolean} [options.fullscreen.iOS=false]
352
293
  * Deprecated: Whether to disable iOS's native fullscreen so controls can work
@@ -362,25 +303,18 @@ var onPlayerReady = function onPlayerReady(player, options) {
362
303
  * Whether to disable when the video ends (e.g., if there is an endscreen)
363
304
  * Never shows if the endscreen plugin is present
364
305
  */
365
-
366
-
367
- var mobileUi = function mobileUi(options) {
368
- var _this = this;
369
-
370
- if (options === void 0) {
371
- options = {};
372
- }
373
-
306
+ const mobileUi = function (options = {}) {
374
307
  if (options.forceForTesting || videojs__default['default'].browser.IS_ANDROID || videojs__default['default'].browser.IS_IOS) {
375
- this.ready(function () {
376
- onPlayerReady(_this, videojs__default['default'].mergeOptions(defaults, options));
308
+ this.ready(() => {
309
+ onPlayerReady(this, videojs__default['default'].obj.merge(defaults, options));
377
310
  });
378
311
  }
379
- }; // Register the plugin with video.js.
380
-
312
+ };
381
313
 
382
- registerPlugin('mobileUi', mobileUi); // Include the version number.
314
+ // Register the plugin with video.js.
315
+ videojs__default['default'].registerPlugin('mobileUi', mobileUi);
383
316
 
317
+ // Include the version number.
384
318
  mobileUi.VERSION = version;
385
319
 
386
320
  module.exports = mobileUi;
@@ -1,2 +1,2 @@
1
- /*! @name videojs-mobile-ui @version 0.7.0 @license MIT */
2
- @-webkit-keyframes fadeAndScale{0%,to{opacity:0}25%{opacity:1}}@keyframes fadeAndScale{0%,to{opacity:0}25%{opacity:1}}.video-js.vjs-has-started .vjs-touch-overlay{position:absolute;pointer-events:auto;top:0}.video-js .vjs-touch-overlay{display:block;width:100%;height:100%;pointer-events:none}.video-js .vjs-touch-overlay.skip{opacity:0;-webkit-animation:fadeAndScale .6s linear;animation:fadeAndScale .6s linear;background-repeat:no-repeat;background-position:80% center;background-size:10%;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>')}.video-js .vjs-touch-overlay.skip.reverse{background-position:20% center;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>')}.video-js .vjs-touch-overlay .vjs-play-control{top:50%;left:50%;transform:translate(-50%,-50%);position:absolute;width:30%;height:80%;pointer-events:none;opacity:0;transition:opacity .3s ease}.video-js .vjs-touch-overlay .vjs-play-control .vjs-icon-placeholder::before{content:'';background-size:60%;background-position:center center;background-repeat:no-repeat;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="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/><path d="M0 0h24v24H0z" fill="none"/></svg>')}.video-js .vjs-touch-overlay .vjs-play-control.vjs-paused .vjs-icon-placeholder::before{content:'';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="M8 5v14l11-7z"/><path d="M0 0h24v24H0z" fill="none"/></svg>')}.video-js .vjs-touch-overlay .vjs-play-control.vjs-ended .vjs-icon-placeholder::before{content:'';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="M0 0h24v24H0z" fill="none"/><path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/></svg>')}.video-js .vjs-touch-overlay.show-play-toggle .vjs-play-control{opacity:1;pointer-events:auto}.video-js.vjs-mobile-ui-disable-end.vjs-ended .vjs-touch-overlay{display:none}
1
+ /*! @name videojs-mobile-ui @version 1.0.0 @license MIT */
2
+ @keyframes fadeAndScale{0%,to{opacity:0}25%{opacity:1}}.video-js.vjs-has-started .vjs-touch-overlay{position:absolute;pointer-events:auto;top:0}.video-js .vjs-touch-overlay{display:block;width:100%;height:100%;pointer-events:none}.video-js .vjs-touch-overlay.skip{opacity:0;animation:fadeAndScale .8s linear;background-repeat:no-repeat;background-position:80% center;background-size:10%;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>')}.video-js .vjs-touch-overlay.skip:after{content:attr(data-skip-text);position:absolute;top:60%;left:70%}.video-js .vjs-touch-overlay.skip.reverse{background-position:20% center;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>')}.video-js .vjs-touch-overlay.skip.reverse:after{right:70%;left:unset}.video-js .vjs-touch-overlay .vjs-play-control{top:50%;left:50%;transform:translate(-50%,-50%);position:absolute;width:30%;height:80%;pointer-events:none;opacity:0;transition:opacity .3s ease}.video-js .vjs-touch-overlay .vjs-play-control .vjs-icon-placeholder::before{content:'';background-size:60%;background-position:center center;background-repeat:no-repeat;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="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/><path d="M0 0h24v24H0z" fill="none"/></svg>')}.video-js .vjs-touch-overlay .vjs-play-control.vjs-paused .vjs-icon-placeholder::before{content:'';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="M8 5v14l11-7z"/><path d="M0 0h24v24H0z" fill="none"/></svg>')}.video-js .vjs-touch-overlay .vjs-play-control.vjs-ended .vjs-icon-placeholder::before{content:'';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="M0 0h24v24H0z" fill="none"/><path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/></svg>')}.video-js .vjs-touch-overlay.show-play-toggle .vjs-play-control{opacity:1;pointer-events:auto}.video-js.vjs-mobile-ui-disable-end.vjs-ended .vjs-touch-overlay{display:none}