SkillAgentSearch skills...

Page.js

Micro client-side router inspired by the Express router

Install / Use

/learn @visionmedia/Page.js
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

page router logo

Tiny Express-inspired client-side router.

Build Status Coverage Status Gitter

page('/', index)
page('/user/:user', show)
page('/user/:user/edit', edit)
page('/user/:user/album', album)
page('/user/:user/album/sort', sort)
page('*', notfound)
page()

Installation

There are multiple ways to install page.js. With package managers:

$ npm install page # for browserify
$ component install visionmedia/page.js
$ bower install visionmedia/page.js

Or use with a CDN. We support:

Using with global script tags:

<script src="https://unpkg.com/page/page.js"></script>
<script>
  page('/about', function(){
    // Do stuff
  });
</script>

Or with modules, in modern browsers:

<script type="module">
  import page from "//unpkg.com/page/page.mjs";

  page('/home', () => { ... });
</script>

Running examples

To run examples do the following to install dev dependencies and run the example server:

$ git clone git://github.com/visionmedia/page.js
$ cd page.js
$ npm install
$ node examples
$ open http://localhost:4000

Currently we have examples for:

  • basic minimal application showing basic routing
  • notfound similar to basic with single-page 404 support
  • album showing pagination and external links
  • profile simple user profiles
  • query-string shows how you can integrate plugins using the router
  • state illustrates how the history state may be used to cache data
  • server illustrates how to use the dispatch option to server initial content
  • chrome Google Chrome style administration interface
  • transitions Shows off a simple technique for adding transitions between "pages"
  • partials using hogan.js to render mustache partials client side

NOTE: keep in mind these examples do not use jQuery or similar, so portions of the examples may be relatively verbose, though they're not directly related to page.js in any way.

API

page(path, callback[, callback ...])

Defines a route mapping path to the given callback(s). Each callback is invoked with two arguments, context and next. Much like Express invoking next will call the next registered callback with the given path.

page('/', user.list)
page('/user/:id', user.load, user.show)
page('/user/:id/edit', user.load, user.edit)
page('*', notfound)

Under certain conditions, links will be disregarded and will not be dispatched, such as:

  • Links that are not of the same origin
  • Links with the download attribute
  • Links with the target attribute
  • Links with the rel="external" attribute

page(callback)

This is equivalent to page('*', callback) for generic "middleware".

page(path)

Navigate to the given path.

$('.view').click(function(e){
  page('/user/12')
  e.preventDefault()
})

page(fromPath, toPath)

Setup redirect from one path to another.

page.redirect(fromPath, toPath)

Identical to page(fromPath, toPath)

page.redirect(path)

Calling page.redirect with only a string as the first parameter redirects to another route. Waits for the current route to push state and after replaces it with the new one leaving the browser history clean.

page('/default', function(){
  // some logic to decide which route to redirect to
  if(admin) {
    page.redirect('/admin');
  } else {
    page.redirect('/guest');
  }
});

page('/default');

page.show(path)

Identical to page(path) above.

page([options])

Register page's popstate / click bindings. If you're doing selective binding you'll like want to pass { click: false } to specify this yourself. The following options are available:

  • click bind to click events [true]
  • popstate bind to popstate [true]
  • dispatch perform initial dispatch [true]
  • hashbang add #! before urls [false]
  • decodeURLComponents remove URL encoding from path components (query string, pathname, hash) [true]
  • window provide a window to control (by default it will control the main window)

If you wish to load serve initial content from the server you likely will want to set dispatch to false.

page.start([options])

Identical to page([options]) above.

page.stop()

Unbind both the popstate and click handlers.

page.base([path])

Get or set the base path. For example if page.js is operating within /blog/* set the base path to "/blog".

page.strict([enable])

Get or set the strict path matching mode to enable. If enabled /blog will not match "/blog/" and /blog/ will not match "/blog".

page.exit(path, callback[, callback ...])

Defines an exit route mapping path to the given callback(s).

Exit routes are called when a page changes, using the context from the previous change. For example:

page('/sidebar', function(ctx, next) {
  sidebar.open = true
  next()
})

page.exit('/sidebar', function(ctx, next) {
  sidebar.open = false
  next()
})

page.exit(callback)

Equivalent to page.exit('*', callback).

page.create([options])

Create a new page instance with the given options. Options provided are the same as provided in page([options]) above. Use this if you need to control multiple windows (like iframes or popups) in addition to the main window.

var otherPage = page.create({ window: iframe.contentWindow });
otherPage('/', main);

page.clickHandler

This is the click handler used by page to handle routing when a user clicks an anchor like <a href="/user/profile">. This is exported for those who want to disable the click handling behavior with page.start({ click: false }), but still might want to dispatch based on the click handler's logic in some scenarios.

Context

Routes are passed Context objects, these may be used to share state, for example ctx.user =, as well as the history "state" ctx.state that the pushState API provides.

Context#save()

Saves the context using replaceState(). For example this is useful for caching HTML or other resources that were loaded for when a user presses "back".

Context#handled

If true, marks the context as handled to prevent default 404 behaviour. For example this is useful for the routes with interminate quantity of the callbacks.

Context#canonicalPath

Pathname including the "base" (if any) and query string "/admin/login?foo=bar".

Context#path

Pathname and query string "/login?foo=bar".

Context#querystring

Query string void of leading ? such as "foo=bar", defaults to "".

Context#pathname

The pathname void of query string "/login".

Context#state

The pushState state object.

Context#title

The pushState title.

Routing

The router uses the same string-to-regexp conversion that Express does, so things like ":id", ":id?", and "*" work as you might expect.

Another aspect that is much like Express is the ability to pass multiple callbacks. You can use this to your advantage to flatten nested callbacks, or simply to abstract components.

Separating concerns

For example suppose you have a route to edit users, and a route to view users. In both cases you need to load the user. One way to achieve this is with several callbacks as shown here:

page('/user/:user', load, show)
page('/user/:user/edit', load, edit)

Using the * character we can alter this to match all routes prefixed with "/user" to achieve the same result:

page('/user/*', load)
page('/user/:user', show)
page('/user/:user/edit', edit)

Likewise * can be used as catch-alls after all routes acting as a 404 handler, before all routes, in-between and so on. For example:

page('/user/:user', load, show)
page('*', function(){
  $('body').text('Not found!')
})

Default 404 behaviour

By default when a route is not matched, page.js invokes page.stop() to unbind itself, and proceed with redirecting to the location requested. This means you may use page.js with a multi-page application without explicitly binding to certain links.

Working with parameters and contexts

Much like request and response objects are passed around in Express, page.js has a single "Context" object. Using the previous examples of load and show for a user, we can assign arbitrary properties to ctx to maintain state between callbacks.

To build a load function that will load the user for subsequent routes you'll need to access the ":id" passed. You can do this with ctx.params.NAME much like Express:

function load(ctx, next){
  var id = ctx.params.id
}

Then perform some kind of action against the server, assigning the user to ctx.user for other routes to utilize. next() is then invoked to pass control to the following matching route in sequence, if any.

function load(ctx, next){
  var id = ctx.params.id
  $.getJSON('/user/' + id + '.json', function(user){
    ctx.user = user
    next()
  })
}

The "show" function might look something like this, however you may render templates or do anything you want. Note that here next() is not invoked, because

Related Skills

View on GitHub
GitHub Stars7.7k
CategoryDevelopment
Updated3d ago
Forks687

Languages

JavaScript

Security Score

80/100

Audited on Mar 24, 2026

No findings