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
package/index.html CHANGED
@@ -1,69 +1,194 @@
1
- <!doctype html>
1
+ <!DOCTYPE html>
2
2
  <html>
3
+
3
4
  <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
5
+ <meta charset="utf-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
7
  <title>videojs-mobile-ui Demo</title>
7
- <link href="node_modules/video.js/dist/video-js.css" rel="stylesheet">
8
- <link href="dist/videojs-mobile-ui.css" rel="stylesheet">
8
+ <link href="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20height%3D%2224px%22%20viewBox%3D%220%20-960%20960%20960%22%20width%3D%2224px%22%20fill%3D%22%231f1f1f%22%3E%3Cpath%20d%3D%22M419-80q-28%200-52.5-12T325-126L124-381q-8-9-7-21.5t9-20.5q20-21%2048-25t52%2011l74%2045v-328q0-17%2011.5-28.5T340-760q17%200%2029%2011.5t12%2028.5v200h299q50%200%2085%2035t35%2085v160q0%2066-47%20113T640-80H419Zm60-520q-17%200-28.5-11.5T439-640q0-2%205-20%208-14%2012-28.5t4-31.5q0-50-35-85t-85-35q-50%200-85%2035t-35%2085q0%2017%204%2031.5t12%2028.5q3%205%204%2010t1%2010q0%2017-11%2028.5T202-600q-11%200-20.5-6T167-621q-13-22-20-47t-7-52q0-83%2058.5-141.5T340-920q83%200%20141.5%2058.5T540-720q0%2027-7%2052t-20%2047q-5%209-14%2015t-20%206Z%22%2F%3E%3C%2Fsvg%3E" rel="icon" type="image/x-icon" />
9
+ <link href="node_modules/video.js/dist/video-js.css" rel="stylesheet" />
10
+ <link href="dist/videojs-mobile-ui.css" rel="stylesheet" />
9
11
  <style>
10
- .testEl {
11
- width: 10%;
12
- height: 10%;
13
- position: absolute;
14
- top: 0;
15
- pointer-events: none;
16
- display: none;
17
- }
12
+ .testEl {
13
+ width: 10%;
14
+ height: 10%;
15
+ position: absolute;
16
+ top: 0;
17
+ pointer-events: none;
18
+ display: none;
19
+ }
20
+
21
+ body {
22
+ font-size: 16px;
23
+ line-height: 1.4;
24
+ margin-bottom: 60px;
25
+ }
26
+
27
+ .video-container {
28
+ width: 100vw;
29
+ margin-left: calc(50% - 50vw);
30
+ }
31
+
32
+ video-js:fullscreen .vjs-control-bar {
33
+ font-size: 1.1em;
34
+ padding-bottom: 20px;
35
+ height: calc(3em + 20px);
36
+ }
37
+
38
+ #demoOptions {
39
+
40
+ ul {
41
+ list-style: none;
42
+ padding: 0;
43
+ margin: 0;
44
+ }
45
+
46
+ li {
47
+ margin-bottom: 10px;
48
+ }
49
+
50
+ label {
51
+ min-height: 44px;
52
+ /* Apple/Google tap target guidance */
53
+ cursor: pointer;
54
+ font-family: ui-monospace, 'Courier New', Courier, monospace;
55
+ }
56
+
57
+ /* Text inputs */
58
+ input[type="text"],
59
+ input[type="email"],
60
+ input[type="number"],
61
+ input[type="password"],
62
+ textarea {
63
+ width: 90%;
64
+ padding: 10px 12px;
65
+ font-size: 16px;
66
+ /* Prevents iOS zoom */
67
+ border: 1px solid #ccc;
68
+ border-radius: 6px;
69
+ }
70
+
71
+ /* Checkboxes (simple but usable) */
72
+ input[type="checkbox"] {
73
+ width: 20px;
74
+ height: 20px;
75
+ flex-shrink: 0;
76
+ }
77
+
78
+ /* Optional: subtle focus style */
79
+ input:focus,
80
+ textarea:focus {
81
+ outline: none;
82
+ border-color: #007aff;
83
+ /* iOS blue */
84
+ }
85
+
86
+ /* Optional: slightly separate groups */
87
+ li+li {
88
+ border-top: 1px solid #eee;
89
+ padding-top: 8px;
90
+ }
91
+
92
+ button {
93
+ font-size: 16px;
94
+ margin-bottom: 10px;
95
+ }
96
+ }
18
97
  </style>
19
98
  </head>
99
+
20
100
  <body>
21
- <video-js id="videojs-mobile-ui-player" class="video-js vjs-default-skin vjs-fluid" controls playsinline>
22
- <source src="//vjs.zencdn.net/v/oceans.mp4" type='video/mp4'>
23
- <source src="//vjs.zencdn.net/v/oceans.webm" type='video/webm'>
24
- </video-js>
101
+ <h1>videojs-mobile-ui test page.</h1>
102
+ <div class="video-container">
103
+ <video-js id="videojs-mobile-ui-player" class="video-js vjs-default-skin vjs-fluid" controls playsinline>
104
+ <source src="https://d2zihajmogu5jn.cloudfront.net/bipbop-advanced/bipbop_16x9_variant.m3u8"
105
+ type="application/x-mpegurl" />
106
+ </video-js>
107
+ </div>
25
108
  <ul>
26
109
  <li><a href="test/">Run unit tests in browser.</a></li>
27
- <li><a href="docs/api/">Read generated docs.</a></li>
28
110
  </ul>
29
111
  <h2>Options</h2>
30
- <ul id="options">
31
- <li>fullscreen:</li>
32
- <ul>
33
- <li><input type="checkbox" data-section="fullscreen" id="enterOnRotate">enterOnRotate</li>
34
- <li><input type="checkbox" data-section="fullscreen" id="exitOnRotate">exitOnRotate</li>
35
- <li><input type="checkbox" data-section="fullscreen" id="lockOnRotate">lockOnRotate</li>
36
- <li><input type="checkbox" data-section="fullscreen" id="iOS">iOS <b>Deprecated</b></li>
37
- <li><input type="checkbox" data-section="fullscreen" id="fullscreenDisabled">disabled</li>
112
+ <div id="demoOptions">
113
+ <p>Reload to apply changed options.</p>
114
+ <button id="reload">Reload with options</button>
115
+ <ul id="options">
116
+ <li>
117
+ <h3>fullscreen:</h3>
118
+ </li>
119
+ <ul>
120
+ <li>
121
+ <input type="checkbox" data-section="fullscreen" id="enterOnRotate" /> <label for="enterOnRotate">enterOnRotate</label>
122
+ </li>
123
+ <li>
124
+ <input type="checkbox" data-section="fullscreen" id="exitOnRotate" />
125
+ <label for="exitOnRotate">exitOnRotate</label>
126
+ </li>
127
+ <li>
128
+ <input type="checkbox" data-section="fullscreen" id="lockOnRotate" />
129
+ <label for="lockOnRotate">lockOnRotate</label>
130
+ </li>
131
+ <li>
132
+ <input type="checkbox" data-section="fullscreen" id="alwaysLockToLandscape" />
133
+ <label for="alwaysLockToLandscape">alwaysLockToLandscape</label>
134
+ </li>
135
+ <li>
136
+ <input type="checkbox" data-section="fullscreen" id="swipeToFullscreen" />
137
+ <label for="swipeToFullscreen">swipeToFullscreen</label>
138
+ </li>
139
+ <li>
140
+ <input type="checkbox" data-section="fullscreen" id="swipeFromFullscreen" />
141
+ <label for="swipeFromFullscreen">swipeFromFullscreen</label>
142
+ </li>
143
+ <li>
144
+ <input type="checkbox" data-section="fullscreen" id="fullscreenDisabled" />
145
+ <label for="disabled">disabled</label>
146
+ </li>
147
+ </ul>
148
+ <li>
149
+ <h3>touchControls:</h3>
150
+ </li>
151
+ <ul>
152
+ <li>
153
+ <input type="number" data-section="touchControls" id="seekSeconds" />
154
+ <label for="seekSeconds">seekSeconds</label>
155
+ </li>
156
+ <li>
157
+ <input type="number" data-section="touchControls" id="tapTimeout" />
158
+ <label for="tapTimeout">tapTimeout</label>
159
+ </li>
160
+ <li>
161
+ <input type="checkbox" data-section="touchControls" id="disableOnEnd" />
162
+ <label for="disableOnEnd">disableOnEnd</label>
163
+ </li>
164
+ <li>
165
+ <input type="checkbox" data-section="touchControls" id="touchControlsDisabled" />
166
+ <label for="disabled">disabled</label>
167
+ </li>
168
+ </ul>
38
169
  </ul>
39
- <li>touchControls:</li>
40
- <ul>
41
- <li><input type="number" data-section="touchControls" id="seekSeconds">seekSeconds</li>
42
- <li><input type="number" data-section="touchControls" id="tapTimeout">tapTimeout</li>
43
- <li><input type="checkbox" data-section="touchControls" id="disableOnEnd">disableOnEnd</li>
44
- <li><input type="checkbox" data-section="touchControls" id="touchControlsDisabled">disabled</li>
45
- </ul>
46
- </ul>
47
- <button id="reload">Reload with options</button>
170
+ </div>
48
171
  <ul id="log"></ul>
49
172
  <script src="node_modules/video.js/dist/video.js"></script>
50
173
  <script src="dist/videojs-mobile-ui.js"></script>
51
174
  <script>
52
- (function(window, videojs) {
175
+ (function (window, videojs) {
53
176
  var options = {
54
177
  fullscreen: {
55
178
  enterOnRotate: true,
56
179
  exitOnRotate: true,
57
180
  lockOnRotate: true,
58
- iOS: false,
59
- disabled: false
181
+ alwaysLockToLandscape: false,
182
+ swipeToFullscreen: false,
183
+ swipeFromFullscreen: false,
184
+ disabled: false,
60
185
  },
61
186
  touchControls: {
62
187
  seekSeconds: 10,
63
188
  tapTimeout: 300,
64
189
  disableOnEnd: false,
65
- disabled: false
66
- }
190
+ disabled: false,
191
+ },
67
192
  };
68
193
 
69
194
  var url = new URL(window.location);
@@ -73,8 +198,8 @@
73
198
 
74
199
  console.log(JSON.stringify(options, null, 2));
75
200
 
76
- Object.keys(options).forEach(function(section) {
77
- Object.keys(options[section]).forEach(function(prop) {
201
+ Object.keys(options).forEach(function (section) {
202
+ Object.keys(options[section]).forEach(function (prop) {
78
203
  const val = options[section][prop];
79
204
 
80
205
  if (prop === 'disabled') {
@@ -82,46 +207,62 @@
82
207
  }
83
208
 
84
209
  if (typeof val === 'boolean') {
85
- document.getElementById(prop).checked = val;
210
+ document.getElementById(prop).checked = val;
86
211
  }
87
212
  if (typeof val === 'number') {
88
- document.getElementById(prop).value = val;
213
+ document.getElementById(prop).value = val;
89
214
  }
90
215
  });
91
216
  });
92
217
 
93
- document.getElementById('options').querySelectorAll('input').forEach(function(opt) {
94
- opt.addEventListener('change', function() {
95
- if (this.type === 'checkbox') {
96
- const param = this.id.endsWith('Disabled') ? 'disabled' : this.id;
218
+ document
219
+ .getElementById('options')
220
+ .querySelectorAll('input')
221
+ .forEach(function (opt) {
222
+ opt.addEventListener('change', function () {
223
+ if (this.type === 'checkbox') {
224
+ const param = this.id.endsWith('Disabled')
225
+ ? 'disabled'
226
+ : this.id;
97
227
 
98
- options[this.getAttribute('data-section')][param] = this.checked;
99
- } else {
100
- options[this.getAttribute('data-section')][this.id] = parseFloat(this.value);
101
- }
102
- console.log(options);
228
+ options[this.getAttribute('data-section')][param] =
229
+ this.checked;
230
+ } else {
231
+ options[this.getAttribute('data-section')][this.id] =
232
+ parseFloat(this.value);
233
+ }
234
+ console.log(options);
235
+ });
103
236
  });
104
- });
105
237
 
106
- document.getElementById('reload').addEventListener('click', function() {
107
- url.searchParams.set('options', JSON.stringify(options));
238
+ document
239
+ .getElementById('reload')
240
+ .addEventListener('click', function () {
241
+ url.searchParams.set('options', JSON.stringify(options));
108
242
 
109
- window.location = url.href;
110
- })
243
+ window.location = url.href;
244
+ });
111
245
 
112
- window.addEventListener('orientationchange', function() {
246
+ window.addEventListener('orientationchange', function () {
113
247
  var el = document.createElement('li');
114
- var message = (new Date).toTimeString().split(' ')[0] + ' ' + window.orientation;
115
- message += (screen && screen.orientation ? ' ' + screen.orientation.type + ' ' + screen.orientation.angle : '');
248
+ var message =
249
+ new Date().toTimeString().split(' ')[0] + ' ' + window.orientation;
250
+ message +=
251
+ screen && screen.orientation
252
+ ? ' ' + screen.orientation.type + ' ' + screen.orientation.angle
253
+ : '';
116
254
  el.textContent = message;
117
255
  console.log(message);
118
256
  document.getElementById('log').appendChild(el);
119
257
  });
120
258
 
121
- var testPlayer = window.testPlayer = videojs('videojs-mobile-ui-player');
122
- testPlayer.endscreen = function() {};
259
+ var testPlayer = (window.testPlayer = videojs(
260
+ 'videojs-mobile-ui-player'
261
+ ));
262
+ testPlayer.endscreen = function () { };
123
263
  testPlayer.mobileUi(options);
124
- }(window, window.videojs));
264
+ })(window, window.videojs);
125
265
  </script>
126
266
  </body>
127
- </html>
267
+
268
+ </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "videojs-mobile-ui",
3
- "version": "0.7.0",
3
+ "version": "0.9.0-beta.3",
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",
@@ -68,24 +68,27 @@
68
68
  "README.md": "doctoc --notitle"
69
69
  },
70
70
  "dependencies": {
71
- "global": "^4.4.0",
72
- "video.js": "^7"
71
+ "global": "^4.4.0"
72
+ },
73
+ "peerDependencies": {
74
+ "video.js": "^6 || ^7"
73
75
  },
74
76
  "devDependencies": {
75
- "@babel/runtime": "^7.14.0",
76
- "@videojs/generator-helpers": "~2.0.2",
77
- "jsdoc": "^3.6.7",
78
- "karma": "^6.3.2",
79
- "postcss": "^8.2.13",
77
+ "@babel/runtime": "^7.28.6",
78
+ "@videojs/generator-helpers": "~3.2.0",
79
+ "husky": "^8.0.3",
80
+ "jsdoc": "^4.0.5",
81
+ "karma": "^6.4.4",
82
+ "postcss": "^8.5.6",
80
83
  "postcss-cli": "^8.3.1",
81
- "rollup": "^2.46.0",
82
- "sinon": "^9.1.0",
84
+ "rollup": "^2.79.2",
85
+ "sinon": "^14.0.1",
86
+ "video.js": "^7.21.7",
83
87
  "videojs-generate-karma-config": "~8.0.0",
84
- "videojs-generate-postcss-config": "~3.0.0",
85
- "videojs-generate-rollup-config": "~6.2.0",
86
- "videojs-generator-verify": "~3.0.3",
88
+ "videojs-generate-postcss-config": "^3.0.1",
89
+ "videojs-generate-rollup-config": "^7.0.2",
90
+ "videojs-generator-verify": "^4.1.3",
87
91
  "videojs-languages": "^2.0.0",
88
- "videojs-standard": "^8.0.4",
89
- "husky": "^6.0.0"
92
+ "videojs-standard": "^9.1.0"
90
93
  }
91
94
  }
package/src/plugin.css CHANGED
@@ -14,9 +14,9 @@
14
14
  }
15
15
  }
16
16
 
17
- .video-js {
17
+ .video-js.vjs-mobile-ui {
18
18
 
19
- &.vjs-has-started .vjs-touch-overlay {
19
+ &.vjs-has-started:not(.vjs-ad-playing) .vjs-touch-overlay {
20
20
  position: absolute;
21
21
  pointer-events: auto;
22
22
  top: 0;
@@ -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 {
@@ -83,4 +95,10 @@
83
95
  display: none;
84
96
  }
85
97
 
98
+ &:not(:fullscreen).using-fs-swipe-up,
99
+ &:fullscreen.using-fs-swipe-down {
100
+ touch-action: none;
101
+ overflow: hidden;
102
+ }
103
+
86
104
  }
package/src/plugin.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import videojs from 'video.js';
2
2
  import {version as VERSION} from '../package.json';
3
3
  import './touchOverlay.js';
4
+ import initSwipe from './swipeFullscreen.js';
4
5
  import window from 'global/window';
5
6
 
6
7
  // Default options for the plugin.
@@ -9,7 +10,9 @@ const defaults = {
9
10
  enterOnRotate: true,
10
11
  exitOnRotate: true,
11
12
  lockOnRotate: true,
12
- iOS: false,
13
+ lockToLandscapeOnEnter: false,
14
+ swipeToFullscreen: false,
15
+ swipeFromFullscreen: false,
13
16
  disabled: false
14
17
  },
15
18
  touchControls: {
@@ -21,6 +24,7 @@ const defaults = {
21
24
  };
22
25
 
23
26
  const screen = window.screen;
27
+ const registerPlugin = videojs.registerPlugin || videojs.plugin;
24
28
 
25
29
  /**
26
30
  * Gets 'portrait' or 'lanscape' from the two orientation APIs
@@ -48,9 +52,6 @@ const getOrientation = () => {
48
52
  return 'portrait';
49
53
  };
50
54
 
51
- // Cross-compatibility for Video.js 5 and 6.
52
- const registerPlugin = videojs.registerPlugin || videojs.plugin;
53
-
54
55
  /**
55
56
  * Add UI and event listeners
56
57
  *
@@ -58,23 +59,12 @@ const registerPlugin = videojs.registerPlugin || videojs.plugin;
58
59
  * @param {Player} player
59
60
  * A Video.js player object.
60
61
  *
61
- * @param {Object} [options={}]
62
+ * @param {MobileUiOptions} [options={}]
62
63
  * A plain object containing options for the plugin.
63
64
  */
64
65
  const onPlayerReady = (player, options) => {
65
66
  player.addClass('vjs-mobile-ui');
66
67
 
67
- if (options.fullscreen.iOS) {
68
- videojs.log.warn('videojs-mobile-ui: `fullscreen.iOS` is deprecated. Use Video.js option `preferFullWindow` instead.');
69
- if (videojs.browser.IS_IOS && videojs.browser.IOS_VERSION > 9 &&
70
- !player.el_.ownerDocument.querySelector('.bc-iframe')) {
71
- player.tech_.el_.setAttribute('playsinline', 'playsinline');
72
- player.tech_.supportsFullScreen = function() {
73
- return false;
74
- };
75
- }
76
- }
77
-
78
68
  if (!options.touchControls.disabled) {
79
69
 
80
70
  if (options.touchControls.disableOnEnd || typeof player.endscreen === 'function') {
@@ -104,20 +94,26 @@ const onPlayerReady = (player, options) => {
104
94
  return;
105
95
  }
106
96
 
97
+ if (options.fullscreen.swipeToFullscreen || options.fullscreen.swipeFromFullscreen) {
98
+ initSwipe(player, options);
99
+ }
100
+
107
101
  let locked = false;
108
102
 
109
103
  const rotationHandler = () => {
110
104
  const currentOrientation = getOrientation();
111
105
 
112
106
  if (currentOrientation === 'landscape' && options.fullscreen.enterOnRotate) {
113
- if (player.paused() === false) {
114
- player.requestFullscreen();
115
- if (options.fullscreen.lockOnRotate &&
107
+ if (!player.paused() && !player.isFullscreen()) {
108
+ player.requestFullscreen().catch((err) => {
109
+ player.log.warn('Browser refused fullscreen request:', err);
110
+ });
111
+ if ((options.fullscreen.lockOnRotate || options.fullscreen.lockToLandscapeOnEnter) &&
116
112
  screen.orientation && screen.orientation.lock) {
117
113
  screen.orientation.lock('landscape').then(() => {
118
114
  locked = true;
119
- }).catch((e) => {
120
- videojs.log('Browser refused orientation lock:', e);
115
+ }).catch((err) => {
116
+ videojs.log.warn('Browser refused orientation lock:', err);
121
117
  });
122
118
  }
123
119
  }
@@ -143,15 +139,21 @@ const onPlayerReady = (player, options) => {
143
139
  screen.orientation.onchange = null;
144
140
  });
145
141
  }
146
-
147
- player.on('fullscreenchange', _ => {
148
- if (!player.isFullscreen() && locked) {
149
- screen.orientation.unlock();
150
- locked = false;
151
- }
152
- });
153
142
  }
154
143
 
144
+ player.on('fullscreenchange', _ => {
145
+ if (player.isFullscreen() && options.fullscreen.lockToLandscapeOnEnter && getOrientation() === 'portrait') {
146
+ screen.orientation.lock('landscape').then(()=>{
147
+ locked = true;
148
+ }).catch((e) => {
149
+ videojs.log('Browser refused orientation lock:', e);
150
+ });
151
+ } else if (!player.isFullscreen() && locked) {
152
+ screen.orientation.unlock();
153
+ locked = false;
154
+ }
155
+ });
156
+
155
157
  player.on('ended', _ => {
156
158
  if (locked === true) {
157
159
  screen.orientation.unlock();
@@ -161,39 +163,10 @@ const onPlayerReady = (player, options) => {
161
163
  };
162
164
 
163
165
  /**
164
- * A video.js plugin.
165
- *
166
- * Adds a monile UI for player control, and fullscreen orientation control
166
+ * Adds a mobile UI for player control, and fullscreen orientation control
167
167
  *
168
168
  * @function mobileUi
169
- * @param {Object} [options={}]
170
- * Plugin options.
171
- * @param {boolean} [options.forceForTesting=false]
172
- * Enables the display regardless of user agent, for testing purposes
173
- * @param {Object} [options.fullscreen={}]
174
- * Fullscreen options.
175
- * @param {boolean} [options.fullscreen.disabled=false]
176
- * If true no fullscreen handling except the *deprecated* iOS fullwindow hack
177
- * @param {boolean} [options.fullscreen.enterOnRotate=true]
178
- * Whether to go fullscreen when rotating to landscape
179
- * @param {boolean} [options.fullscreen.exitOnRotate=true]
180
- * Whether to leave fullscreen when rotating to portrait (if not locked)
181
- * @param {boolean} [options.fullscreen.lockOnRotate=true]
182
- * Whether to lock orientation when rotating to landscape
183
- * Unlocked when exiting fullscreen or on 'ended'
184
- * @param {boolean} [options.fullscreen.iOS=false]
185
- * Deprecated: Whether to disable iOS's native fullscreen so controls can work
186
- * @param {Object} [options.touchControls={}]
187
- * Touch UI options.
188
- * @param {boolean} [options.touchControls.disabled=false]
189
- * If true no touch controls are added.
190
- * @param {int} [options.touchControls.seekSeconds=10]
191
- * Number of seconds to seek on double-tap
192
- * @param {int} [options.touchControls.tapTimeout=300]
193
- * Interval in ms to be considered a doubletap
194
- * @param {boolean} [options.touchControls.disableOnEnd=false]
195
- * Whether to disable when the video ends (e.g., if there is an endscreen)
196
- * Never shows if the endscreen plugin is present
169
+ * @param {Object} [options={}] Plugin options
197
170
  */
198
171
  const mobileUi = function(options = {}) {
199
172
  if (options.forceForTesting || videojs.browser.IS_ANDROID || videojs.browser.IS_IOS) {