You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Connected.Components/TScripts/mudResizeObserver.js

143 lines
4.8 KiB

// Copyright (c) MudBlazor 2021
// MudBlazor licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
class MudResizeObserverFactory {
constructor() {
this._maps = {};
}
connect(id, dotNetRef, elements, elementIds, options) {
var existingEntry = this._maps[id];
if (!existingEntry) {
var observer = new MudResizeObserver(dotNetRef, options);
this._maps[id] = observer;
}
var result = this._maps[id].connect(elements, elementIds);
return result;
}
disconnect(id, element) {
//I can't think about a case, where this can be called, without observe has been called before
//however, a check is not harmful either
var existingEntry = this._maps[id];
if (existingEntry) {
existingEntry.disconnect(element);
}
}
cancelListener(id) {
//cancelListener is called during dispose of .net instance
//in rare cases it could be possible, that no object has been connect so far
//and no entry exists. Therefore, a little check to prevent an error in this case
var existingEntry = this._maps[id];
if (existingEntry) {
existingEntry.cancelListener();
delete this._maps[id];
}
}
}
class MudResizeObserver {
constructor(dotNetRef, options) {
this.logger = options.enableLogging ? console.log : (message) => { };
this.options = options;
this._dotNetRef = dotNetRef
var delay = (this.options || {}).reportRate || 200;
this.throttleResizeHandlerId = -1;
var observervedElements = [];
this._observervedElements = observervedElements;
this.logger('[MudBlazor | ResizeObserver] Observer initialized');
this._resizeObserver = new ResizeObserver(entries => {
var changes = [];
this.logger('[MudBlazor | ResizeObserver] changes detected');
for (let entry of entries) {
var target = entry.target;
var affectedObservedElement = observervedElements.find((x) => x.element == target);
if (affectedObservedElement) {
var size = entry.target.getBoundingClientRect();
if (affectedObservedElement.isInitialized == true) {
changes.push({ id: affectedObservedElement.id, size: size });
}
else {
affectedObservedElement.isInitialized = true;
}
}
}
if (changes.length > 0) {
if (this.throttleResizeHandlerId >= 0) {
clearTimeout(this.throttleResizeHandlerId);
}
this.throttleResizeHandlerId = window.setTimeout(this.resizeHandler.bind(this, changes), delay);
}
});
}
resizeHandler(changes) {
try {
this.logger("[MudBlazor | ResizeObserver] OnSizeChanged handler invoked");
this._dotNetRef.invokeMethodAsync("OnSizeChanged", changes);
} catch (error) {
this.logger("[MudBlazor | ResizeObserver] Error in OnSizeChanged handler:", { error });
}
}
connect(elements, ids) {
var result = [];
this.logger('[MudBlazor | ResizeObserver] Start observing elements...');
for (var i = 0; i < elements.length; i++) {
var newEntry = {
element: elements[i],
id: ids[i],
isInitialized: false,
};
this.logger("[MudBlazor | ResizeObserver] Start observing element:", { newEntry });
result.push(elements[i].getBoundingClientRect());
this._observervedElements.push(newEntry);
this._resizeObserver.observe(elements[i]);
}
return result;
}
disconnect(elementId) {
this.logger('[MudBlazor | ResizeObserver] Try to unobserve element with id', { elementId });
var affectedObservedElement = this._observervedElements.find((x) => x.id == elementId);
if (affectedObservedElement) {
var element = affectedObservedElement.element;
this._resizeObserver.unobserve(element);
this.logger('[MudBlazor | ResizeObserver] Element found. Ubobserving size changes of element', { element });
var index = this._observervedElements.indexOf(affectedObservedElement);
this._observervedElements.splice(index, 1);
}
}
cancelListener() {
this.logger('[MudBlazor | ResizeObserver] Closing ResizeObserver. Detaching all observed elements');
this._resizeObserver.disconnect();
this._dotNetRef = undefined;
}
}
window.mudResizeObserver = new MudResizeObserverFactory();