Skip to content

Commit

Permalink
fix(observedom): Callback not being called for changes other than chi…
Browse files Browse the repository at this point in the history
…ldList changes (#1025)

* fix(observedom): Callback not being called for changes other than node inert/remove

Allow callback to be called based on passed options.

Previously it was only being called if nodes were added or inserted, regardless of which options were passed (i.e. attribute changes, childList, textnode changes, etc.)

This fix remove this restriction.

* Create loose-equal.js

* Update index.js

* Update observe-dom.js

* Update index.js

* Delete loose-equal.js

* Update observe-dom.js

* Update observe-dom.js

* Update observe-dom.js

* Update observe-dom.js
  • Loading branch information
tmorehouse committed Sep 11, 2017
1 parent 72ffba9 commit 88cfaef
Showing 1 changed file with 32 additions and 3 deletions.
35 changes: 32 additions & 3 deletions lib/utils/observe-dom.js
@@ -1,5 +1,6 @@

import { assign } from '../utils/object';
import { assign } from './object';

/**
* Observe a DOM element changes, falls back to eventListener mode
* @param {Element} el The DOM element to observe
Expand All @@ -14,14 +15,42 @@ export default function observeDOM(el, callback, opts) {
if (MutationObserver) {
// Define a new observer
const obs = new MutationObserver(mutations => {
if (mutations[0].addedNodes.length > 0 || mutations[0].removedNodes.length > 0) {
let changed = false;
// A Mutation can contain several changes, so we loop through them to see what has changed
// We break out of the loop early if any "significant" change has been detected
for (let i = 0; i < mutations.length && !changed; i++) {
// The muttion record
const mutation = mutations[i];
// Mutation Type
const type = mutation.type;
// DOM Node
const target = mutation.target;
// Previous Value (only for characterData and attributes)
const old = mutation.oldValue;
if (type === 'characterData' && target.nodeType === Node.TEXT_NODE && old !== target.data) {
// We ignore nodes that are not TEXt (i.e. comments, etc) as they don't change layout
// Updating character data with the same value still triggers a mutation
// So we compare the old value to the new value
changed = true;
} else if (type === 'attributes' && target.getAttribute(mutation.attributeName) !== old) {
// Updating an attribute with the same value still triggers a mutation
// So we compare the old value to the new value
changed = true;
} else if (type === 'childList' && (mutation.addedNodes.length > 0 || mutation.removedNodes.length > 0)) {
// This includes HTMLElement and Text Nodes being added/removed
changed = true;
}
}
if (changed) {
// We only call the callback if a change that could affect layout/size truely happened.
callback();
}
});

// Have the observer observe foo for changes in children
// Have the observer observe foo for changes in children, etc
obs.observe(el, assign({childList: true, subtree: true}, opts));
} else if (eventListenerSupported) {
// Legacy interface. most likely not used in modern browsers
el.addEventListener('DOMNodeInserted', callback, false);
el.addEventListener('DOMNodeRemoved', callback, false);
}
Expand Down

0 comments on commit 88cfaef

Please sign in to comment.