Example HTML
All of the code examples below reference the following basic HTML:
<!-- Demo Site -->
<!-- https://f6yx6z.csb.app/ -->
<html>
<head>
<!-- The Evolv snippet must be loaded before the mutate library can be used -->
<script
src="https://media.evolv.ai/asset-manager/releases/latest/webloader.min.js"
data-evolv-environment="c1325716de"
data-evolv-pushstate="true"
></script>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
/>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<nav>
<ul>
<li class="navItemOne styleOne styleTwo styleThree">nav item 1</li>
<li class="navItemTwo">nav item 2</li>
<li>nav item 3</li>
<li>nav item 4</li>
</ul>
</nav>
<main>
<div class="section section-one">
<h1>Section One</h1>
<div class="content">
<h2>Yar Pirate Ipsum</h2>
<p>
Prow scuttle parrel provost Sail ho shrouds spirits boom mizzenmast
yardarm. Pinnace holystone mizzenmast quarter crow's nest nipperkin
grog yardarm hempen halter furl. Swab barque interloper chantey
doubloon starboard grog black jack gangway rutters.
</p>
</div>
</div>
<div class="section section-two">
<h1>Section Two</h1>
<div class="content">
<img
src="https://pirateipsum.me/img/poster1.jpg"
alt="pirate ipsum poster 1"
/>
<img
src="https://pirateipsum.me/img/poster2.jpg"
alt="pirate ipsum poster 2"
/>
</div>
</div>
<div class="section section-three">
<h1>Section Three</h1>
<div class="content">
<a href="https://evolv.ai/">Evolv AI</a>
</div>
</div>
</main>
</body>
</html>
In order to mutate an element or elements on the page, you need to first collect the element(s);
The collect method requires two parameters:
- The selector of the element(s)
- The name that you would like to use to refer to the collector. This name can be whatever you'd like.
var collect = window.evolv.collect;
var mutate = window.evolv.mutate;
collect("nav > ul", "navList");
collect("nav > ul > li", "navItem");
collect(".navItemOne", "navItemOne");
collect(".section-one", "sectionOne");
collect(".section-one p", "sectionOneCopy");
collect(".section-two img", "sectionTwoImage");
collect(".section-three a", "sectionThreeLink");
In the example above, the following number of elements will be collected for each of the following collector names:
- navList - 1
- navItem - 4
- navItemOne - 1
- sectionOneCopy - 1
- sectionTwoImage - 2
- sectionThreeLink - 1
Once an element has been collected, the element will have a class added to it that prefixes the collector name with mutate-
, thus all of navItem
elements will have the class mutate-navItem
added.
The subscribe
method behaves like a mutationObserver allowing you to run a callback method when a collected component is added, modified, or removed from the page.
collect.get('sectionTwoImage').subscribe((action, sectionTwoImage) => {
switch (action) {
case 0:
console.log('sectionTwoImage has been collected and exists in the DOM');
break;
case 1:
console.log('sectionTwoImage has been removed the DOM');
break;
case 2:
console.log('sectionTwoImage has been modified');
break;
default:
// action will always be 0, 1, or 2.
}
});
A customMutation gives you a reference to each element collected and allows you to manipulate the element with standarad JavaScript.
mutate('sectionOneCopy').customMutation((state, sectionOneCopy) => {
// log the element collected for sectionOneCopy
console.log('sectionOneCopy: ', sectionOneCopy);
// change the textContent of the element
sectionOneCopy.textContent = "this is my new copy";
// add an attribute to the element
sectionOneCopy.setAttribute('myNewAttribute', 'my new attribute value');
});
The .on()
method is a shorthand way to add an event listener to the element(s) collected.
mutate('navItem').on('click', (e) => {
console.log(`${e.target.textContent} clicked!`);
});
The .attributes()
method allows you to manipulate existing element attributes or add a new attributes. Notice that both images will change since the collector is looking at the selector .section-two img
. If we want to change only the first image, we'd need to collect only the first image by making the selector more specific.
mutate('sectionTwoImage').attributes({
'src': 'https://picsum.photos/200/300',
'class': 'cheeseburger'
});
The .text()
method will update the text of the component that you are mutating.
mutate('navItemOne').text('updated text');
The .html()
method allows you to replace the innerHTML of the element mutated with the HTML that you pass into the method.
mutate('sectionOneCopy').html(`
<ul>
<li>I</li>
<li>can</li>
<li>replace</li>
<li>the</li>
<li>existing</li>
<li>HTML</li>
<li>with</li>
<li>anything</li>
<li>I</li>
<li>want!</li>
</ul>
`);
The .classes()
method adds or removes classes from a collected component. In the following example, classOne
will be removed from the first navItem
component and classFour
will be added to all of the navItem
components.
mutate('navItem').classes({
'classOne': false,
'classFour': true
});
The .styles()
method adds or updates inline styles for a collected component. In the following example, color: blue;
will be added as an inline style to all navItem
components.
mutate('navItem').styles({
'color': 'blue'
});
The .hide()
method will set an inline style on the element(s) collected to display: none
.
mutate('sectionOneCopy').hide();
The .child()
method takes a selector and finds the first child element that matches the selector.
In the following example, the class sectionOneTitle
will be added to the <h1>
element in sectionOne
.
mutate("navList")
.child("li")
.classes({
'firstNavItem': true
});
The .children()
method gives a reference to all of the immediate child elements.
In the following example, the class sectionOneChild
will be added to the h1
and div
children in sectionOne
.
mutate("sectionOne")
.children()
.classes({
'sectionOneChild': true
});
The .parent()
method takes a selector and finds the first ancestor element that matches the selector.
In the following example, the class sectionOneCopyAncestor
will be added to the <main>
element.
mutate("sectionOneCopy")
.parent('main')
.classes({
'sectionOneCopyAncestor': true
});
The .parents()
method gives a reference to all of the ancestor elements.
In the following example, the class sectionOneChild
will be added to the h1
and div
children in sectionOne
.
mutate("sectionOne")
.parents()
.classes({
'sectionOneAncestor': true
});
The inject()
method will insert HTML or an element next to the element being mutated. Essentially, it is a shorthand method for insertAdjacentHTML
or insertAdjacentElement
.
Arguments The .inject
method takes in two arguments, where the second argument is optional and defaults to true.
- an HTML string or element reference.
- a boolean value for whether or not the HTML element created/element reference should be cloned.
Placement Options
-
.before()
- behaves likebeforebegin
-
.prepend()
- behaves likeafterbegin
-
.append()
- behaves likebeforeend
-
.after()
- behaves likeafterend
In the following HTML example, a new <li>
will be inserted before navItemOne
.
mutate('navItemOne').inject(`
<li class="navItemZero">nav item 0</li>
`).before();
In the following Element example, navItemTwo
will be placed before navItemOne
.
mutate("navItemOne")
.inject(document.querySelector(".navItemTwo"), false)
.before();
In the following Element example, navItemTwo
will be cloned and the clone will be placed before navItemOne
. This results in 2 navItemTwo
elements.
mutate("navItemOne")
.inject(document.querySelector(".navItemTwo"), true)
.before();