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

uri-router

v3.0.5

Published

A small framework for building URI driven DOM applications

Downloads

27

Readme

uri-router npm tests

A small framework for building URI driven DOM applications.

saucelabs

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 String
  • replace 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, calling Router.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() and hide() 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
  • 3.x
    • Changed uri.base semantics and added a corresponding uri.top property
  • 2.x
    • Changed uri.init semantics
    • Expose the current uri
    • Set default watch property to "href"
  • 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.