/** * Registers a callback when an element is appended to the document body. Note that the callback will be called * only once, if the element is appended more than once a new callback should be registered. * * @param element the HTML element which is going to be added to the body * @param callback {@link ObserverCallback} */ public static void onAttach(HTMLElement element, ObserverCallback callback) { if (element != null) { BodyObserver.addAttachObserver(element, callback); } }
/** * Registers a callback when an element is removed from the document body. Note that the callback will be called * only once, if the element is removed and re-appended a new callback should be registered. * * @param element the HTML element which is going to be removed from the body * @param callback {@link ObserverCallback} */ public static void onDetach(HTMLElement element, ObserverCallback callback) { if (element != null) { BodyObserver.addDetachObserver(element, callback); } }
/** * Check if the observer is already started, if not it will start it, then register and callback for when the * element is removed from the dom. */ static void addDetachObserver(HTMLElement element, ObserverCallback callback) { if (!ready) { startObserving(); } detachObservers.add(createObserver(element, callback, DETACH_UID_KEY)); }
private static void startObserving() { MutationObserver mutationObserver = new MutationObserver( (MutationRecord[] records, MutationObserver observer) -> { for (MutationRecord record : records) { onElementsRemoved(record); onElementsAppended(record); } return null; }); MutationObserverInit mutationObserverInit = MutationObserverInit.create(); mutationObserverInit.setChildList(true); mutationObserverInit.setSubtree(true); mutationObserver.observe(document.body, mutationObserverInit); ready = true; }
private static void onElementsRemoved(MutationRecord record) { List<ElementObserver> observed = new ArrayList<>(); List<HTMLElement> removedElements = stream(record.removedNodes) .filter(htmlElements()) .map(asHtmlElement()) .collect(toList()); for (ElementObserver elementObserver : detachObservers) { if (elementObserver.observedElement() == null) { observed.add(elementObserver); } else { if (removedElements.contains(elementObserver.observedElement()) || isChildOfObservedElement(removedElements, DETACH_UID_KEY, elementObserver.attachId())) { elementObserver.callback().onObserved(record); elementObserver.observedElement().removeAttribute(DETACH_UID_KEY); observed.add(elementObserver); } } } detachObservers.removeAll(observed); }
private static void onElementsAppended(MutationRecord record) { List<ElementObserver> observed = new ArrayList<>(); List<HTMLElement> addedElements = stream(record.addedNodes) .filter(htmlElements()) .map(asHtmlElement()) .collect(toList()); for (ElementObserver elementObserver : attachObservers) { if (elementObserver.observedElement() == null) { observed.add(elementObserver); } else { if (addedElements.contains(elementObserver.observedElement()) || isChildOfObservedElement(addedElements, ATTACH_UID_KEY, elementObserver.attachId())) { elementObserver.callback().onObserved(record); elementObserver.observedElement().removeAttribute(ATTACH_UID_KEY); observed.add(elementObserver); } } } attachObservers.removeAll(observed); }
/** * Check if the observer is already started, if not it will start it, then register and callback for when the * element is attached to the dom. */ static void addAttachObserver(HTMLElement element, ObserverCallback callback) { if (!ready) { startObserving(); } attachObservers.add(createObserver(element, callback, ATTACH_UID_KEY)); }