npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

operator.js

v3.5.4

Published

A drop-in "PJAX" solution for fluid, smooth transitions between pages. **2.87kb gzipped.** Zero stress.

Downloads

11

Readme

operator.js

A drop-in "PJAX" solution for fluid, smooth transitions between pages. 2.87kb gzipped. Zero stress.

js-standard-style

Features

  1. Simple config
  2. Easily handle transitions with CSS
  3. Pages are cached after initial visit
  4. Pre-cache select pages, as needed
  5. Parametized routes
  6. Async-by-default, easy data loading between routes
  7. Manages scroll position between route changes
  8. Client-side redirects

Install

npm i operator.js --save

Usage

Import the library and call it with an empty object to use the default options.

import operator from 'operator.js'

const app = operator({})

Operator requires a single wrapper around each of your pages.

<div id='root'>
  <!--> Page content here <!-->
</div>

You'll also want some minimal CSS. Below is a basic fade-in/fade-out effect.

#root {
  transition: opacity var(--fast) var(--ease);
}
.operator-is-transitioning #root {
  opacity: 0;
}

And that's it. Internal links will now smoothly transition automatically.


Options

The operator factory accepts a single options object.

const app = operator({
  // options
})

Available options

root - string

The id of your outer wrapper. Default: root.

const app = operator({
  root: 'root'
})

transitionSpeed - number

The speed of your CSS transition, can be any number (milliseconds). Default: 0.

const app = operator({
  transitionSpeed: 400
})

routes - object

An object where the keys are the routes and values are the route handlers. Each handler should return true to allow operator to follow the route. If you return false, the route will be followed via a normal page load. This is useful for a variety of reasons.

Handlers can also return an instance of Promise. Within this Promise, you can request data for the next route, perform custom animations, or whatever you want. Operator will wait until the promise resolves before transitioning to the next route. Magic.

Additionally, handlers can return a string that represents a path to redirect to. This path can be returned synchronously, or as the resolved value of a promise. See Client-side Redirects for an example.

Routes configured on the initial instance are executed immediately when the page loads.

const app = operator({
  routes: {
    '/products/:id': ({ id }) => {
      return new Promise((resolve, reject) => {
        api.getProductById(id).then(product => {
          resolve(product)
        })
      })
    },
    '*': () => {
      /**
       * Could perform custom transitions
       * on each route
       */
      return true
    }
  }
})

evaluateScripts (experimental) - boolean

If true, operator will parse each new route and attempt to re-mount scripts to the page. It does this by recreating each script tag and appending it to the DOM.

API

on(event, callback)

Listen for emitted events from the instance. These can be useful to transitions, destroying other library instances, or initiating new instances.

app.on('beforeRender', (newRoute) => {})
app.on('afterRender', () => {})

go(route)

Navigate to a route.

app.go('/products')

push(route[, title])

Push a new path and title to history without loading any data. Useful for filtering, modals, etc.

app.push('/products?sort=price', 'Filtered by Price')

prefetch(route)

Cache a request for an arbitrary route. The method also returns a Promise that resolves with the requested page.

app.prefetch('/about').then(markup => {
  // do something with page markup
})

addRoute(route, handler)

Adds a route and handler. Routes added with this method are not executed on initial startup.

app.addRoute('/products/:id', ({ id }) => {
  // do something with product id
  return true
})

disable()

Disable operator without destorying the instance.

enable()

Re-enable operator after disabling it.

isEnabled()

Check if operator is enabled. Returns true or false.

destory()

Stop everything. Pretty straighforward.


Advanced Usage

Code splitting

Operator doesn't do anything specifically to aid your in code splitting, but the async route handlers mean you can load the scripts for a new route before it's rendered, which keeps things buttery smooth.

With webpack, it looks like this:

app.addRoute('/products/*', () => {
  return import('flickity').then(flickity => {
    window.Flickity = flickity
  })
})

Client-side redirects

To create simple client side redirects, just return the path you wish to redirect to from your route handler.

const app = operator({
  routes: {
    '/products/:id': ({ id }) => {
      if (id === 'some-product') {
        return '/products/all'
      } else {
        return true
      }
    },
    '/about': () => {
      return fetchAboutDataFromAPI().then(data => {
        if (data.hasRedirect) {
          return '/'
        } else {
          return true
        }
      })
    }
  }
})

Dependencies

Related Projects

Sites Using Operator

MIT License