Registers a function to be called when an element with the given selector is inserted into the DOM.
Use compilers to activate your custom Javascript behavior on matching elements.
You should migrate your DOMContentLoaded
callbacks to compilers. This will make sure they run both at page load and
when a new fragment is inserted later.
It will also organize your JavaScript snippets by selector of affected elements.
This jQuery compiler will insert the current time into a
<div class='current-time'></div>:
up.compiler('.current-time', function(element) {
var now = new Date()
element.textContent = now.toString()
})
The compiler function will be called once for each matching element when the page loads, or when a matching fragment is inserted later.
up.compiler() is a great way to integrate JavaScript libraries.
Let's say your JavaScript plugin wants you to call lightboxify()
on links that should open a lightbox. You decide to
do this for all links with an lightbox class:
<a href="river.png" class="lightbox">River</a>
<a href="ocean.png" class="lightbox">Ocean</a>
This JavaScript will do exactly that:
up.compiler('a.lightbox', function(element) {
lightboxify(element)
})
If your compiler returns a function, Unpoly will use this as a destructor to clean up if the element leaves the DOM. Note that in Unpoly the same DOM and JavaScript environment will persist through many page loads, so it's important to not create memory leaks.
You should clean up after yourself whenever your compilers have global
side effects, like a setInterval
or event handlers bound to the document root.
Here is a version of .current-time that updates
the time every second, and cleans up once it's done. Note how it returns
a function that calls clearInterval:
up.compiler('.current-time', function(element) {
function update() {
var now = new Date()
element.textContent = now.toString()
}
setInterval(update, 1000)
return function() {
clearInterval(update)
};
})
If we didn't clean up after ourselves, we would have many ticking intervals
operating on detached DOM elements after we have created and removed a couple
of <clock> elements.
In case you want to attach structured data to the event you're observing,
you can serialize the data to JSON and put it into an [up-data] attribute.
For instance, a container for a Google Map
might attach the location and names of its marker pins:
<div class='google-map' up-data='[
{ "lat": 48.36, "lng": 10.99, "title": "Friedberg" },
{ "lat": 48.75, "lng": 11.45, "title": "Ingolstadt" }
]'></div>
The JSON will be parsed and handed to your compiler as a second argument:
up.compiler('.google-map', function(element, pins) {
var map = new google.maps.Map(element)
pins.forEach(function(pin) {
var position = new google.maps.LatLng(pin.lat, pin.lng)
new google.maps.Marker({
position: position,
map: map,
title: pin.title
})
})
})
The selector to match.
The priority of this compiler. Compilers with a higher priority are run first. Two compilers with the same priority are run in the order they were registered.
If set to true and a fragment insertion contains multiple
elements matching the selector, compiler is only called once
with a jQuery collection containing all matching elements.
If set to true compiled fragment will be persisted during
page updates.
This has the same effect as setting an up-keep attribute on the element.
The function to call when a matching element is inserted.
The function takes the new element as the first argument.
If the element has an up-data attribute, its value is parsed as JSON
and passed as a second argument.
The function may return a destructor function that cleans the compiled
object before it is removed from the DOM. The destructor is supposed to
clear global state
such as timeouts and event handlers bound to the document.
The destructor is not expected to remove the element from the DOM, which
is already handled by up.destroy().