|
|
|
|
// 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();
|