/operator.js

An AJAX + routing library that transforms a normal site into a Single Page Application (SPA).

Primary LanguageJavaScript

Operator npm

An AJAX + routing library that transforms a normal site into a Single Page Application (SPA).

6.06kb gzipped.

Install

npm i operator.js --save

Usage

import operator from 'operator.js'

const app = operator({
  root: '#root',
  duration: 200, // transition duration
  ignore: [
    route => /logout/.test(route)
  ]
})

Options

Operator accepts a single options object with the following keys:

root

A selector for the root element of your site

const app = operator({
  root: '.js-root-element'
})

duration (optional)

Page transition duration, if desired. Operator adds an is-transitioning class to the documentElement while navigating for the duration provided here. default: 0

const app = operator({
  root: '.js-root-element',
  duration: 1000
})

ignore (optional)

An array of functions to test against the route. Functions must return booleans. If a test returns true, the route is followed via normal page load instead of AJAX. In the below example, routes matching products will be ignored:

const app = operator({
  root: '.js-root-element',
  ignore: [
    route => /products/.test(route)
  ]
})

Optionally, you can pass a sub-array containing a name value and a test function. If the test returns true, an event (name) is emitted with an object as payload. The payload object contains the native DOM event object returned from delegate and the matched route:

const app = operator({
  root: '#root',
  ignore: [
    ['products', route => /products/.test(route)]
  ]
})

app.on('products', ({event, route}) => {
  // do stuff
  // you can also event.preventDefault()
})

API

import operator from 'operator.js'

.on(event, callback)

Operator emits the following events:

before:route

Before the route is resolved and the page loaded. The callback recieves the route to be resolved.

operator.on('before:route', ({ route }) => {
  // do stuff  
})

after:route

After the route is resolved and the page loaded. The callback recieves the new route and page title.

operator.on('after:route', ({ route, title }) => {
  // do stuff  
})

before:transition

Before the page starts its transition. The callback recieves no params.

operator.on('before:transition', () => {
  // do stuff  
})

after:transition

After the page completes its transition. The callback recieves no params.

operator.on('after:transition', () => {
  // do stuff  
})

.go(route, callback)

Navigate to a given route.

operator.go('/products', (route, title) => {
  // do stuff
})

.push(route)

Update History and set a new active URL, but don't fetch any data. Useful for manual route manipulation relating to UI changes.

operator.push('/products/lightbox-open')

// or for hash
operator.push('#anchor')

.getState()

Returns an object with the current route and title values.

operator.getState() // { route: '/products', title: 'Products' }

Common Use Cases

Anchors

By default, operator will ignore anchors and let native browser behavior take over. You can, however, intercept these hash events using the ignore option. The below example uses to jump.js to smooth-scroll to the anchor target:

import jump from 'jump.js'

const app = operator({
  root: '#root',
  ignore: [
    ['hash', path => /#/.test(path)]
  ]
})

app.on('hash', ({event}) => {
  event.preventDefault()
  let hash = event.delegateTarget.getAttribute('href')
  jump(hash, { duration: 500 })
})

Client-side Redirects

Using the ignore option, you can block a route and navigate to another, effectively creating a redirect. However, operator will not redirect on initial load. Currently.

const app = operator({
  root: '#root',
  ignore: [
    ['products', path => /products/.test(path)]
  ]
})

app.on('products', ({event}) => {
  event.preventDefault()
  app.go('/')
})

Dependencies

Related Projects

TODO

  1. On-page-load redirects?

MIT License - Would love to hear your thoughts! :)