1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
/**
* @file resize-manager.js
*/
import window from 'global/window';
import { debounce } from './utils/fn.js';
import * as Events from './utils/events.js';
import { merge } from './utils/obj.js';
import Component from './component.js';
/**
* A Resize Manager. It is in charge of triggering `playerresize` on the player in the right conditions.
*
* It'll either create an iframe and use a debounced resize handler on it or use the new {@link https://wicg.github.io/ResizeObserver/|ResizeObserver}.
*
* If the ResizeObserver is available natively, it will be used. A polyfill can be passed in as an option.
* If a `playerresize` event is not needed, the ResizeManager component can be removed from the player, see the example below.
*
* @example <caption>How to disable the resize manager</caption>
* const player = videojs('#vid', {
* resizeManager: false
* });
*
* @see {@link https://wicg.github.io/ResizeObserver/|ResizeObserver specification}
*
* @extends Component
*/
class ResizeManager extends Component {
/**
* Create the ResizeManager.
*
* @param {Object} player
* The `Player` that this class should be attached to.
*
* @param {Object} [options]
* The key/value store of ResizeManager options.
*
* @param {Object} [options.ResizeObserver]
* A polyfill for ResizeObserver can be passed in here.
* If this is set to null it will ignore the native ResizeObserver and fall back to the iframe fallback.
*/
constructor(player, options) {
let RESIZE_OBSERVER_AVAILABLE = options.ResizeObserver || window.ResizeObserver;
// if `null` was passed, we want to disable the ResizeObserver
if (options.ResizeObserver === null) {
RESIZE_OBSERVER_AVAILABLE = false;
}
// Only create an element when ResizeObserver isn't available
const options_ = merge({
createEl: !RESIZE_OBSERVER_AVAILABLE,
reportTouchActivity: false
}, options);
super(player, options_);
this.ResizeObserver = options.ResizeObserver || window.ResizeObserver;
this.loadListener_ = null;
this.resizeObserver_ = null;
this.debouncedHandler_ = debounce(() => {
this.resizeHandler();
}, 100, false, this);
if (RESIZE_OBSERVER_AVAILABLE) {
this.resizeObserver_ = new this.ResizeObserver(this.debouncedHandler_);
this.resizeObserver_.observe(player.el());
} else {
this.loadListener_ = () => {
if (!this.el_ || !this.el_.contentWindow) {
return;
}
const debouncedHandler_ = this.debouncedHandler_;
let unloadListener_ = this.unloadListener_ = function() {
Events.off(this, 'resize', debouncedHandler_);
Events.off(this, 'unload', unloadListener_);
unloadListener_ = null;
};
// safari and edge can unload the iframe before resizemanager dispose
// we have to dispose of event handlers correctly before that happens
Events.on(this.el_.contentWindow, 'unload', unloadListener_);
Events.on(this.el_.contentWindow, 'resize', debouncedHandler_);
};
this.one('load', this.loadListener_);
}
}
createEl() {
return super.createEl('iframe', {
className: 'vjs-resize-manager',
tabIndex: -1,
title: this.localize('No content')
}, {
'aria-hidden': 'true'
});
}
/**
* Called when a resize is triggered on the iframe or a resize is observed via the ResizeObserver
*
* @fires Player#playerresize
*/
resizeHandler() {
/**
* Called when the player size has changed
*
* @event Player#playerresize
* @type {Event}
*/
// make sure player is still around to trigger
// prevents this from causing an error after dispose
if (!this.player_ || !this.player_.trigger) {
return;
}
this.player_.trigger('playerresize');
}
dispose() {
if (this.debouncedHandler_) {
this.debouncedHandler_.cancel();
}
if (this.resizeObserver_) {
if (this.player_.el()) {
this.resizeObserver_.unobserve(this.player_.el());
}
this.resizeObserver_.disconnect();
}
if (this.loadListener_) {
this.off('load', this.loadListener_);
}
if (this.el_ && this.el_.contentWindow && this.unloadListener_) {
this.unloadListener_.call(this.el_.contentWindow);
}
this.ResizeObserver = null;
this.resizeObserver = null;
this.debouncedHandler_ = null;
this.loadListener_ = null;
super.dispose();
}
}
Component.registerComponent('ResizeManager', ResizeManager);
export default ResizeManager;
|