uri-router
v3.0.5
Published
A small framework for building URI driven DOM applications
Downloads
27
Maintainers
Readme
uri-router
A small framework for building URI driven DOM applications.
Example
index.html
<!doctype html>
<html>
<body>
<nav>
<a href="/">home</a> |
<a href="/about">about</a> |
<a href="/contact">contact</a>
</nav>
<div id="pages"></div>
</body>
<script type="text/javascript" src="/app.js"></script>
</html>
app.js
var router = require('uri-router')
var nav = require('./nav')
var home = require('./home')
var about = require('./about')
var contact = require('./contact')
router({
routes: [
['.*', nav]
]
})
router({
watch: 'pathname',
outlet: document.querySelector('#pages'),
routes: [
['/', home],
['/about', about],
['/contact', contact]
]
})
nav.js (a view that's already on the DOM)
module.exports = document.querySelector('nav')
var qsa = require('qsa-es5')
module.exports.show = function (uri) {
qsa('a', this).forEach(function (a) {
var active = a.getAttribute('href') === uri.pathname
a.style.textDecoration = active ? 'underline' : 'none'
})
}
home.js (a plain DOM element as a view)
module.exports = function () {
var el = document.createElement('H1')
el.textContent = 'Home'
return el
}
about.js (a web component as a view)
var About = {
prototype: Object.create(window.HTMLElement.prototype)
}
About.prototype.createdCallback = function () {
var shadow = this.createShadowRoot()
shadow.innerHTML = '<h1>About</h1>'
}
module.exports = document.registerElement('about-component', About)
contact.js (a view that uses lifecycle hooks to transition in and out)
module.exports = function () {
var el = document.createElement('div')
el.innerHTML = '<h1>Contact</h1>'
el.show = show
el.hide = hide
el.style.transition = 'opacity 0.5s'
return el
}
function show () {
window.getComputedStyle(this).opacity
this.style.opacity = '1'
}
function hide (uri, cb) {
this.style.opacity = '0'
this.addEventListener('transitionend', cb)
}
The code above is pretty basic, check out the example app for fancier things:
$ npm run example
Test
$ npm run test-local
$ # to run the tests at sauce, open a sauce-connect tunnel and do:
$ SAUCE_USERNAME=x SAUCE_ACCESS_KEY=y npm run test
Require
var Router = require('uri-router')
Returns a function for creating routers. The first time uri-router
is required, it will globally hijack all link clicks and form submissions targeting the origin and start listening for the popstate
event.
Static methods
It's critical you do not use window.history.{pushState,replaceState,go,back}()
directly! Use the static methods listed here instead.
Router.push(location, [replace])
Update window.location
.
location
Stringreplace
Boolean; indicates to use replaceState instead of pushState
Router.replace(location)
Shortcut for Router.push(location, true)
.
Router.pop()
Like window.history.back()
put queued properly.
Router.search(query, [replace])
Update window.location.search
without clobbering the existing query.
example: assuming the search string is set to
?a=1
, callingRouter.search({ b: 2 })
would change it to?a=1&b=2
.
Instance methods
var r = Router(opts)
The constructor. opts
is augmented, tracked and returned as r
. Beware, r
is NOT actually an instance of Router
! I am open to changing this if there is a good reason.
r.destroy()
Hide any active views and stop the instance from updating on {push,replace,pop}state
.
Instance properties
r.watch
Should be set to the name of a property on window.location
, generally "pathname" or "hash"
r.routes
An array of regex / handler pairs like: ['regex', handler]
. The handler can be an instance of HTMLElement, a newable constructor that inherits from HTMLElement, or a function with signature (uri, next)
. Handlers that are plain functions should either call next
to be treated as middleware (falling through to succeeding routes) or return an instance of HTMLElement, but not both.
views generated by route handlers can optionally define
show()
andhide()
methods, see lifecycle hooks for more details.
r.outlet
An optional DOM element. If an outlet is specified, location changes will trigger the removal of any existing elements, and the appending of any elements generated by the matched handler. If the same handler is matched more than once in a row, and handler.reusable === true
, the existing view will simply get a show()
hook rather than being removed and created again from scratch.
r.base
An optional prefix to ignore for r.watch
. Useful for building abstract views with nested routers.
Lifecycle hooks
Any time window.location
changes, all active views should expect to receive one or more of the following (optional) hooks:
view.show(uri)
Called on all active views when window.location
changes. See URI Properties for properties available on uri
.
view.hide(uri, cb)
Called after a view becomes inactive, but just before it is removed from the DOM. If the hide implementation accepts a callback, (and the router specifies an outlet
) the router will defer removing the view from the DOM until the callback is executed.
URI properties
URI
objects are passed to route handlers and lifecycle hooks. They define most of the properties described in the URL spec and some Router
specific properties described here:
init
True when window.location
has not changed since the page loaded.
back
True when the browser's back button has been clicked or Router.pop()
was called.
replace
True when Router.replace
initiated the location change.
watch
Alias for the dispatching router's watch
property.
base
Alias for the dispatching router's base
property.
top
If there are any capture groups in the route regex, this will be set to the value of the first group. You can use this to set r.base
on nested routers.
params
An array of the capture group values from the route regex, excepting the first group, which is considered the base
- see above.
query
A parsed querystring object.
Releases
- 3.0.1
- Added option
Router.replaceOnClick
to replace instead of push by default when handling link clicks
- Added option
- 3.x
- Changed
uri.base
semantics and added a correspondinguri.top
property
- Changed
- 2.x
- Changed
uri.init
semantics - Expose the current uri
- Set default watch property to "href"
- Changed
- 1.x
- Complete rewrite, November 2015
- 0.x
- Initial prototype, August 2014
License
Copyright © 2014 Jesse Tane [email protected]
This work is free. You can redistribute it and/or modify it under the terms of the WTFPL.
No Warranty. The Software is provided "as is" without warranty of any kind, either express or implied, including without limitation any implied warranties of condition, uninterrupted use, merchantability, fitness for a particular purpose, or non-infringement.