Skip to content

Instantly share code, notes, and snippets.

@samthor
Created September 9, 2018 01:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save samthor/c3745675e7b76c924f0c51628747e91c to your computer and use it in GitHub Desktop.
Save samthor/c3745675e7b76c924f0c51628747e91c to your computer and use it in GitHub Desktop.
helper JS to observe $ changes
/**
* Raw IDObserver class. Use via default method below.
*/
export class IDObserver {
/**
* @param {!Node|!ShadowRoot} root
*/
constructor(root) {
// if root is ShadowRoot, we have getElementById: otherwise use QS
const getById = root.getElementById ?
(id) => root.getElementById(id) :
(id) => root.querySelector(`#${CSS.escape(id)}`);
const refreshDOM = () => {
const cache = {};
for (const el of root.querySelectorAll('[id]')) {
cache[el.id] = el;
}
return cache;
};
let cache = refreshDOM();
// immediate $ getter
const getter = (id) => {
const has = cache[id];
if (has !== undefined) {
return has;
}
// always fallback to getById incase of DOM changes
const found = getById(id);
if (found) {
cache[id] = found;
}
return found;
};
this._object = new Proxy({}, {
has(target, key) { return getter(key) !== undefined; },
get(target, prop, receiver) { return getter(prop); },
deleteProperty(target, prop) { return false; },
set(obj, prop, value) { return false; },
ownKeys(target) {
cache = refreshDOM();
return Object.keys(this._cache);
},
});
const mo = new MutationObserver(() => {
cache = refreshDOM();
});
mo.observe(root, {attributeFilter: ['id'], subtree: true, childList: true});
// TODO(samthor): Should this provide a cleanup/shutdown method?
}
/**
* @return {!Object<string, !Node>}
*/
get object() {
return this._object;
}
}
/**
* Observes IDs within the given root node. This is useful to create a '$'-like object, e.g.:
* this.$ = new IDObserver(shadowRoot);
* this.$.idWithinRoot.textContent = '...';
*
* @param {!Node|!ShadowRoot} root
* @return {!Object<string, !Node>}
*/
export default function(root) {
return new IDObserver(root).object;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment