define(["dom"],function(dom){"use strict";var running,prevContext,prevPageContext,location="undefined"!=typeof window&&(window.history.location||window.location),dispatch=!0,base="",hashbang=!1,allRoutes=[];function page(path,routeInfo,fn){"function"==typeof fn?(page.callbacks[path.toUpperCase()]={routeInfo:routeInfo,fn:fn},allRoutes.push(routeInfo)):page.start(path)}page.getRoutes=function(){return allRoutes},page.callbacks={},page.current="",page.base=function(path){if(0===arguments.length)return base;base=path};var loaded="complete"===document.readyState;function onpopstate(e){if(loaded&&!function(event){var state=event.state||{};return!1!==previousPopState.navigate?(previousPopState=state,!1):(previousPopState=state,!0)}(e))if(e.state){var path=e.state.path;page.replace(path,e.state,null,null,!0)}else page.show(location.pathname+location.hash,void 0,void 0,!1,!0)}function decodeURLEncodedURIComponent(val){return"string"!=typeof val?val:decodeURIComponent(val.replace(/\+/g," "))}function Context(path,state){"/"===path[0]&&0!==path.indexOf(base)&&(path=base+(hashbang?"#!":"")+path);var i=path.indexOf("?");if(this.canonicalPath=path,this.path=path.replace(base,"")||"/",hashbang&&(this.path=this.path.replace("#!","")||"/"),this.title=document.title,this.state=state||{},this.state.path=path,this.querystring=~i?decodeURLEncodedURIComponent(path.slice(i+1)):"",this.pathname=decodeURLEncodedURIComponent(~i?path.slice(0,i):path),this.hash="",!hashbang){if(!~this.path.indexOf("#"))return;var parts=this.path.split("#");this.path=parts[0],this.hash=decodeURLEncodedURIComponent(parts[1])||"",this.querystring=this.querystring.split("#")[0]}}dom.addEventListener(window,"load",function(){setTimeout(function(){loaded=!0},0)},{once:!0}),page.start=function(options){if(options=options||{},!running&&(!(running=!0)===options.dispatch&&(dispatch=!1),!1!==options.popstate&&window.addEventListener("popstate",onpopstate,!1),!0===options.hashbang&&(hashbang=!0),dispatch)){var url;if(hashbang&&~location.hash.indexOf("#!")){url=location.hash.substr(2);var href=location.href.toString();href.indexOf("?")>=href.indexOf("#!")&&(url+=location.search)}else url=location.pathname+location.search+location.hash;page.replace(url,null,!0,dispatch)}},page.show=function(path,state,dispatch,push,isBack){var ctx=new Context(path,state);return ctx.isBack=isBack,page.current=ctx.path,!1!==dispatch&&page.dispatch(ctx),!1!==ctx.handled&&!1!==push&&ctx.pushState(),ctx},page.restorePreviousState=function(){page.show((prevContext=prevPageContext).pathname,prevContext.state,!1,!0,!1)},page.back=function(path,state){history.back()},page.canGoBack=function(){return 1<history.length},page.replace=function(path,state,init,dispatch,isBack){var ctx=new Context(path,state);return ctx.isBack=isBack,page.current=ctx.path,ctx.init=init,ctx.save(),!1!==dispatch&&page.dispatch(ctx),ctx},page.getRoute=function(path){var callbacks=page.callbacks,qsIndex=path.indexOf("?"),route=callbacks[(~qsIndex?path.slice(0,qsIndex):path).toUpperCase()];return route?route.routeInfo:null},page.dispatch=function(ctx){prevPageContext=prevContext;var callbacks=page.callbacks,path=(prevContext=ctx).path;if(path===page.current){var qsIndex=path.indexOf("?"),route=callbacks[(~qsIndex?path.slice(0,qsIndex):path).toUpperCase()];return route.fn(ctx,route.routeInfo)}ctx.handled=!1},(page.Context=Context).prototype.pushState=function(){history.pushState(this.state,this.title,hashbang&&"/"!==this.path?"#!"+this.path:this.canonicalPath)},Context.prototype.save=function(){history.replaceState(this.state,this.title,hashbang&&"/"!==this.path?"#!"+this.path:this.canonicalPath)};var previousPopState={};function sameOrigin(href){var origin=location.protocol+"//"+location.hostname;return location.port&&(origin+=":"+location.port),href&&0===href.indexOf(origin)}return page.pushState=function(state,title,url){hashbang&&(url="#!"+url),history.pushState(state,title,url),previousPopState=state},page.handleAnchorClick=function(e,checkWhich){if((1===function(e){return null===(e=e||window.event).which?e.button:e.which}(e)||!1===checkWhich)&&!(e.metaKey||e.ctrlKey||e.shiftKey||e.defaultPrevented)){for(var el=e.target;el&&"A"!==el.nodeName;)el=el.parentNode;if(el&&"A"===el.nodeName&&!el.hasAttribute("download")&&"external"!==el.getAttribute("rel")){var link=el.getAttribute("href");if("#"!==link){if((hashbang||el.pathname!==location.pathname||!el.hash&&"#"!==link)&&!el.target&&sameOrigin(el.href)){var path=el.pathname+el.search+(el.hash||""),orig=path;0===path.indexOf(base)&&(path=path.substr(base.length)),hashbang&&(path=path.replace("#!","")),e.preventDefault(),page.show(orig)}}else e.preventDefault()}}},page.sameOrigin=sameOrigin,page});