npm install app-decorators --save
System.config({
map : {
"app-decorators": "node_modules/app-decorators/src/index",
}
});
- add path, search or hash routes separately
- caches matched routes
- no unnecessary handler calls
- event driven
- useful public methods
- no vendor libraries
- written in ES6
- test driven
- performance written
import { Router } from 'app-decorators';
let router = Router.create();
// add path route
router.on('Home /', () => {
console.log('home');
});
router.on('Results /products/{{category}}.html', (matched, search, hash) => {
console.log(matched.params.category);
});
router.on('Product /products/{{category}}/{{id}}.html', (matched, search, hash) => {
console.log(matched.params.category);
console.log(matched.params.id);
});
// add search route
router.on('ShowArea ?show={{type}}', (matched, search, hash) => {
console.log(matched.params.type);
});
// add hash route
router.on('MarkLines #markfrom={{from}}&to={{to}}', (matched, search, hash) => {
// e.g. on click of .show-hightlight (see index.html)
console.log(matched.params); // log: { markfrom: 5, to: 10 }
console.log(search); // log: { show: 'video', a: 'b', c: 'd' }
console.log(hash); // log: { markfrom: 5, to: 10 jumpTo: 'foo' }
});
// start route
router.start();
<a class="home" href="/"> Home </a>
<a class=".results" href="/products/samsung/s4"> Samsung Galaxy S4 </a>
<a class="show-video" href="/products/samsung/s4?show=video"> Show Video </a>
<a class="show-hightlight"href="/products/samsung/s4?show=video&a=b&c=d#markfrom=5&to=10&jumpTo=foo"> Show Highlight </a>
/**
* register all routes at once
*/
let router = Router.create({
routes: {
'Home /': () => {},
'Results /products/{{category}}.html': () => {},
'Product /products/{{category}}/{{id}}.html': () => {},
},
});
/**
* bind property object to handler
*/
class Foo() {
fooMethod(name){
console.log(`Hello ${name}`) // log: hello foo
}
}
let foo = new Foo();
let router = Router.create({
routes: {
'Home /': () => {},
'Results /products/{{category}}.html': () => {
// with the bind property (see below)
// you have direct access to Foo instance
this.fooMethod('foo');
}
},
bind: foo // <=
});
/**
* scope your routes
*/
let navigation = document.querySelector('navigation');
let router = Router.create({
routes: {
'Home /': () => {},
'Results /products/{{category}}.html': () => {}
},
// Info: scope must be an instanceof HTMLElement
// Now your routes will be only perform in <navigation>.
scope: navigation
});
/**
* shadow your routes like shadowDom with shadowRoute
*/
// example coming soon
/**
* on method (register your routes)
*/
let router = Router.create();
router.on('myRoute1 /my/path/{{name}}', () => {});
// if you not pass a handler, the
// router will be return a promise
let promise = router.on('myRoute2 ?name={{name}}');
promise
.then((matched) => {
return matched.params.name;
})
.then((value) => {
console.log(value) // log: baz
});
/**
* Alternate to on method
* addRouteListener method (register your routes)
*/
let router = Router.create();
router.addRouteListener('myRoute1', '/my/path/{{name}}', () => {});
router.addRouteListener('myRoute2', '?name=foo', () => {});
/**
* trigger method (manuel triggering )
*/
let router = Router.create();
router.on('myRoute1 /my/path/{{name}}', () => {});
router.on('myRoute2 ?name=foo', (matched, search, hash) => {
console.log(matched.params.hello) // log: 'world'
});
// trigger
router.trigger('myRoute2');
// trigger with args
router.trigger('myRoute2', { hello: 'world' });
/**
* firing event natively
*/
let router = Router.create({
scope: document.body
});
// register routes
router.on('route1 /', () => {});
router.on('route2 /some/{{name}}.html', (matched, search, hash) => {
console.log(matched.params.name); // log: path
});
// create CustomEvent
let event = new CustomEvent('route2', {
detail: {
name: 'path'
}
});
// trigger event
document.body.dispatchEvent(event);
/**
* match method (manuel matching, without over clicking a-tag )
*/
let router = Router.create();
router.on('myRoute1 /my/path/{{name}}', (matched, search, hash) => {
console.log(matched.params) // log: { name: 'awesome' }
console.log(search) // log: { a:1, b:2 }
console.log(hash) // log: { c:3, d:4 }
});
// will match
router.match('/my/path/awesome?a=1&b=2#c=3&d=4');
// will match and cache (see optional "true" paramter)
router.match('/my/path/link', true);
// will not match (is not registered)
router.match('/your/path/awesome');
/**
* whoami method (return who is/are passed in fragment)
*/
let router = Router.create();
router.on('myRoute1 /my/path/{{name}}', () => {});
router.on('myRoute2 ?hello=world', () => {});
router.on('myRoute3 #hash=tag', () => {});
// will match
let matched = router.whoami('/my/path/awesome#hash=tag');
// will log:
console.log(matched);
[{
'/my/path/{{name}}': {
name: 'myRoute1',
type: 'dynamic',
route: '/my/path/{{name}}',
urlpart: 'pathname',
regex: '^\\/this\\/path\\/(?<name>[\\d\\w?()|{}_.,-]+)$',
params: {
name: 'awesome'
},
fragment: '/my/path/awesome',
cache: false,
},
},
{
'#hash=tag': {
name: 'myRoute3',
type: 'static',
route: '#hash=tag',
urlpart: 'hash',
regex: '#hash=tag',
params: {},
fragment: '#hash=tag',
cache: false,
},
}]
/**
* which method (return who is passed routename)
*/
let router = Router.create();
router.on('myRoute1 /my/path/{{name}}', () => {});
router.on('myRoute2 ?hello=world', () => {});
router.on('myRoute3 #hash=tag', () => {});
// will match
let which = router.which('myRoute1');
// will log:
console.log(which);
{
'/my/path/{{name}}': {
name: 'myRoute1',
type: 'dynamic',
route: '/my/path/{{name}}',
urlpart: 'pathname',
regex: '^\\/this\\/path\\/(?<name>[\\d\\w?()|{}_.,-]+)$',
params: null,
fragment: null,
cache: false,
}
}
/**
* constructURL method (will build an url)
*/
let router = Router.create();
router.on('myRoute1 /some/static/path.html', () => {});
router.on('myRoute2 /{{static}}/path/{{id}}.html', () => {});
// build url for myRoute1
let url1 = router.constructURL('myRoute1');
console.log(url1) // log: /some/static/path.html
// build url for myRoute2
let url2 = router.constructURL('myRoute2', { static: 'foo', id:44 });
console.log(url1) // log: /foo/path/44.html
/**
* go method (build url and redirect to)
*/
let router = Router.create();
router.on('myRoute1 /some/static/path.html', () => {});
router.on('myRoute2 /{{static}}/path/{{id}}.html', (matched, search, hash) => {
console.log(matched.params) // log: { static: 'foo', id:44 }
});
router.go('myRoute2', { static: 'foo', id:44 });
/**
* start/stop method (will start the router)
*/
let router = Router.create();
router.on('myRoute1 /some/static/path.html', () => {});
router.on('myRoute2 /{{static}}/path/{{id}}.html', () => {});
router.start(); // will start the router
router.stop(); // will stop the router
/**
* off method (remove your routes)
*/
let router = Router.create();
router.on('myRoute1 /my/path/1', () => {});
router.on('myRoute2 /my/path/2', () => {});
router.on('myRoute3 /my/path/3', () => {});
// will remove myRoute1
router.off('myRoute1');
// will remove all routes (not implemented yet)
router.off();
/**
* destroy method (will kill your router instance)
*/
let router = Router.create();
router.on('myRoute1 /my/path/1', () => {});
router.on('myRoute2 /my/path/2', () => {});
router.on('myRoute3 /my/path/3', () => {});
router.destroy();
let router = Router.create();
// This is not possible, it throw an Error.
// You can pass pathname (/a/b.html), search (?c=d&e=f) or hash(#g=h&i=j)
// separately like above
router.on('AllInOne /a/b?c=d&e=f#g=h&i=j', () => {});
make install
make compile
make test
(c) 2015 - 2016 Serkan Sipahi App-Decorators may be freely distributed under the MIT license.