riot-route
Advanced tools
Comparing version 2.5.0 to 3.0.0
@@ -1,4 +0,129 @@ | ||
;define(function(require, exports, module) { | ||
'use strict' | ||
define(function () { 'use strict'; | ||
var observable = function(el) { | ||
/** | ||
* Extend the original object or create a new empty one | ||
* @type { Object } | ||
*/ | ||
el = el || {}; | ||
/** | ||
* Private variables | ||
*/ | ||
var callbacks = {}, | ||
slice = Array.prototype.slice; | ||
/** | ||
* Public Api | ||
*/ | ||
// extend the el object adding the observable methods | ||
Object.defineProperties(el, { | ||
/** | ||
* Listen to the given `event` ands | ||
* execute the `callback` each time an event is triggered. | ||
* @param { String } event - event id | ||
* @param { Function } fn - callback function | ||
* @returns { Object } el | ||
*/ | ||
on: { | ||
value: function(event, fn) { | ||
if (typeof fn == 'function') | ||
{ (callbacks[event] = callbacks[event] || []).push(fn); } | ||
return el | ||
}, | ||
enumerable: false, | ||
writable: false, | ||
configurable: false | ||
}, | ||
/** | ||
* Removes the given `event` listeners | ||
* @param { String } event - event id | ||
* @param { Function } fn - callback function | ||
* @returns { Object } el | ||
*/ | ||
off: { | ||
value: function(event, fn) { | ||
if (event == '*' && !fn) { callbacks = {}; } | ||
else { | ||
if (fn) { | ||
var arr = callbacks[event]; | ||
for (var i = 0, cb; cb = arr && arr[i]; ++i) { | ||
if (cb == fn) { arr.splice(i--, 1); } | ||
} | ||
} else { delete callbacks[event]; } | ||
} | ||
return el | ||
}, | ||
enumerable: false, | ||
writable: false, | ||
configurable: false | ||
}, | ||
/** | ||
* Listen to the given `event` and | ||
* execute the `callback` at most once | ||
* @param { String } event - event id | ||
* @param { Function } fn - callback function | ||
* @returns { Object } el | ||
*/ | ||
one: { | ||
value: function(event, fn) { | ||
function on() { | ||
el.off(event, on); | ||
fn.apply(el, arguments); | ||
} | ||
return el.on(event, on) | ||
}, | ||
enumerable: false, | ||
writable: false, | ||
configurable: false | ||
}, | ||
/** | ||
* Execute all callback functions that listen to | ||
* the given `event` | ||
* @param { String } event - event id | ||
* @returns { Object } el | ||
*/ | ||
trigger: { | ||
value: function(event) { | ||
var arguments$1 = arguments; | ||
// getting the arguments | ||
var arglen = arguments.length - 1, | ||
args = new Array(arglen), | ||
fns, | ||
fn, | ||
i; | ||
for (i = 0; i < arglen; i++) { | ||
args[i] = arguments$1[i + 1]; // skip first argument | ||
} | ||
fns = slice.call(callbacks[event] || [], 0); | ||
for (i = 0; fn = fns[i]; ++i) { | ||
fn.apply(el, args); | ||
} | ||
if (callbacks['*'] && event != '*') | ||
{ el.trigger.apply(el, ['*', event].concat(args)); } | ||
return el | ||
}, | ||
enumerable: false, | ||
writable: false, | ||
configurable: false | ||
} | ||
}); | ||
return el | ||
}; | ||
/** | ||
@@ -9,25 +134,29 @@ * Simple client-side router | ||
var observable = require('riot-observable') | ||
var RE_ORIGIN = /^.+?\/\/+[^\/]+/; | ||
var EVENT_LISTENER = 'EventListener'; | ||
var REMOVE_EVENT_LISTENER = 'remove' + EVENT_LISTENER; | ||
var ADD_EVENT_LISTENER = 'add' + EVENT_LISTENER; | ||
var HAS_ATTRIBUTE = 'hasAttribute'; | ||
var REPLACE = 'replace'; | ||
var POPSTATE = 'popstate'; | ||
var HASHCHANGE = 'hashchange'; | ||
var TRIGGER = 'trigger'; | ||
var MAX_EMIT_STACK_LEVEL = 3; | ||
var win = typeof window != 'undefined' && window; | ||
var doc = typeof document != 'undefined' && document; | ||
var hist = win && history; | ||
var loc = win && (hist.location || win.location); | ||
var prot = Router.prototype; | ||
var clickEvent = doc && doc.ontouchstart ? 'touchstart' : 'click'; | ||
var central = observable(); | ||
var RE_ORIGIN = /^.+?\/\/+[^\/]+/, | ||
EVENT_LISTENER = 'EventListener', | ||
REMOVE_EVENT_LISTENER = 'remove' + EVENT_LISTENER, | ||
ADD_EVENT_LISTENER = 'add' + EVENT_LISTENER, | ||
HAS_ATTRIBUTE = 'hasAttribute', | ||
REPLACE = 'replace', | ||
POPSTATE = 'popstate', | ||
HASHCHANGE = 'hashchange', | ||
TRIGGER = 'trigger', | ||
MAX_EMIT_STACK_LEVEL = 3, | ||
win = typeof window != 'undefined' && window, | ||
doc = typeof document != 'undefined' && document, | ||
hist = win && history, | ||
loc = win && (hist.location || win.location), // see html5-history-api | ||
prot = Router.prototype, // to minify more | ||
clickEvent = doc && doc.ontouchstart ? 'touchstart' : 'click', | ||
started = false, | ||
central = observable(), | ||
routeFound = false, | ||
debouncedEmit, | ||
base, current, parser, secondParser, emitStack = [], emitStackLevel = 0 | ||
var started = false; | ||
var routeFound = false; | ||
var debouncedEmit; | ||
var base; | ||
var current; | ||
var parser; | ||
var secondParser; | ||
var emitStack = []; | ||
var emitStackLevel = 0; | ||
@@ -51,5 +180,5 @@ /** | ||
var re = new RegExp('^' + filter[REPLACE](/\*/g, '([^/?#]+?)')[REPLACE](/\.\./, '.*') + '$'), | ||
args = path.match(re) | ||
args = path.match(re); | ||
if (args) return args.slice(1) | ||
if (args) { return args.slice(1) } | ||
} | ||
@@ -64,6 +193,6 @@ | ||
function debounce(fn, delay) { | ||
var t | ||
var t; | ||
return function () { | ||
clearTimeout(t) | ||
t = setTimeout(fn, delay) | ||
clearTimeout(t); | ||
t = setTimeout(fn, delay); | ||
} | ||
@@ -77,7 +206,7 @@ } | ||
function start(autoExec) { | ||
debouncedEmit = debounce(emit, 1) | ||
win[ADD_EVENT_LISTENER](POPSTATE, debouncedEmit) | ||
win[ADD_EVENT_LISTENER](HASHCHANGE, debouncedEmit) | ||
doc[ADD_EVENT_LISTENER](clickEvent, click) | ||
if (autoExec) emit(true) | ||
debouncedEmit = debounce(emit, 1); | ||
win[ADD_EVENT_LISTENER](POPSTATE, debouncedEmit); | ||
win[ADD_EVENT_LISTENER](HASHCHANGE, debouncedEmit); | ||
doc[ADD_EVENT_LISTENER](clickEvent, click); | ||
if (autoExec) { emit(true); } | ||
} | ||
@@ -89,6 +218,6 @@ | ||
function Router() { | ||
this.$ = [] | ||
observable(this) // make it observable | ||
central.on('stop', this.s.bind(this)) | ||
central.on('emit', this.e.bind(this)) | ||
this.$ = []; | ||
observable(this); // make it observable | ||
central.on('stop', this.s.bind(this)); | ||
central.on('emit', this.e.bind(this)); | ||
} | ||
@@ -119,3 +248,3 @@ | ||
function getPathFromBase(href) { | ||
return base[0] == '#' | ||
return base[0] === '#' | ||
? (href || loc.href || '').split(base)[1] || '' | ||
@@ -127,16 +256,17 @@ : (loc ? getPathFromRoot(href) : href || '')[REPLACE](base, '') | ||
// the stack is needed for redirections | ||
var isRoot = emitStackLevel == 0, first | ||
if (MAX_EMIT_STACK_LEVEL <= emitStackLevel) return | ||
var isRoot = emitStackLevel === 0; | ||
if (MAX_EMIT_STACK_LEVEL <= emitStackLevel) { return } | ||
emitStackLevel++ | ||
emitStackLevel++; | ||
emitStack.push(function() { | ||
var path = getPathFromBase() | ||
if (force || path != current) { | ||
central[TRIGGER]('emit', path) | ||
current = path | ||
var path = getPathFromBase(); | ||
if (force || path !== current) { | ||
central[TRIGGER]('emit', path); | ||
current = path; | ||
} | ||
}) | ||
}); | ||
if (isRoot) { | ||
while (first = emitStack.shift()) first() // stack increses within this call | ||
emitStackLevel = 0 | ||
var first; | ||
while (first = emitStack.shift()) { first(); } // stack increses within this call | ||
emitStackLevel = 0; | ||
} | ||
@@ -147,27 +277,27 @@ } | ||
if ( | ||
e.which != 1 // not left click | ||
e.which !== 1 // not left click | ||
|| e.metaKey || e.ctrlKey || e.shiftKey // or meta keys | ||
|| e.defaultPrevented // or default prevented | ||
) return | ||
) { return } | ||
var el = e.target | ||
while (el && el.nodeName != 'A') el = el.parentNode | ||
var el = e.target; | ||
while (el && el.nodeName !== 'A') { el = el.parentNode; } | ||
if ( | ||
!el || el.nodeName != 'A' // not A tag | ||
!el || el.nodeName !== 'A' // not A tag | ||
|| el[HAS_ATTRIBUTE]('download') // has download attr | ||
|| !el[HAS_ATTRIBUTE]('href') // has no href attr | ||
|| el.target && el.target != '_self' // another window or frame | ||
|| el.href.indexOf(loc.href.match(RE_ORIGIN)[0]) == -1 // cross origin | ||
) return | ||
|| el.target && el.target !== '_self' // another window or frame | ||
|| el.href.indexOf(loc.href.match(RE_ORIGIN)[0]) === -1 // cross origin | ||
) { return } | ||
if (el.href != loc.href | ||
if (el.href !== loc.href | ||
&& ( | ||
el.href.split('#')[0] == loc.href.split('#')[0] // internal jump | ||
|| base[0] != '#' && getPathFromRoot(el.href).indexOf(base) !== 0 // outside of base | ||
|| base[0] == '#' && el.href.split(base)[0] != loc.href.split(base)[0] // outside of #base | ||
el.href.split('#')[0] === loc.href.split('#')[0] // internal jump | ||
|| base[0] !== '#' && getPathFromRoot(el.href).indexOf(base) !== 0 // outside of base | ||
|| base[0] === '#' && el.href.split(base)[0] !== loc.href.split(base)[0] // outside of #base | ||
|| !go(getPathFromBase(el.href), el.title || doc.title) // route not found | ||
)) return | ||
)) { return } | ||
e.preventDefault() | ||
e.preventDefault(); | ||
} | ||
@@ -184,14 +314,14 @@ | ||
// Server-side usage: directly execute handlers for the path | ||
if (!hist) return central[TRIGGER]('emit', getPathFromBase(path)) | ||
if (!hist) { return central[TRIGGER]('emit', getPathFromBase(path)) } | ||
path = base + normalize(path) | ||
title = title || doc.title | ||
path = base + normalize(path); | ||
title = title || doc.title; | ||
// browsers ignores the second parameter `title` | ||
shouldReplace | ||
? hist.replaceState(null, title, path) | ||
: hist.pushState(null, title, path) | ||
: hist.pushState(null, title, path); | ||
// so we need to set it manually | ||
doc.title = title | ||
routeFound = false | ||
emit() | ||
doc.title = title; | ||
routeFound = false; | ||
emit(); | ||
return routeFound | ||
@@ -212,6 +342,6 @@ } | ||
prot.m = function(first, second, third) { | ||
if (isString(first) && (!second || isString(second))) go(first, second, third || false) | ||
else if (second) this.r(first, second) | ||
else this.r('@', first) | ||
} | ||
if (isString(first) && (!second || isString(second))) { go(first, second, third || false); } | ||
else if (second) { this.r(first, second); } | ||
else { this.r('@', first); } | ||
}; | ||
@@ -222,5 +352,5 @@ /** | ||
prot.s = function() { | ||
this.off('*') | ||
this.$ = [] | ||
} | ||
this.off('*'); | ||
this.$ = []; | ||
}; | ||
@@ -233,9 +363,9 @@ /** | ||
this.$.concat('@').some(function(filter) { | ||
var args = (filter == '@' ? parser : secondParser)(normalize(path), normalize(filter)) | ||
var args = (filter === '@' ? parser : secondParser)(normalize(path), normalize(filter)); | ||
if (typeof args != 'undefined') { | ||
this[TRIGGER].apply(null, [filter].concat(args)) | ||
this[TRIGGER].apply(null, [filter].concat(args)); | ||
return routeFound = true // exit from loop | ||
} | ||
}, this) | ||
} | ||
}, this); | ||
}; | ||
@@ -248,11 +378,11 @@ /** | ||
prot.r = function(filter, action) { | ||
if (filter != '@') { | ||
filter = '/' + normalize(filter) | ||
this.$.push(filter) | ||
if (filter !== '@') { | ||
filter = '/' + normalize(filter); | ||
this.$.push(filter); | ||
} | ||
this.on(filter, action) | ||
} | ||
this.on(filter, action); | ||
}; | ||
var mainRouter = new Router() | ||
var route = mainRouter.m.bind(mainRouter) | ||
var mainRouter = new Router(); | ||
var route = mainRouter.m.bind(mainRouter); | ||
@@ -264,9 +394,9 @@ /** | ||
route.create = function() { | ||
var newSubRouter = new Router() | ||
var newSubRouter = new Router(); | ||
// assign sub-router's main method | ||
var router = newSubRouter.m.bind(newSubRouter) | ||
var router = newSubRouter.m.bind(newSubRouter); | ||
// stop only this sub-router | ||
router.stop = newSubRouter.s.bind(newSubRouter) | ||
router.stop = newSubRouter.s.bind(newSubRouter); | ||
return router | ||
} | ||
}; | ||
@@ -278,10 +408,10 @@ /** | ||
route.base = function(arg) { | ||
base = arg || '#' | ||
current = getPathFromBase() // recalculate current path | ||
} | ||
base = arg || '#'; | ||
current = getPathFromBase(); // recalculate current path | ||
}; | ||
/** Exec routing right now **/ | ||
route.exec = function() { | ||
emit(true) | ||
} | ||
emit(true); | ||
}; | ||
@@ -296,8 +426,8 @@ /** | ||
// reset parser for testing... | ||
parser = DEFAULT_PARSER | ||
secondParser = DEFAULT_SECOND_PARSER | ||
parser = DEFAULT_PARSER; | ||
secondParser = DEFAULT_SECOND_PARSER; | ||
} | ||
if (fn) parser = fn | ||
if (fn2) secondParser = fn2 | ||
} | ||
if (fn) { parser = fn; } | ||
if (fn2) { secondParser = fn2; } | ||
}; | ||
@@ -309,7 +439,7 @@ /** | ||
route.query = function() { | ||
var q = {} | ||
var href = loc.href || current | ||
href[REPLACE](/[?&](.+?)=([^&]*)/g, function(_, k, v) { q[k] = v }) | ||
var q = {}; | ||
var href = loc.href || current; | ||
href[REPLACE](/[?&](.+?)=([^&]*)/g, function(_, k, v) { q[k] = v; }); | ||
return q | ||
} | ||
}; | ||
@@ -320,10 +450,10 @@ /** Stop routing **/ | ||
if (win) { | ||
win[REMOVE_EVENT_LISTENER](POPSTATE, debouncedEmit) | ||
win[REMOVE_EVENT_LISTENER](HASHCHANGE, debouncedEmit) | ||
doc[REMOVE_EVENT_LISTENER](clickEvent, click) | ||
win[REMOVE_EVENT_LISTENER](POPSTATE, debouncedEmit); | ||
win[REMOVE_EVENT_LISTENER](HASHCHANGE, debouncedEmit); | ||
doc[REMOVE_EVENT_LISTENER](clickEvent, click); | ||
} | ||
central[TRIGGER]('stop') | ||
started = false | ||
central[TRIGGER]('stop'); | ||
started = false; | ||
} | ||
} | ||
}; | ||
@@ -337,18 +467,19 @@ /** | ||
if (win) { | ||
if (document.readyState == 'complete') start(autoExec) | ||
if (document.readyState === 'complete') { start(autoExec); } | ||
// the timeout is needed to solve | ||
// a weird safari bug https://github.com/riot/route/issues/33 | ||
else win[ADD_EVENT_LISTENER]('load', function() { | ||
setTimeout(function() { start(autoExec) }, 1) | ||
}) | ||
else { win[ADD_EVENT_LISTENER]('load', function() { | ||
setTimeout(function() { start(autoExec); }, 1); | ||
}); } | ||
} | ||
started = true | ||
started = true; | ||
} | ||
} | ||
}; | ||
/** Prepare the router **/ | ||
route.base() | ||
route.parser() | ||
route.base(); | ||
route.parser(); | ||
module.exports = route | ||
return route; | ||
}); |
@@ -1,1 +0,1 @@ | ||
define(function(t,e,n){"use strict";var i=t("riot-observable");var r=/^.+?\/\/+[^\/]+/,f="EventListener",o="remove"+f,u="add"+f,s="hasAttribute",a="replace",c="popstate",h="hashchange",l="trigger",p=3,d=typeof window!="undefined"&&window,m=typeof document!="undefined"&&document,v=d&&history,y=d&&(v.location||d.location),w=P.prototype,b=m&&m.ontouchstart?"touchstart":"click",g=false,$=i(),x=false,A,K,N,S,T,E=[],O=0;function k(t){return t.split(/[\/?#]/)}function q(t,e){var n=new RegExp("^"+e[a](/\*/g,"([^/?#]+?)")[a](/\.\./,".*")+"$"),i=t.match(n);if(i)return i.slice(1)}function D(t,e){var n;return function(){clearTimeout(n);n=setTimeout(t,e)}}function L(t){A=D(B,1);d[u](c,A);d[u](h,A);m[u](b,C);if(t)B(true)}function P(){this.$=[];i(this);$.on("stop",this.s.bind(this));$.on("emit",this.e.bind(this))}function R(t){return t[a](/^\/|\/$/,"")}function _(t){return typeof t=="string"}function j(t){return(t||y.href)[a](r,"")}function z(t){return K[0]=="#"?(t||y.href||"").split(K)[1]||"":(y?j(t):t||"")[a](K,"")}function B(t){var e=O==0,n;if(p<=O)return;O++;E.push(function(){var e=z();if(t||e!=N){$[l]("emit",e);N=e}});if(e){while(n=E.shift())n();O=0}}function C(t){if(t.which!=1||t.metaKey||t.ctrlKey||t.shiftKey||t.defaultPrevented)return;var e=t.target;while(e&&e.nodeName!="A")e=e.parentNode;if(!e||e.nodeName!="A"||e[s]("download")||!e[s]("href")||e.target&&e.target!="_self"||e.href.indexOf(y.href.match(r)[0])==-1)return;if(e.href!=y.href&&(e.href.split("#")[0]==y.href.split("#")[0]||K[0]!="#"&&j(e.href).indexOf(K)!==0||K[0]=="#"&&e.href.split(K)[0]!=y.href.split(K)[0]||!F(z(e.href),e.title||m.title)))return;t.preventDefault()}function F(t,e,n){if(!v)return $[l]("emit",z(t));t=K+R(t);e=e||m.title;n?v.replaceState(null,e,t):v.pushState(null,e,t);m.title=e;x=false;B();return x}w.m=function(t,e,n){if(_(t)&&(!e||_(e)))F(t,e,n||false);else if(e)this.r(t,e);else this.r("@",t)};w.s=function(){this.off("*");this.$=[]};w.e=function(t){this.$.concat("@").some(function(e){var n=(e=="@"?S:T)(R(t),R(e));if(typeof n!="undefined"){this[l].apply(null,[e].concat(n));return x=true}},this)};w.r=function(t,e){if(t!="@"){t="/"+R(t);this.$.push(t)}this.on(t,e)};var G=new P;var H=G.m.bind(G);H.create=function(){var t=new P;var e=t.m.bind(t);e.stop=t.s.bind(t);return e};H.base=function(t){K=t||"#";N=z()};H.exec=function(){B(true)};H.parser=function(t,e){if(!t&&!e){S=k;T=q}if(t)S=t;if(e)T=e};H.query=function(){var t={};var e=y.href||N;e[a](/[?&](.+?)=([^&]*)/g,function(e,n,i){t[n]=i});return t};H.stop=function(){if(g){if(d){d[o](c,A);d[o](h,A);m[o](b,C)}$[l]("stop");g=false}};H.start=function(t){if(!g){if(d){if(document.readyState=="complete")L(t);else d[u]("load",function(){setTimeout(function(){L(t)},1)})}g=true}};H.base();H.parser();n.exports=H}); | ||
define(function(){"use strict";var e=function(e){e=e||{};var t={},r=Array.prototype.slice;Object.defineProperties(e,{on:{value:function(r,n){if(typeof n=="function"){(t[r]=t[r]||[]).push(n)}return e},enumerable:false,writable:false,configurable:false},off:{value:function(r,n){if(r=="*"&&!n){t={}}else{if(n){var i=t[r];for(var f=0,a;a=i&&i[f];++f){if(a==n){i.splice(f--,1)}}}else{delete t[r]}}return e},enumerable:false,writable:false,configurable:false},one:{value:function(t,r){function n(){e.off(t,n);r.apply(e,arguments)}return e.on(t,n)},enumerable:false,writable:false,configurable:false},trigger:{value:function(n){var i=arguments;var f=arguments.length-1,a=new Array(f),u,o,l;for(l=0;l<f;l++){a[l]=i[l+1]}u=r.call(t[n]||[],0);for(l=0;o=u[l];++l){o.apply(e,a)}if(t["*"]&&n!="*"){e.trigger.apply(e,["*",n].concat(a))}return e},enumerable:false,writable:false,configurable:false}});return e};var t=/^.+?\/\/+[^\/]+/;var r="EventListener";var n="remove"+r;var i="add"+r;var f="hasAttribute";var a="replace";var u="popstate";var o="hashchange";var l="trigger";var s=3;var c=typeof window!="undefined"&&window;var v=typeof document!="undefined"&&document;var h=c&&history;var p=c&&(h.location||c.location);var d=j.prototype;var m=v&&v.ontouchstart?"touchstart":"click";var b=e();var g=false;var y=false;var w;var $;var A;var x;var K;var N=[];var O=0;function S(e){return e.split(/[\/?#]/)}function T(e,t){var r=new RegExp("^"+t[a](/\*/g,"([^/?#]+?)")[a](/\.\./,".*")+"$"),n=e.match(r);if(n){return n.slice(1)}}function E(e,t){var r;return function(){clearTimeout(r);r=setTimeout(e,t)}}function P(e){w=E(R,1);c[i](u,w);c[i](o,w);v[i](m,_);if(e){R(true)}}function j(){this.$=[];e(this);b.on("stop",this.s.bind(this));b.on("emit",this.e.bind(this))}function k(e){return e[a](/^\/|\/$/,"")}function q(e){return typeof e=="string"}function D(e){return(e||p.href)[a](t,"")}function L(e){return $[0]==="#"?(e||p.href||"").split($)[1]||"":(p?D(e):e||"")[a]($,"")}function R(e){var t=O===0;if(s<=O){return}O++;N.push(function(){var t=L();if(e||t!==A){b[l]("emit",t);A=t}});if(t){var r;while(r=N.shift()){r()}O=0}}function _(e){if(e.which!==1||e.metaKey||e.ctrlKey||e.shiftKey||e.defaultPrevented){return}var r=e.target;while(r&&r.nodeName!=="A"){r=r.parentNode}if(!r||r.nodeName!=="A"||r[f]("download")||!r[f]("href")||r.target&&r.target!=="_self"||r.href.indexOf(p.href.match(t)[0])===-1){return}if(r.href!==p.href&&(r.href.split("#")[0]===p.href.split("#")[0]||$[0]!=="#"&&D(r.href).indexOf($)!==0||$[0]==="#"&&r.href.split($)[0]!==p.href.split($)[0]||!z(L(r.href),r.title||v.title))){return}e.preventDefault()}function z(e,t,r){if(!h){return b[l]("emit",L(e))}e=$+k(e);t=t||v.title;r?h.replaceState(null,t,e):h.pushState(null,t,e);v.title=t;y=false;R();return y}d.m=function(e,t,r){if(q(e)&&(!t||q(t))){z(e,t,r||false)}else if(t){this.r(e,t)}else{this.r("@",e)}};d.s=function(){this.off("*");this.$=[]};d.e=function(e){this.$.concat("@").some(function(t){var r=(t==="@"?x:K)(k(e),k(t));if(typeof r!="undefined"){this[l].apply(null,[t].concat(r));return y=true}},this)};d.r=function(e,t){if(e!=="@"){e="/"+k(e);this.$.push(e)}this.on(e,t)};var B=new j;var C=B.m.bind(B);C.create=function(){var e=new j;var t=e.m.bind(e);t.stop=e.s.bind(e);return t};C.base=function(e){$=e||"#";A=L()};C.exec=function(){R(true)};C.parser=function(e,t){if(!e&&!t){x=S;K=T}if(e){x=e}if(t){K=t}};C.query=function(){var e={};var t=p.href||A;t[a](/[?&](.+?)=([^&]*)/g,function(t,r,n){e[r]=n});return e};C.stop=function(){if(g){if(c){c[n](u,w);c[n](o,w);v[n](m,_)}b[l]("stop");g=false}};C.start=function(e){if(!g){if(c){if(document.readyState==="complete"){P(e)}else{c[i]("load",function(){setTimeout(function(){P(e)},1)})}}g=true}};C.base();C.parser();return C}); |
@@ -1,4 +0,3 @@ | ||
;(function() { | ||
'use strict' | ||
/* istanbul ignore next */ | ||
var route = (function () { | ||
'use strict'; | ||
@@ -12,3 +11,3 @@ var observable = function(el) { | ||
el = el || {} | ||
el = el || {}; | ||
@@ -19,22 +18,5 @@ /** | ||
var callbacks = {}, | ||
slice = Array.prototype.slice | ||
slice = Array.prototype.slice; | ||
/** | ||
* Private Methods | ||
*/ | ||
/** | ||
* Helper function needed to get and loop all the events in a string | ||
* @param { String } e - event string | ||
* @param {Function} fn - callback | ||
*/ | ||
function onEachEvent(e, fn) { | ||
var es = e.split(' '), l = es.length, i = 0 | ||
for (; i < l; i++) { | ||
var name = es[i] | ||
if (name) fn(name, i) | ||
} | ||
} | ||
/** | ||
* Public Api | ||
@@ -46,5 +28,5 @@ */ | ||
/** | ||
* Listen to the given space separated list of `events` and | ||
* Listen to the given `event` ands | ||
* execute the `callback` each time an event is triggered. | ||
* @param { String } events - events ids | ||
* @param { String } event - event id | ||
* @param { Function } fn - callback function | ||
@@ -54,10 +36,5 @@ * @returns { Object } el | ||
on: { | ||
value: function(events, fn) { | ||
if (typeof fn != 'function') return el | ||
onEachEvent(events, function(name, pos) { | ||
(callbacks[name] = callbacks[name] || []).push(fn) | ||
fn.typed = pos > 0 | ||
}) | ||
value: function(event, fn) { | ||
if (typeof fn == 'function') | ||
{ (callbacks[event] = callbacks[event] || []).push(fn); } | ||
return el | ||
@@ -71,4 +48,4 @@ }, | ||
/** | ||
* Removes the given space separated list of `events` listeners | ||
* @param { String } events - events ids | ||
* Removes the given `event` listeners | ||
* @param { String } event - event id | ||
* @param { Function } fn - callback function | ||
@@ -78,13 +55,11 @@ * @returns { Object } el | ||
off: { | ||
value: function(events, fn) { | ||
if (events == '*' && !fn) callbacks = {} | ||
value: function(event, fn) { | ||
if (event == '*' && !fn) { callbacks = {}; } | ||
else { | ||
onEachEvent(events, function(name, pos) { | ||
if (fn) { | ||
var arr = callbacks[name] | ||
for (var i = 0, cb; cb = arr && arr[i]; ++i) { | ||
if (cb == fn) arr.splice(i--, 1) | ||
} | ||
} else delete callbacks[name] | ||
}) | ||
if (fn) { | ||
var arr = callbacks[event]; | ||
for (var i = 0, cb; cb = arr && arr[i]; ++i) { | ||
if (cb == fn) { arr.splice(i--, 1); } | ||
} | ||
} else { delete callbacks[event]; } | ||
} | ||
@@ -99,5 +74,5 @@ return el | ||
/** | ||
* Listen to the given space separated list of `events` and | ||
* Listen to the given `event` and | ||
* execute the `callback` at most once | ||
* @param { String } events - events ids | ||
* @param { String } event - event id | ||
* @param { Function } fn - callback function | ||
@@ -107,8 +82,8 @@ * @returns { Object } el | ||
one: { | ||
value: function(events, fn) { | ||
value: function(event, fn) { | ||
function on() { | ||
el.off(events, on) | ||
fn.apply(el, arguments) | ||
el.off(event, on); | ||
fn.apply(el, arguments); | ||
} | ||
return el.on(events, on) | ||
return el.on(event, on) | ||
}, | ||
@@ -122,35 +97,31 @@ enumerable: false, | ||
* Execute all callback functions that listen to | ||
* the given space separated list of `events` | ||
* @param { String } events - events ids | ||
* the given `event` | ||
* @param { String } event - event id | ||
* @returns { Object } el | ||
*/ | ||
trigger: { | ||
value: function(events) { | ||
value: function(event) { | ||
var arguments$1 = arguments; | ||
// getting the arguments | ||
var arglen = arguments.length - 1, | ||
args = new Array(arglen), | ||
fns | ||
fns, | ||
fn, | ||
i; | ||
for (var i = 0; i < arglen; i++) { | ||
args[i] = arguments[i + 1] // skip first argument | ||
for (i = 0; i < arglen; i++) { | ||
args[i] = arguments$1[i + 1]; // skip first argument | ||
} | ||
onEachEvent(events, function(name, pos) { | ||
fns = slice.call(callbacks[event] || [], 0); | ||
fns = slice.call(callbacks[name] || [], 0) | ||
for (i = 0; fn = fns[i]; ++i) { | ||
fn.apply(el, args); | ||
} | ||
for (var i = 0, fn; fn = fns[i]; ++i) { | ||
if (fn.busy) continue | ||
fn.busy = 1 | ||
fn.apply(el, fn.typed ? [name].concat(args) : args) | ||
if (fns[i] !== fn) { i-- } | ||
fn.busy = 0 | ||
} | ||
if (callbacks['*'] && event != '*') | ||
{ el.trigger.apply(el, ['*', event].concat(args)); } | ||
if (callbacks['*'] && name != '*') | ||
el.trigger.apply(el, ['*', name].concat(args)) | ||
}) | ||
return el | ||
@@ -162,7 +133,8 @@ }, | ||
} | ||
}) | ||
}); | ||
return el | ||
} | ||
}; | ||
/** | ||
@@ -173,24 +145,29 @@ * Simple client-side router | ||
var RE_ORIGIN = /^.+?\/\/+[^\/]+/; | ||
var EVENT_LISTENER = 'EventListener'; | ||
var REMOVE_EVENT_LISTENER = 'remove' + EVENT_LISTENER; | ||
var ADD_EVENT_LISTENER = 'add' + EVENT_LISTENER; | ||
var HAS_ATTRIBUTE = 'hasAttribute'; | ||
var REPLACE = 'replace'; | ||
var POPSTATE = 'popstate'; | ||
var HASHCHANGE = 'hashchange'; | ||
var TRIGGER = 'trigger'; | ||
var MAX_EMIT_STACK_LEVEL = 3; | ||
var win = typeof window != 'undefined' && window; | ||
var doc = typeof document != 'undefined' && document; | ||
var hist = win && history; | ||
var loc = win && (hist.location || win.location); | ||
var prot = Router.prototype; | ||
var clickEvent = doc && doc.ontouchstart ? 'touchstart' : 'click'; | ||
var central = observable(); | ||
var RE_ORIGIN = /^.+?\/\/+[^\/]+/, | ||
EVENT_LISTENER = 'EventListener', | ||
REMOVE_EVENT_LISTENER = 'remove' + EVENT_LISTENER, | ||
ADD_EVENT_LISTENER = 'add' + EVENT_LISTENER, | ||
HAS_ATTRIBUTE = 'hasAttribute', | ||
REPLACE = 'replace', | ||
POPSTATE = 'popstate', | ||
HASHCHANGE = 'hashchange', | ||
TRIGGER = 'trigger', | ||
MAX_EMIT_STACK_LEVEL = 3, | ||
win = typeof window != 'undefined' && window, | ||
doc = typeof document != 'undefined' && document, | ||
hist = win && history, | ||
loc = win && (hist.location || win.location), // see html5-history-api | ||
prot = Router.prototype, // to minify more | ||
clickEvent = doc && doc.ontouchstart ? 'touchstart' : 'click', | ||
started = false, | ||
central = observable(), | ||
routeFound = false, | ||
debouncedEmit, | ||
base, current, parser, secondParser, emitStack = [], emitStackLevel = 0 | ||
var started = false; | ||
var routeFound = false; | ||
var debouncedEmit; | ||
var base; | ||
var current; | ||
var parser; | ||
var secondParser; | ||
var emitStack = []; | ||
var emitStackLevel = 0; | ||
@@ -214,5 +191,5 @@ /** | ||
var re = new RegExp('^' + filter[REPLACE](/\*/g, '([^/?#]+?)')[REPLACE](/\.\./, '.*') + '$'), | ||
args = path.match(re) | ||
args = path.match(re); | ||
if (args) return args.slice(1) | ||
if (args) { return args.slice(1) } | ||
} | ||
@@ -227,6 +204,6 @@ | ||
function debounce(fn, delay) { | ||
var t | ||
var t; | ||
return function () { | ||
clearTimeout(t) | ||
t = setTimeout(fn, delay) | ||
clearTimeout(t); | ||
t = setTimeout(fn, delay); | ||
} | ||
@@ -240,7 +217,7 @@ } | ||
function start(autoExec) { | ||
debouncedEmit = debounce(emit, 1) | ||
win[ADD_EVENT_LISTENER](POPSTATE, debouncedEmit) | ||
win[ADD_EVENT_LISTENER](HASHCHANGE, debouncedEmit) | ||
doc[ADD_EVENT_LISTENER](clickEvent, click) | ||
if (autoExec) emit(true) | ||
debouncedEmit = debounce(emit, 1); | ||
win[ADD_EVENT_LISTENER](POPSTATE, debouncedEmit); | ||
win[ADD_EVENT_LISTENER](HASHCHANGE, debouncedEmit); | ||
doc[ADD_EVENT_LISTENER](clickEvent, click); | ||
if (autoExec) { emit(true); } | ||
} | ||
@@ -252,6 +229,6 @@ | ||
function Router() { | ||
this.$ = [] | ||
observable(this) // make it observable | ||
central.on('stop', this.s.bind(this)) | ||
central.on('emit', this.e.bind(this)) | ||
this.$ = []; | ||
observable(this); // make it observable | ||
central.on('stop', this.s.bind(this)); | ||
central.on('emit', this.e.bind(this)); | ||
} | ||
@@ -282,3 +259,3 @@ | ||
function getPathFromBase(href) { | ||
return base[0] == '#' | ||
return base[0] === '#' | ||
? (href || loc.href || '').split(base)[1] || '' | ||
@@ -290,16 +267,17 @@ : (loc ? getPathFromRoot(href) : href || '')[REPLACE](base, '') | ||
// the stack is needed for redirections | ||
var isRoot = emitStackLevel == 0, first | ||
if (MAX_EMIT_STACK_LEVEL <= emitStackLevel) return | ||
var isRoot = emitStackLevel === 0; | ||
if (MAX_EMIT_STACK_LEVEL <= emitStackLevel) { return } | ||
emitStackLevel++ | ||
emitStackLevel++; | ||
emitStack.push(function() { | ||
var path = getPathFromBase() | ||
if (force || path != current) { | ||
central[TRIGGER]('emit', path) | ||
current = path | ||
var path = getPathFromBase(); | ||
if (force || path !== current) { | ||
central[TRIGGER]('emit', path); | ||
current = path; | ||
} | ||
}) | ||
}); | ||
if (isRoot) { | ||
while (first = emitStack.shift()) first() // stack increses within this call | ||
emitStackLevel = 0 | ||
var first; | ||
while (first = emitStack.shift()) { first(); } // stack increses within this call | ||
emitStackLevel = 0; | ||
} | ||
@@ -310,27 +288,27 @@ } | ||
if ( | ||
e.which != 1 // not left click | ||
e.which !== 1 // not left click | ||
|| e.metaKey || e.ctrlKey || e.shiftKey // or meta keys | ||
|| e.defaultPrevented // or default prevented | ||
) return | ||
) { return } | ||
var el = e.target | ||
while (el && el.nodeName != 'A') el = el.parentNode | ||
var el = e.target; | ||
while (el && el.nodeName !== 'A') { el = el.parentNode; } | ||
if ( | ||
!el || el.nodeName != 'A' // not A tag | ||
!el || el.nodeName !== 'A' // not A tag | ||
|| el[HAS_ATTRIBUTE]('download') // has download attr | ||
|| !el[HAS_ATTRIBUTE]('href') // has no href attr | ||
|| el.target && el.target != '_self' // another window or frame | ||
|| el.href.indexOf(loc.href.match(RE_ORIGIN)[0]) == -1 // cross origin | ||
) return | ||
|| el.target && el.target !== '_self' // another window or frame | ||
|| el.href.indexOf(loc.href.match(RE_ORIGIN)[0]) === -1 // cross origin | ||
) { return } | ||
if (el.href != loc.href | ||
if (el.href !== loc.href | ||
&& ( | ||
el.href.split('#')[0] == loc.href.split('#')[0] // internal jump | ||
|| base[0] != '#' && getPathFromRoot(el.href).indexOf(base) !== 0 // outside of base | ||
|| base[0] == '#' && el.href.split(base)[0] != loc.href.split(base)[0] // outside of #base | ||
el.href.split('#')[0] === loc.href.split('#')[0] // internal jump | ||
|| base[0] !== '#' && getPathFromRoot(el.href).indexOf(base) !== 0 // outside of base | ||
|| base[0] === '#' && el.href.split(base)[0] !== loc.href.split(base)[0] // outside of #base | ||
|| !go(getPathFromBase(el.href), el.title || doc.title) // route not found | ||
)) return | ||
)) { return } | ||
e.preventDefault() | ||
e.preventDefault(); | ||
} | ||
@@ -347,14 +325,14 @@ | ||
// Server-side usage: directly execute handlers for the path | ||
if (!hist) return central[TRIGGER]('emit', getPathFromBase(path)) | ||
if (!hist) { return central[TRIGGER]('emit', getPathFromBase(path)) } | ||
path = base + normalize(path) | ||
title = title || doc.title | ||
path = base + normalize(path); | ||
title = title || doc.title; | ||
// browsers ignores the second parameter `title` | ||
shouldReplace | ||
? hist.replaceState(null, title, path) | ||
: hist.pushState(null, title, path) | ||
: hist.pushState(null, title, path); | ||
// so we need to set it manually | ||
doc.title = title | ||
routeFound = false | ||
emit() | ||
doc.title = title; | ||
routeFound = false; | ||
emit(); | ||
return routeFound | ||
@@ -375,6 +353,6 @@ } | ||
prot.m = function(first, second, third) { | ||
if (isString(first) && (!second || isString(second))) go(first, second, third || false) | ||
else if (second) this.r(first, second) | ||
else this.r('@', first) | ||
} | ||
if (isString(first) && (!second || isString(second))) { go(first, second, third || false); } | ||
else if (second) { this.r(first, second); } | ||
else { this.r('@', first); } | ||
}; | ||
@@ -385,5 +363,5 @@ /** | ||
prot.s = function() { | ||
this.off('*') | ||
this.$ = [] | ||
} | ||
this.off('*'); | ||
this.$ = []; | ||
}; | ||
@@ -396,9 +374,9 @@ /** | ||
this.$.concat('@').some(function(filter) { | ||
var args = (filter == '@' ? parser : secondParser)(normalize(path), normalize(filter)) | ||
var args = (filter === '@' ? parser : secondParser)(normalize(path), normalize(filter)); | ||
if (typeof args != 'undefined') { | ||
this[TRIGGER].apply(null, [filter].concat(args)) | ||
this[TRIGGER].apply(null, [filter].concat(args)); | ||
return routeFound = true // exit from loop | ||
} | ||
}, this) | ||
} | ||
}, this); | ||
}; | ||
@@ -411,11 +389,11 @@ /** | ||
prot.r = function(filter, action) { | ||
if (filter != '@') { | ||
filter = '/' + normalize(filter) | ||
this.$.push(filter) | ||
if (filter !== '@') { | ||
filter = '/' + normalize(filter); | ||
this.$.push(filter); | ||
} | ||
this.on(filter, action) | ||
} | ||
this.on(filter, action); | ||
}; | ||
var mainRouter = new Router() | ||
var route = mainRouter.m.bind(mainRouter) | ||
var mainRouter = new Router(); | ||
var route = mainRouter.m.bind(mainRouter); | ||
@@ -427,9 +405,9 @@ /** | ||
route.create = function() { | ||
var newSubRouter = new Router() | ||
var newSubRouter = new Router(); | ||
// assign sub-router's main method | ||
var router = newSubRouter.m.bind(newSubRouter) | ||
var router = newSubRouter.m.bind(newSubRouter); | ||
// stop only this sub-router | ||
router.stop = newSubRouter.s.bind(newSubRouter) | ||
router.stop = newSubRouter.s.bind(newSubRouter); | ||
return router | ||
} | ||
}; | ||
@@ -441,10 +419,10 @@ /** | ||
route.base = function(arg) { | ||
base = arg || '#' | ||
current = getPathFromBase() // recalculate current path | ||
} | ||
base = arg || '#'; | ||
current = getPathFromBase(); // recalculate current path | ||
}; | ||
/** Exec routing right now **/ | ||
route.exec = function() { | ||
emit(true) | ||
} | ||
emit(true); | ||
}; | ||
@@ -459,8 +437,8 @@ /** | ||
// reset parser for testing... | ||
parser = DEFAULT_PARSER | ||
secondParser = DEFAULT_SECOND_PARSER | ||
parser = DEFAULT_PARSER; | ||
secondParser = DEFAULT_SECOND_PARSER; | ||
} | ||
if (fn) parser = fn | ||
if (fn2) secondParser = fn2 | ||
} | ||
if (fn) { parser = fn; } | ||
if (fn2) { secondParser = fn2; } | ||
}; | ||
@@ -472,7 +450,7 @@ /** | ||
route.query = function() { | ||
var q = {} | ||
var href = loc.href || current | ||
href[REPLACE](/[?&](.+?)=([^&]*)/g, function(_, k, v) { q[k] = v }) | ||
var q = {}; | ||
var href = loc.href || current; | ||
href[REPLACE](/[?&](.+?)=([^&]*)/g, function(_, k, v) { q[k] = v; }); | ||
return q | ||
} | ||
}; | ||
@@ -483,10 +461,10 @@ /** Stop routing **/ | ||
if (win) { | ||
win[REMOVE_EVENT_LISTENER](POPSTATE, debouncedEmit) | ||
win[REMOVE_EVENT_LISTENER](HASHCHANGE, debouncedEmit) | ||
doc[REMOVE_EVENT_LISTENER](clickEvent, click) | ||
win[REMOVE_EVENT_LISTENER](POPSTATE, debouncedEmit); | ||
win[REMOVE_EVENT_LISTENER](HASHCHANGE, debouncedEmit); | ||
doc[REMOVE_EVENT_LISTENER](clickEvent, click); | ||
} | ||
central[TRIGGER]('stop') | ||
started = false | ||
central[TRIGGER]('stop'); | ||
started = false; | ||
} | ||
} | ||
}; | ||
@@ -500,18 +478,19 @@ /** | ||
if (win) { | ||
if (document.readyState == 'complete') start(autoExec) | ||
if (document.readyState === 'complete') { start(autoExec); } | ||
// the timeout is needed to solve | ||
// a weird safari bug https://github.com/riot/route/issues/33 | ||
else win[ADD_EVENT_LISTENER]('load', function() { | ||
setTimeout(function() { start(autoExec) }, 1) | ||
}) | ||
else { win[ADD_EVENT_LISTENER]('load', function() { | ||
setTimeout(function() { start(autoExec); }, 1); | ||
}); } | ||
} | ||
started = true | ||
started = true; | ||
} | ||
} | ||
}; | ||
/** Prepare the router **/ | ||
route.base() | ||
route.parser() | ||
route.base(); | ||
route.parser(); | ||
window.route = route | ||
})(); | ||
return route; | ||
}()); |
@@ -1,1 +0,1 @@ | ||
(function(){"use strict";var e=function(e){e=e||{};var t={},n=Array.prototype.slice;function i(e,t){var n=e.split(" "),i=n.length,r=0;for(;r<i;r++){var f=n[r];if(f)t(f,r)}}Object.defineProperties(e,{on:{value:function(n,r){if(typeof r!="function")return e;i(n,function(e,n){(t[e]=t[e]||[]).push(r);r.typed=n>0});return e},enumerable:false,writable:false,configurable:false},off:{value:function(n,r){if(n=="*"&&!r)t={};else{i(n,function(e,n){if(r){var i=t[e];for(var f=0,u;u=i&&i[f];++f){if(u==r)i.splice(f--,1)}}else delete t[e]})}return e},enumerable:false,writable:false,configurable:false},one:{value:function(t,n){function i(){e.off(t,i);n.apply(e,arguments)}return e.on(t,i)},enumerable:false,writable:false,configurable:false},trigger:{value:function(r){var f=arguments.length-1,u=new Array(f),o;for(var a=0;a<f;a++){u[a]=arguments[a+1]}i(r,function(i,r){o=n.call(t[i]||[],0);for(var f=0,a;a=o[f];++f){if(a.busy)continue;a.busy=1;a.apply(e,a.typed?[i].concat(u):u);if(o[f]!==a){f--}a.busy=0}if(t["*"]&&i!="*")e.trigger.apply(e,["*",i].concat(u))});return e},enumerable:false,writable:false,configurable:false}});return e};var t=/^.+?\/\/+[^\/]+/,n="EventListener",i="remove"+n,r="add"+n,f="hasAttribute",u="replace",o="popstate",a="hashchange",s="trigger",l=3,c=typeof window!="undefined"&&window,h=typeof document!="undefined"&&document,p=c&&history,d=c&&(p.location||c.location),v=j.prototype,b=h&&h.ontouchstart?"touchstart":"click",m=false,y=e(),g=false,w,$,A,x,K,N=[],O=0;function S(e){return e.split(/[\/?#]/)}function T(e,t){var n=new RegExp("^"+t[u](/\*/g,"([^/?#]+?)")[u](/\.\./,".*")+"$"),i=e.match(n);if(i)return i.slice(1)}function E(e,t){var n;return function(){clearTimeout(n);n=setTimeout(e,t)}}function P(e){w=E(R,1);c[r](o,w);c[r](a,w);h[r](b,_);if(e)R(true)}function j(){this.$=[];e(this);y.on("stop",this.s.bind(this));y.on("emit",this.e.bind(this))}function k(e){return e[u](/^\/|\/$/,"")}function q(e){return typeof e=="string"}function D(e){return(e||d.href)[u](t,"")}function L(e){return $[0]=="#"?(e||d.href||"").split($)[1]||"":(d?D(e):e||"")[u]($,"")}function R(e){var t=O==0,n;if(l<=O)return;O++;N.push(function(){var t=L();if(e||t!=A){y[s]("emit",t);A=t}});if(t){while(n=N.shift())n();O=0}}function _(e){if(e.which!=1||e.metaKey||e.ctrlKey||e.shiftKey||e.defaultPrevented)return;var n=e.target;while(n&&n.nodeName!="A")n=n.parentNode;if(!n||n.nodeName!="A"||n[f]("download")||!n[f]("href")||n.target&&n.target!="_self"||n.href.indexOf(d.href.match(t)[0])==-1)return;if(n.href!=d.href&&(n.href.split("#")[0]==d.href.split("#")[0]||$[0]!="#"&&D(n.href).indexOf($)!==0||$[0]=="#"&&n.href.split($)[0]!=d.href.split($)[0]||!z(L(n.href),n.title||h.title)))return;e.preventDefault()}function z(e,t,n){if(!p)return y[s]("emit",L(e));e=$+k(e);t=t||h.title;n?p.replaceState(null,t,e):p.pushState(null,t,e);h.title=t;g=false;R();return g}v.m=function(e,t,n){if(q(e)&&(!t||q(t)))z(e,t,n||false);else if(t)this.r(e,t);else this.r("@",e)};v.s=function(){this.off("*");this.$=[]};v.e=function(e){this.$.concat("@").some(function(t){var n=(t=="@"?x:K)(k(e),k(t));if(typeof n!="undefined"){this[s].apply(null,[t].concat(n));return g=true}},this)};v.r=function(e,t){if(e!="@"){e="/"+k(e);this.$.push(e)}this.on(e,t)};var B=new j;var C=B.m.bind(B);C.create=function(){var e=new j;var t=e.m.bind(e);t.stop=e.s.bind(e);return t};C.base=function(e){$=e||"#";A=L()};C.exec=function(){R(true)};C.parser=function(e,t){if(!e&&!t){x=S;K=T}if(e)x=e;if(t)K=t};C.query=function(){var e={};var t=d.href||A;t[u](/[?&](.+?)=([^&]*)/g,function(t,n,i){e[n]=i});return e};C.stop=function(){if(m){if(c){c[i](o,w);c[i](a,w);h[i](b,_)}y[s]("stop");m=false}};C.start=function(e){if(!m){if(c){if(document.readyState=="complete")P(e);else c[r]("load",function(){setTimeout(function(){P(e)},1)})}m=true}};C.base();C.parser();window.route=C})(); | ||
var route=function(){"use strict";var e=function(e){e=e||{};var t={},r=Array.prototype.slice;Object.defineProperties(e,{on:{value:function(r,n){if(typeof n=="function"){(t[r]=t[r]||[]).push(n)}return e},enumerable:false,writable:false,configurable:false},off:{value:function(r,n){if(r=="*"&&!n){t={}}else{if(n){var i=t[r];for(var a=0,f;f=i&&i[a];++a){if(f==n){i.splice(a--,1)}}}else{delete t[r]}}return e},enumerable:false,writable:false,configurable:false},one:{value:function(t,r){function n(){e.off(t,n);r.apply(e,arguments)}return e.on(t,n)},enumerable:false,writable:false,configurable:false},trigger:{value:function(n){var i=arguments;var a=arguments.length-1,f=new Array(a),u,o,l;for(l=0;l<a;l++){f[l]=i[l+1]}u=r.call(t[n]||[],0);for(l=0;o=u[l];++l){o.apply(e,f)}if(t["*"]&&n!="*"){e.trigger.apply(e,["*",n].concat(f))}return e},enumerable:false,writable:false,configurable:false}});return e};var t=/^.+?\/\/+[^\/]+/;var r="EventListener";var n="remove"+r;var i="add"+r;var a="hasAttribute";var f="replace";var u="popstate";var o="hashchange";var l="trigger";var s=3;var c=typeof window!="undefined"&&window;var v=typeof document!="undefined"&&document;var h=c&&history;var p=c&&(h.location||c.location);var d=j.prototype;var m=v&&v.ontouchstart?"touchstart":"click";var b=e();var g=false;var y=false;var w;var $;var A;var x;var K;var N=[];var O=0;function S(e){return e.split(/[\/?#]/)}function T(e,t){var r=new RegExp("^"+t[f](/\*/g,"([^/?#]+?)")[f](/\.\./,".*")+"$"),n=e.match(r);if(n){return n.slice(1)}}function E(e,t){var r;return function(){clearTimeout(r);r=setTimeout(e,t)}}function P(e){w=E(R,1);c[i](u,w);c[i](o,w);v[i](m,_);if(e){R(true)}}function j(){this.$=[];e(this);b.on("stop",this.s.bind(this));b.on("emit",this.e.bind(this))}function k(e){return e[f](/^\/|\/$/,"")}function q(e){return typeof e=="string"}function D(e){return(e||p.href)[f](t,"")}function L(e){return $[0]==="#"?(e||p.href||"").split($)[1]||"":(p?D(e):e||"")[f]($,"")}function R(e){var t=O===0;if(s<=O){return}O++;N.push(function(){var t=L();if(e||t!==A){b[l]("emit",t);A=t}});if(t){var r;while(r=N.shift()){r()}O=0}}function _(e){if(e.which!==1||e.metaKey||e.ctrlKey||e.shiftKey||e.defaultPrevented){return}var r=e.target;while(r&&r.nodeName!=="A"){r=r.parentNode}if(!r||r.nodeName!=="A"||r[a]("download")||!r[a]("href")||r.target&&r.target!=="_self"||r.href.indexOf(p.href.match(t)[0])===-1){return}if(r.href!==p.href&&(r.href.split("#")[0]===p.href.split("#")[0]||$[0]!=="#"&&D(r.href).indexOf($)!==0||$[0]==="#"&&r.href.split($)[0]!==p.href.split($)[0]||!z(L(r.href),r.title||v.title))){return}e.preventDefault()}function z(e,t,r){if(!h){return b[l]("emit",L(e))}e=$+k(e);t=t||v.title;r?h.replaceState(null,t,e):h.pushState(null,t,e);v.title=t;y=false;R();return y}d.m=function(e,t,r){if(q(e)&&(!t||q(t))){z(e,t,r||false)}else if(t){this.r(e,t)}else{this.r("@",e)}};d.s=function(){this.off("*");this.$=[]};d.e=function(e){this.$.concat("@").some(function(t){var r=(t==="@"?x:K)(k(e),k(t));if(typeof r!="undefined"){this[l].apply(null,[t].concat(r));return y=true}},this)};d.r=function(e,t){if(e!=="@"){e="/"+k(e);this.$.push(e)}this.on(e,t)};var B=new j;var C=B.m.bind(B);C.create=function(){var e=new j;var t=e.m.bind(e);t.stop=e.s.bind(e);return t};C.base=function(e){$=e||"#";A=L()};C.exec=function(){R(true)};C.parser=function(e,t){if(!e&&!t){x=S;K=T}if(e){x=e}if(t){K=t}};C.query=function(){var e={};var t=p.href||A;t[f](/[?&](.+?)=([^&]*)/g,function(t,r,n){e[r]=n});return e};C.stop=function(){if(g){if(c){c[n](u,w);c[n](o,w);v[n](m,_)}b[l]("stop");g=false}};C.start=function(e){if(!g){if(c){if(document.readyState==="complete"){P(e)}else{c[i]("load",function(){setTimeout(function(){P(e)},1)})}}g=true}};C.base();C.parser();return C}(); |
@@ -1,3 +0,21 @@ | ||
# Router API | ||
# Introduction | ||
The default riot.js bundle does not contain any router allowing you to pick any library that fits better to your needs. | ||
However we have developed and maintain `riot-route`, a small router library that could be used also as standalone module and fits perfectly to the minimal riot philosophy. | ||
If you want to use `riot-route` in your project you just need to include it either adding via `<script>` tag: | ||
```html | ||
<script src="path/to/dist/route.js"></script> | ||
``` | ||
Or if you are using es6 syntax you could do: | ||
```js | ||
import route from 'riot-route' // var route = require('riot-route') is also ok | ||
``` | ||
# API | ||
The Riot Router is the minimal router implementation with such technologies: | ||
@@ -4,0 +22,0 @@ |
@@ -0,1 +1,3 @@ | ||
'use strict' | ||
/** | ||
@@ -6,5 +8,5 @@ * Simple client-side router | ||
var observable = require('riot-observable') | ||
import observable from 'riot-observable' | ||
var RE_ORIGIN = /^.+?\/\/+[^\/]+/, | ||
const RE_ORIGIN = /^.+?\/\/+[^\/]+/, | ||
EVENT_LISTENER = 'EventListener', | ||
@@ -25,7 +27,14 @@ REMOVE_EVENT_LISTENER = 'remove' + EVENT_LISTENER, | ||
clickEvent = doc && doc.ontouchstart ? 'touchstart' : 'click', | ||
central = observable() | ||
let | ||
started = false, | ||
central = observable(), | ||
routeFound = false, | ||
debouncedEmit, | ||
base, current, parser, secondParser, emitStack = [], emitStackLevel = 0 | ||
base, | ||
current, | ||
parser, | ||
secondParser, | ||
emitStack = [], | ||
emitStackLevel = 0 | ||
@@ -48,3 +57,3 @@ /** | ||
function DEFAULT_SECOND_PARSER(path, filter) { | ||
var re = new RegExp('^' + filter[REPLACE](/\*/g, '([^/?#]+?)')[REPLACE](/\.\./, '.*') + '$'), | ||
const re = new RegExp('^' + filter[REPLACE](/\*/g, '([^/?#]+?)')[REPLACE](/\.\./, '.*') + '$'), | ||
args = path.match(re) | ||
@@ -62,3 +71,3 @@ | ||
function debounce(fn, delay) { | ||
var t | ||
let t | ||
return function () { | ||
@@ -115,3 +124,3 @@ clearTimeout(t) | ||
function getPathFromBase(href) { | ||
return base[0] == '#' | ||
return base[0] === '#' | ||
? (href || loc.href || '').split(base)[1] || '' | ||
@@ -123,3 +132,3 @@ : (loc ? getPathFromRoot(href) : href || '')[REPLACE](base, '') | ||
// the stack is needed for redirections | ||
var isRoot = emitStackLevel == 0, first | ||
const isRoot = emitStackLevel === 0 | ||
if (MAX_EMIT_STACK_LEVEL <= emitStackLevel) return | ||
@@ -129,4 +138,4 @@ | ||
emitStack.push(function() { | ||
var path = getPathFromBase() | ||
if (force || path != current) { | ||
const path = getPathFromBase() | ||
if (force || path !== current) { | ||
central[TRIGGER]('emit', path) | ||
@@ -137,2 +146,3 @@ current = path | ||
if (isRoot) { | ||
let first | ||
while (first = emitStack.shift()) first() // stack increses within this call | ||
@@ -145,3 +155,3 @@ emitStackLevel = 0 | ||
if ( | ||
e.which != 1 // not left click | ||
e.which !== 1 // not left click | ||
|| e.metaKey || e.ctrlKey || e.shiftKey // or meta keys | ||
@@ -151,18 +161,18 @@ || e.defaultPrevented // or default prevented | ||
var el = e.target | ||
while (el && el.nodeName != 'A') el = el.parentNode | ||
let el = e.target | ||
while (el && el.nodeName !== 'A') el = el.parentNode | ||
if ( | ||
!el || el.nodeName != 'A' // not A tag | ||
!el || el.nodeName !== 'A' // not A tag | ||
|| el[HAS_ATTRIBUTE]('download') // has download attr | ||
|| !el[HAS_ATTRIBUTE]('href') // has no href attr | ||
|| el.target && el.target != '_self' // another window or frame | ||
|| el.href.indexOf(loc.href.match(RE_ORIGIN)[0]) == -1 // cross origin | ||
|| el.target && el.target !== '_self' // another window or frame | ||
|| el.href.indexOf(loc.href.match(RE_ORIGIN)[0]) === -1 // cross origin | ||
) return | ||
if (el.href != loc.href | ||
if (el.href !== loc.href | ||
&& ( | ||
el.href.split('#')[0] == loc.href.split('#')[0] // internal jump | ||
|| base[0] != '#' && getPathFromRoot(el.href).indexOf(base) !== 0 // outside of base | ||
|| base[0] == '#' && el.href.split(base)[0] != loc.href.split(base)[0] // outside of #base | ||
el.href.split('#')[0] === loc.href.split('#')[0] // internal jump | ||
|| base[0] !== '#' && getPathFromRoot(el.href).indexOf(base) !== 0 // outside of base | ||
|| base[0] === '#' && el.href.split(base)[0] !== loc.href.split(base)[0] // outside of #base | ||
|| !go(getPathFromBase(el.href), el.title || doc.title) // route not found | ||
@@ -229,3 +239,3 @@ )) return | ||
this.$.concat('@').some(function(filter) { | ||
var args = (filter == '@' ? parser : secondParser)(normalize(path), normalize(filter)) | ||
const args = (filter === '@' ? parser : secondParser)(normalize(path), normalize(filter)) | ||
if (typeof args != 'undefined') { | ||
@@ -244,3 +254,3 @@ this[TRIGGER].apply(null, [filter].concat(args)) | ||
prot.r = function(filter, action) { | ||
if (filter != '@') { | ||
if (filter !== '@') { | ||
filter = '/' + normalize(filter) | ||
@@ -252,4 +262,4 @@ this.$.push(filter) | ||
var mainRouter = new Router() | ||
var route = mainRouter.m.bind(mainRouter) | ||
const mainRouter = new Router() | ||
const route = mainRouter.m.bind(mainRouter) | ||
@@ -261,5 +271,5 @@ /** | ||
route.create = function() { | ||
var newSubRouter = new Router() | ||
const newSubRouter = new Router() | ||
// assign sub-router's main method | ||
var router = newSubRouter.m.bind(newSubRouter) | ||
const router = newSubRouter.m.bind(newSubRouter) | ||
// stop only this sub-router | ||
@@ -304,4 +314,4 @@ router.stop = newSubRouter.s.bind(newSubRouter) | ||
route.query = function() { | ||
var q = {} | ||
var href = loc.href || current | ||
const q = {} | ||
const href = loc.href || current | ||
href[REPLACE](/[?&](.+?)=([^&]*)/g, function(_, k, v) { q[k] = v }) | ||
@@ -331,3 +341,3 @@ return q | ||
if (win) { | ||
if (document.readyState == 'complete') start(autoExec) | ||
if (document.readyState === 'complete') start(autoExec) | ||
// the timeout is needed to solve | ||
@@ -347,2 +357,2 @@ // a weird safari bug https://github.com/riot/route/issues/33 | ||
module.exports = route | ||
export default route |
{ | ||
"name": "riot-route", | ||
"version": "2.5.0", | ||
"version": "3.0.0", | ||
"description": "Simple isomorphic router", | ||
"main": "lib/index.js", | ||
"jsnext:main": "dist/es6.route.js", | ||
"main": "dist/cjs.route.js", | ||
"jsnext:main": "lib/index.js", | ||
"directories": { | ||
@@ -12,5 +12,15 @@ "lib": "lib", | ||
"scripts": { | ||
"pretest": "make build", | ||
"test": "make test", | ||
"prepublish": "make build" | ||
"pretest": "npm run build", | ||
"test": "npm run eslint && npm run karma && npm run mocha", | ||
"prepublish": "npm run build", | ||
"build": "npm run rollup && npm run uglify && npm run uglify-amd", | ||
"rollup": "node rollup.js", | ||
"uglify": "uglifyjs dist/route.js --comments --mangle -o dist/route.min.js", | ||
"uglify-amd": "uglifyjs dist/amd.route.js --comments --mangle -o dist/amd.route.min.js", | ||
"watch": "chokidar lib/* lib/**/* -c 'npm run build'", | ||
"eslint": "eslint lib test/specs", | ||
"karma": "karma start test/karma.conf.js", | ||
"karma-bs": "BROWSERSTACK=1 karma start test/karma.conf.js", | ||
"mocha": "mocha test/specs/server.specs.js", | ||
"coveralls": "RIOT_COV=1 cat ./coverage/lcov.info ./coverage/report-lcov/lcov.info | coveralls" | ||
}, | ||
@@ -26,18 +36,21 @@ "repository": { | ||
"dependencies": { | ||
"riot-observable": "^2.5.0" | ||
"riot-observable": "^3.0.0" | ||
}, | ||
"devDependencies": { | ||
"chokidar-cli": "^1.2.0", | ||
"coveralls": "^2.11.11", | ||
"electron-prebuilt": "^1.3.1", | ||
"eslint": "^3.1.1", | ||
"coveralls": "^2.11.15", | ||
"electron-prebuilt": "^1.3.9", | ||
"eslint": "^3.10.2", | ||
"expect.js": "^0.3.1", | ||
"karma": "^1.1.1", | ||
"karma-browserstack-launcher": "^1.0.1", | ||
"karma": "^1.3.0", | ||
"karma-browserstack-launcher": "^1.1.1", | ||
"karma-coverage": "^1.1.1", | ||
"karma-electron": "^4.0.0", | ||
"karma-mocha": "^1.1.1", | ||
"karma-mocha-reporter": "^2.0.4", | ||
"mocha": "^2.5.3", | ||
"uglify-js": "^2.7.0" | ||
"karma-electron": "^5.1.1", | ||
"karma-mocha": "^1.3.0", | ||
"karma-mocha-reporter": "^2.2.1", | ||
"mocha": "^3.1.2", | ||
"rollup": "^0.36.3", | ||
"rollup-plugin-buble": "^0.14.0", | ||
"rollup-plugin-node-resolve": "^2.0.0", | ||
"uglify-js": "^2.7.4" | ||
}, | ||
@@ -44,0 +57,0 @@ "author": "Muut, Inc. and other contributors", |
@@ -1,10 +0,7 @@ | ||
[![Build Status][travis-image]][travis-url] | ||
[![Code Quality][codeclimate-image]][codeclimate-url] | ||
[![NPM version][npm-version-image]][npm-url] | ||
[![NPM downloads][npm-downloads-image]][npm-url] | ||
[![MIT License][license-image]][license-url] | ||
[![Coverage Status][coverage-image]][coverage-url] | ||
# Riot Router | ||
[![Build Status][travis-image]][travis-url] [![Code Quality][codeclimate-image]][codeclimate-url] [![NPM version][npm-version-image]][npm-url] [![NPM downloads][npm-downloads-image]][npm-url] [![MIT License][license-image]][license-url] [![Coverage Status][coverage-image]][coverage-url] | ||
> Simple client-side router | ||
The Riot Router is the minimal router implementation with such technologies: | ||
@@ -17,29 +14,30 @@ | ||
A part of Riot.js, but it also works without Riot.js. | ||
It started as a part of Riot.js, but now it becomes an independent library. It works with or without Riot.js. | ||
## Documentation | ||
## Table of Contents | ||
- [API (latest)](doc/) | ||
- [Install](#install) | ||
- [Usage](#usage) | ||
- [Demos](#demos) | ||
- [Contribute](#contribute) | ||
- [License](#license) | ||
See also riotjs.com: | ||
## Install | ||
- [API (English)](http://riotjs.com/api/route/) | ||
- [API (Japanese)](http://riotjs.com/ja/api/route/) | ||
We have 4 editions: | ||
## Downloads | ||
edition | target | file | via | ||
:-- | :-- | :-- | :-- | ||
**Standalone** | `<script>` tag | `dist/route.min.js` | [jsdelivr](https://www.jsdelivr.com/?query=riot-route) ⋅ Bower ⋅ [download](https://raw.githubusercontent.com/riot/route/master/dist/route.min.js) | ||
**AMD** | [RequireJS](http://requirejs.org/) | `dist/amd.route.min.js` | [jsdelivr](https://www.jsdelivr.com/?query=riot-route) ⋅ Bower ⋅ [download](https://raw.githubusercontent.com/riot/route/master/dist/amd.route.min.js) | ||
**CommonJS** | [Browserify](http://browserify.org/), [webpack](https://webpack.github.io/) | `dist/cjs.route.js` | [npm](https://www.npmjs.com/package/riot-route) | ||
**ES module** | [Rollup](http://rollupjs.org/) | `lib/index.js` | [npm](https://www.npmjs.com/package/riot-route) | ||
We have 3 editions: | ||
### jsdelivr | ||
- **Standalone**: | ||
- [route.js](https://raw.githubusercontent.com/riot/route/master/dist/route.js) | ||
- [route.min.js](https://raw.githubusercontent.com/riot/route/master/dist/route.min.js) | ||
- **AMD**: | ||
- *for RequireJS* | ||
- [amd.route.js](https://raw.githubusercontent.com/riot/route/master/dist/amd.route.js) | ||
- [amd.route.min.js](https://raw.githubusercontent.com/riot/route/master/dist/amd.route.min.js) | ||
- **CommonJS** | ||
- *for Browserify, Webpack, ...etc* | ||
- download via npm | ||
```html | ||
<script src="https://cdn.jsdelivr.net/riot-route/x.x.x/route.min.js"></script> | ||
``` | ||
## Installation | ||
*Note*: change the part `x.x.x` to the version numbers what you want to use: ex. `2.5.0` or `3.0.0`. | ||
@@ -58,2 +56,13 @@ ### npm | ||
### Download by yourself | ||
- [Standalone](https://raw.githubusercontent.com/riot/route/master/dist/route.min.js) | ||
- [AMD](https://raw.githubusercontent.com/riot/route/master/dist/amd.route.min.js) | ||
## Usage | ||
- [API Documentation (latest)](doc/) | ||
See also [riotjs.com](http://riotjs.com/api/route/). | ||
## Demos | ||
@@ -64,9 +73,15 @@ | ||
## Development | ||
## Contribute | ||
Feel free to dive in! [Open an issue](https://github.com/riot/route/issues) or submit PRs. | ||
- `$ npm install` to setup | ||
- `$ make build` to build it once | ||
- `$ make watch` to watch and build it continuously | ||
- `$ npm run build` to build it once | ||
- `$ npm run watch` to watch and build it continuously | ||
- `$ npm test` to test | ||
## License | ||
MIT (c) Muut, Inc. and other contributors | ||
[travis-image]:https://img.shields.io/travis/riot/observable.svg?style=flat-square | ||
@@ -73,0 +88,0 @@ [travis-url]:https://travis-ci.org/riot/route |
@@ -61,3 +61,3 @@ /* eslint-disable */ | ||
'device' : 'iPhone 6', | ||
'os_version': '8.0', | ||
'os_version': '8.3', | ||
'os': 'ios' | ||
@@ -72,2 +72,2 @@ }, | ||
} | ||
} | ||
} |
@@ -31,3 +31,3 @@ function fireEvent(node, eventName) { | ||
var counter = 0, $, $$ | ||
var counter = 0, $, $$, html | ||
@@ -342,3 +342,3 @@ before(function() { | ||
}) | ||
route(function(first) { | ||
route(function() { | ||
counter++ | ||
@@ -432,7 +432,6 @@ }) | ||
it('redirecting inside the router', function() { | ||
var str | ||
route.base('/') | ||
route(function(first) { | ||
counter++ | ||
if (first == 'fruit') route('/vegitable') | ||
if (first === 'fruit') route('/vegitable') | ||
}) | ||
@@ -445,10 +444,9 @@ route('fruit') | ||
it('too many redirection', function() { | ||
var str | ||
route.base('/') | ||
route(function(first) { | ||
counter++ | ||
if (first == 'one') route('/two') | ||
if (first == 'two') route('/three') | ||
if (first == 'three') route('/four') | ||
if (first == 'four') route('/five') | ||
if (first === 'one') route('/two') | ||
if (first === 'two') route('/three') | ||
if (first === 'three') route('/four') | ||
if (first === 'four') route('/five') | ||
}) | ||
@@ -455,0 +453,0 @@ route('one') |
@@ -1,2 +0,2 @@ | ||
var route = require('../../lib/index') | ||
var route = require('../../') | ||
var expect = require('expect.js') | ||
@@ -3,0 +3,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
99
86899
16
31
2114
+ Addedriot-observable@3.0.0(transitive)
- Removedriot-observable@2.5.0(transitive)
Updatedriot-observable@^3.0.0