improve code

This commit is contained in:
Rene
2021-04-14 22:43:09 +02:00
parent ea052b3001
commit ae5d08bc37
5 changed files with 46 additions and 21 deletions
@@ -72,6 +72,7 @@ const emptyStylePropsToZero = (stlyeObj: StyleObject, baseStyle?: StyleObject) =
{ ...baseStyle }
);
// TODO: observer textarea attrs if textarea
// TODO: tabindex, open etc.
const attrs = ['id', 'class', 'style', 'open'];
const paddingInfoFallback: PaddingInfo = {
@@ -44,7 +44,7 @@ export interface DOMObserverOptions {
_ignoreContentChange?: DOMObserverIgnoreContentChange;
}
export interface DOMObserver {
_disconnect: () => void;
_destroy: () => void;
_updateEventContentChange: (newEventContentChange?: DOMObserverEventContentChange) => void;
_update: () => void;
}
@@ -52,18 +52,21 @@ export interface DOMObserver {
// const styleChangingAttributes = ['id', 'class', 'style', 'open'];
// const mutationObserverAttrsTextarea = ['wrap', 'cols', 'rows'];
const createEventContentChange = (
target: Element,
eventContentChange: DOMObserverEventContentChange,
map: Map<Node, string>,
callback: (...args: any) => any
) => {
/**
* Creates a set of helper functions to observe events of elements inside the target element.
* @param target The target element of which the children elements shall be observed. (not only direct children but also nested ones)
* @param eventContentChange The event content change array. (array of tuples: selector and eventname(s))
* @param callback Callback which is called if one of the elements emits the corresponding event.
* @returns A object which contains a set of helper functions to destroy and update the observation of elements.
*/
const createEventContentChange = (target: Element, eventContentChange: DOMObserverEventContentChange, callback: (...args: any) => any) => {
let map: Map<Node, string> | undefined;
let eventContentChangeRef: DOMObserverEventContentChange;
const addEvent = (elm: Node, eventName: string) => {
const entry = map.get(elm);
const entry = map!.get(elm);
const newEntry = isUndefined(entry);
const registerEvent = () => {
map.set(elm, eventName);
map!.set(elm, eventName);
on(elm, eventName, callback);
};
@@ -75,10 +78,10 @@ const createEventContentChange = (
}
};
const _destroy = () => {
map.forEach((eventName: string, elm: Node) => {
map!.forEach((eventName: string, elm: Node) => {
off(elm, eventName, callback);
});
map.clear();
map!.clear();
};
const _updateElements = (getElements?: (selector: string) => Node[]) => {
if (eventContentChangeRef) {
@@ -105,23 +108,31 @@ const createEventContentChange = (
});
}
};
const _update = (newEventContentChange: DOMObserverEventContentChange) => {
const _updateEventContentChange = (newEventContentChange: DOMObserverEventContentChange) => {
map = map || new Map<Node, string>();
eventContentChangeRef = newEventContentChange;
_destroy();
_updateElements();
};
if (eventContentChange) {
_update(eventContentChange);
_updateEventContentChange(eventContentChange);
}
return {
_destroy,
_updateElements,
_update,
_updateEventContentChange,
};
};
/**
* Creates a DOM observer which observes DOM changes to either the target element or its children. (not only direct children but also nested ones)
* @param target The element which shall be observed.
* @param callback The callback which gets called if a change was detected.
* @param options The options for DOM change detection.
* @returns A object which represents the instance of the DOM observer.
*/
export const createDOMObserver = (
target: HTMLElement,
callback: (targetChangedAttrs: string[], targetStyleChanged: boolean, contentChanged: boolean) => any,
@@ -138,13 +149,12 @@ export const createDOMObserver = (
_ignoreContentChange,
} = options || {};
const {
_updateElements: updateEventContentChangeElements,
_destroy: destroyEventContentChange,
_update: updateEventContentChange,
_updateElements: updateEventContentChangeElements,
_updateEventContentChange: updateEventContentChange,
} = createEventContentChange(
target,
_observeContent && _eventContentChange,
new Map<Node, string>(),
debounce(() => {
if (isConnected) {
callback([], false, true);
@@ -155,7 +165,7 @@ export const createDOMObserver = (
// MutationObserver
const finalAttributes = _attributes || [];
const finalStyleChangingAttributes = _styleChangingAttributes || [];
const observedAttributes = finalAttributes.concat(finalStyleChangingAttributes); // TODO: observer textarea attrs if textarea
const observedAttributes = finalAttributes.concat(finalStyleChangingAttributes);
const observerCallback = (mutations: MutationRecord[]) => {
const ignoreTargetChange = _ignoreTargetChange || noop;
const ignoreContentChange = _ignoreContentChange || noop;
@@ -199,6 +209,7 @@ export const createDOMObserver = (
});
if (childListChanged && !isEmptyArray(totalAddedNodes)) {
// adds / removes the new elements from the event content change
updateEventContentChangeElements((selector) =>
totalAddedNodes.reduce<Node[]>((arr, node) => {
push(arr, find(selector, node));
@@ -224,7 +235,7 @@ export const createDOMObserver = (
isConnected = true;
return {
_disconnect: () => {
_destroy: () => {
if (isConnected) {
destroyEventContentChange();
mutationObserver.disconnect();
@@ -63,6 +63,13 @@ const scrollAmount = 3333333;
const directionIsRTL = (elm: HTMLElement): boolean => style(elm, 'direction') === 'rtl';
const domRectHasDimensions = (rect?: DOMRectReadOnly) => rect && (rect.height || rect.width);
/**
* Creates a size observer which observes any size, padding, margin and border changes of the target element. Depending on the options also direction and appear can be observed.
* @param target The target element which shall be observed.
* @param onSizeChangedCallback The callback which gets called after a size change was detected.
* @param options The options for size detection, whether to observe also direction and appear.
* @returns A object which represents the instance of the size observer.
*/
export const createSizeObserver = (
target: HTMLElement,
onSizeChangedCallback: (directionIsRTLCache?: CacheValues<boolean>) => any,
@@ -22,6 +22,12 @@ export interface TrinsicObserver {
};
}
/**
* Creates a trinsic observer which observes changes to intrinsic or extrinsic sizing for the height of the target element.
* @param target The element which shall be observed.
* @param onTrinsicChangedCallback The callback which gets called after a change was detected.
* @returns A object which represents the instance of the trinsic observer.
*/
export const createTrinsicObserver = (
target: HTMLElement,
onTrinsicChangedCallback: (heightIntrinsic: CacheValues<boolean>) => any
@@ -1,6 +1,6 @@
<div id="controls">
<button id="ioPolyfill">ResizeObserver polyfill</button>
<button id="roPolyfill">IntersectionObserver polyfill</button><br />
<button id="roPolyfill">IntersectionObserver polyfill</button>
<button id="ioPolyfill">ResizeObserver polyfill</button><br />
<label for="display">display</label>
<select name="display" id="display">
<option value="displayBlock">block</option>