growthbook / dom-mutator Goto Github PK
View Code? Open in Web Editor NEWApply persistent DOM Mutations on top of HTML you don't control.
Home Page: https://growthbook.github.io/dom-mutator/
License: MIT License
Apply persistent DOM Mutations on top of HTML you don't control.
Home Page: https://growthbook.github.io/dom-mutator/
License: MIT License
There are 2 persistence features when calling mutate
:
Both of these have a performance cost and should have options to disable on a case-by-case basis.
Only able to reproduce on an actual site, not with Jest :(
applyMutations should only update the virtual DOM and mark the element as dirty if needed.
Then, in a requestAnimationFrame, call setValue to update the real DOM.
Hopefully this lets all changes queue up and be applied at once to avoid loops and throttle DOM updates.
mutate("div", "appendHTML", "<b>foo");
When a mutation comes in, we compare the actual HTML to the desired HTML to see if we need to re-apply the mutation. When setting innerHTML, the browser transforms the string passed in to valid HTML (e.g. <b>foo
becomes <b>foo</b>
). So this comparison check always fails and we always append to the end, which in turn causes another mutation and an infinite loop of appending.
A possible fix is to first set innerHTML on a temporary detached element and then read it back out to get the transformed HTML.
document.body.innerHTML = '<div>foo</div>';
const revert = mutate('div', 'addClass', 'hello');
await sleep();
revert();
mutate('div', 'addClass', 'hello');
await sleep();
// The below fails, it actually equals `<div>foo</div>`
expect(document.body.innerHTML).toEqual('<div class="hello">foo</div>');
If you call mutate("#myid", ...)
, once a matching element is found, we can stop waiting for new elements to appear, since ids are unique on a page.
[^,]*#id
- id match (with optional narrowing prefix)body
or html
- specific elements that can only exist once on a pageWe can also add an optional 4th argument to mutate
with config options, one of which explicitly says to only match the first element found.
Currently, there's an infinite loop when 2 mutations affect the same attribute of the same element. This only affects mutation types setAttribute
, appendHTML
, and setHTML
.
Examples:
// Can break even with different selectors and mutation types
mutate('p', 'setHTML', 'foo');
mutate('p.myclass', 'appendHTML', 'bar');
// setAttribute can also conflict with addClass and removeClass
mutate('p', 'addClass', 'foo');
mutate('p', 'setAttribute', 'class="bar"');
The mutations don't necessarily have to have the same selector either, one could target div
another could target .class
and they both could reference the same element.
One solution is to keep a Map of Element to attribute handler. If a new mutation affects the same attribute as an existing mutation, revert the old mutation first.
We store the original innerHTML
to revert, but this creates new DOM nodes instead of reverting to the old ones. This breaks things like React that are using element references and also breaks event listeners.
Instead, we can store the original children nodes and restore them
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.