@playkit-js/playkit-js
Version:
[](https://github.com/kaltura/playkit-js/actions/workflows/run_canary.yaml) [ • 3.3 kB
text/typescript
import { FakeEvent } from '../event/fake-event';
import { FakeEventTarget } from '../event/fake-event-target';
import { CustomEventType } from '../event/event-type';
/**
* A Factory class to create a resize observer for the player.
*/
class ResizeWatcher extends FakeEventTarget {
private _observer?: ResizeObserver | IFrameObserver;
private _el?: HTMLElement;
constructor() {
super();
}
/**
* Removes resize listeners.
* @returns {void}
*/
public destroy(): void {
if (this._observer) {
this._observer.disconnect();
}
this._observer = undefined;
this._el = undefined;
}
/**
* Start listening to a resize of the element.
* @param {HTMLElement} el - the element to listen to.
* @returns {void}
*/
public init(el: HTMLElement): void {
if (this._observer) return;
this._el = el;
window.ResizeObserver ? this._createNativeObserver() : this._createIframeObserver();
if (this._el instanceof HTMLElement && this._observer) {
(this._observer as ResizeObserver | IFrameObserver).observe(this._el);
}
}
private _createNativeObserver(): void {
this._observer = new ResizeObserver((entries) => {
entries.forEach(() => {
this._triggerResize();
});
});
}
private _createIframeObserver(): void {
this._observer = new IFrameObserver(this._triggerResize.bind(this));
}
private _triggerResize(): void {
this.dispatchEvent(new FakeEvent(CustomEventType.RESIZE));
}
}
const IFRAME_CLASS_NAME: string = 'playkit-size-iframe';
/**
* This class mimics the API of the ResizeObserver API (currently available only in Chrome).
* Creates an empty iFrame next to the player container, which gets the dimensions of it's parent and listens to
* the iframes resize event.
* @param {Function} callback - the function to be called when a resize event is detected.
*/
class IFrameObserver {
private _observersStore: { [id: number]: HTMLIFrameElement } = {};
private _onChangeCallback: () => void;
constructor(callback: () => void) {
this._onChangeCallback = callback;
}
/**
* start detecting resize event
* @param {HTMLElement} el - The element that is going to be resized.
* @returns {void}
*/
public observe(el: HTMLElement): void {
const iframe = this._createIframe();
const playerId = el.getAttribute('id');
this._observersStore[playerId!] = iframe;
el.appendChild(iframe);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
iframe.contentWindow.onresize = (): void => this._onChangeCallback();
}
/**
* remove all resize listeners
* @returns {void}
*/
public disconnect(): void {
for (const target in this._observersStore) {
const el = document.getElementById(target);
const iframe = this._observersStore[target];
iframe.onresize = null;
if (el) {
el.removeChild(iframe);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
delete this._observersStore[el.getAttribute('id')];
}
}
}
private _createIframe(): HTMLIFrameElement {
const iframe = document.createElement('iframe');
iframe.className = IFRAME_CLASS_NAME;
return iframe;
}
}
export { ResizeWatcher };