Edit this page

up.script up.compiler(selector, [options], compiler)
JavaScript function

Registers a function to be called when an element with the given selector is inserted into the DOM.

Compiler functions run both at page load and when a new fragment is inserted later. This makes compilers a great tool to activate custom JavaScript behavior on matching elements.

When an element with children is inserted, the compiler function is called once for each match in the new subtree.

Example

This 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 rendered later.

Prefer compilers over DOMContentLoaded

Listeners to DOMContentLoaded (or load) only run when the page is loaded initially. They will not run for subsequent fragment updates within the page. Compiler functions run both at page load and when a new fragment is inserted later. q You should migrate your DOMContentLoaded callbacks to compilers. See Migrating legacy JavaScripts for advice on migrating legacy applications.

Integrating JavaScript libraries

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)
})

Cleaning up after yourself

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) {
  let update = () => element.textContent = new Date().toString()
  let updateInterval = setInterval(update, 1000)
  return () => clearInterval(updateInterval)
})

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 .current-time elements.

An alternative way to register a destructor function is up.destructor().

Important

The destructor function is not expected to remove the element from the DOM.

Passing parameters to a compiler

You may attach data to an element using HTML5 data attributes or encoded as relaxed JSON in an [up-data] attribute:

<span class="user" up-data="{ age: 31, name: 'Alice' }">Alice</span>

An object with the element's attached data will be passed to your compilers as a second argument:

up.compiler('.user', function(element, data) { // mark: data
  console.log(data.age)  // result: 31
  console.log(data.name) // result: "Alice"
})

See attaching data to elements for more details and examples.

Throwing exceptions from compilers

It is safe to throw exceptions from a compiler or its destructor. A crashing compiler will not interrupt a render pass, or prevent other compilers on the same element.

Exceptions thrown by compiler functions are logged to the browser's error console. Unpoly also emits an error event on window.

See errors in user code for details.

Accessing information about the render pass

Compilers may accept a third argument with information about the current render pass:

up.compiler('.user', function(element, data, meta) { // mark: meta
  console.log(meta.layer.mode)   // result: "root"
  console.log(meta.revalidating) // result: true
})

The following properties are available:

Property Type   Description
meta.layer up.Layer   The layer of the fragment being compiled.
This has the same value as up.layer.current.
meta.revalidating boolean optional Whether the element was reloaded for the purpose of cache revalidation.

Registering compilers after booting

When you deliver your JavaScript in multiple files, you may register compilers after Unpoly was booted.

When compilers are registered after Unpoly was booted, it is run on current elements, but only if the compiler has the default priority.

If the compiler has a non-default priority, it is run on future fragments only. In this case either remove the { priority } option or manually call up.hello() on an element that should be recompiled.


Parameters

selector
required

The selector to match.

string
[options.priority=0]
optional

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.

number
[options.batch=false]
optional

If set to true and a fragment insertion contains multiple elements matching selector, the compiler function is only called once with all these elements.

boolean
compiler
required

The function to call when an element matching selector is inserted.

The function may accept up to three arguments:

  1. The new element being compiled.
  2. Any attached data.
  3. Information about the current render pass.

The function may return a destructor function that cleans the compiled object before it is removed from the DOM. The destructor function is called with the compiled element.

Function(element, data, meta): Function(element)